From 4cac8f375abdead9adf6be946af79a6638cda121 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 12:38:32 +0000 Subject: [PATCH 1/3] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 710d8bd..28bf561 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 98 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-ccbe854895eb34a9562e33979f5f43cd6ad1f529d5924ee56e56f0c94dcf0454.yml -openapi_spec_hash: 2fa4ecbe742fc46fdde481188c1d885e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-652441005cba60f2ada5328d8dfc60165f6ab0bb271d6b64feca250fe73dc197.yml +openapi_spec_hash: f50a08ba2578efd8b756bdd920510c50 config_hash: dd218aae3f852dff79e77febc2077b8e From 19e11cc10d4b9331a5342152ca745d06535809c7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 18:44:38 +0000 Subject: [PATCH 2/3] feat: add batch computer action proxy endpoint --- .stats.yml | 8 +- api.md | 3 + browsercomputer.go | 285 ++++++++++++++++++++++++++++++++++++++++ browsercomputer_test.go | 97 ++++++++++++++ 4 files changed, 389 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 28bf561..91fd3b6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 98 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-652441005cba60f2ada5328d8dfc60165f6ab0bb271d6b64feca250fe73dc197.yml -openapi_spec_hash: f50a08ba2578efd8b756bdd920510c50 -config_hash: dd218aae3f852dff79e77febc2077b8e +configured_endpoints: 100 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a6d93dc291278035c96add38bb6150ec2b9ba8bbabb4676e3dbbb8444cf3b1e4.yml +openapi_spec_hash: 694bcc56d94fd0ff0d1f7b0fc1dae8ba +config_hash: 62e33cf2ed8fe0b4ceebba63367481ad diff --git a/api.md b/api.md index 95e03e0..0c0e1a9 100644 --- a/api.md +++ b/api.md @@ -171,13 +171,16 @@ Methods: Response Types: +- kernel.BrowserComputerGetMousePositionResponse - kernel.BrowserComputerSetCursorVisibilityResponse Methods: +- client.Browsers.Computer.Batch(ctx context.Context, id string, body kernel.BrowserComputerBatchParams) error - client.Browsers.Computer.CaptureScreenshot(ctx context.Context, id string, body kernel.BrowserComputerCaptureScreenshotParams) (\*http.Response, error) - client.Browsers.Computer.ClickMouse(ctx context.Context, id string, body kernel.BrowserComputerClickMouseParams) error - client.Browsers.Computer.DragMouse(ctx context.Context, id string, body kernel.BrowserComputerDragMouseParams) error +- client.Browsers.Computer.GetMousePosition(ctx context.Context, id string) (\*kernel.BrowserComputerGetMousePositionResponse, error) - client.Browsers.Computer.MoveMouse(ctx context.Context, id string, body kernel.BrowserComputerMoveMouseParams) error - client.Browsers.Computer.PressKey(ctx context.Context, id string, body kernel.BrowserComputerPressKeyParams) error - client.Browsers.Computer.Scroll(ctx context.Context, id string, body kernel.BrowserComputerScrollParams) error diff --git a/browsercomputer.go b/browsercomputer.go index 8ed7bba..9d2d806 100644 --- a/browsercomputer.go +++ b/browsercomputer.go @@ -35,6 +35,21 @@ func NewBrowserComputerService(opts ...option.RequestOption) (r BrowserComputerS return } +// Send an array of computer actions to execute in order on the browser instance. +// Execution stops on the first error. This reduces network latency compared to +// sending individual action requests. +func (r *BrowserComputerService) Batch(ctx context.Context, id string, body BrowserComputerBatchParams, 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/batch", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, nil, opts...) + return +} + // Capture a screenshot of the browser instance func (r *BrowserComputerService) CaptureScreenshot(ctx context.Context, id string, body BrowserComputerCaptureScreenshotParams, opts ...option.RequestOption) (res *http.Response, err error) { opts = slices.Concat(r.Options, opts) @@ -74,6 +89,18 @@ func (r *BrowserComputerService) DragMouse(ctx context.Context, id string, body return } +// Get the current mouse cursor position on the browser instance +func (r *BrowserComputerService) GetMousePosition(ctx context.Context, id string, opts ...option.RequestOption) (res *BrowserComputerGetMousePositionResponse, err error) { + opts = slices.Concat(r.Options, opts) + if id == "" { + err = errors.New("missing required id parameter") + return + } + path := fmt.Sprintf("browsers/%s/computer/get_mouse_position", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, nil, &res, opts...) + return +} + // Move the mouse cursor to the specified coordinates on the browser instance func (r *BrowserComputerService) MoveMouse(ctx context.Context, id string, body BrowserComputerMoveMouseParams, opts ...option.RequestOption) (err error) { opts = slices.Concat(r.Options, opts) @@ -138,6 +165,26 @@ func (r *BrowserComputerService) TypeText(ctx context.Context, id string, body B return } +type BrowserComputerGetMousePositionResponse struct { + // X coordinate of the cursor + X int64 `json:"x,required"` + // Y coordinate of the cursor + Y int64 `json:"y,required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + X respjson.Field + Y respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BrowserComputerGetMousePositionResponse) RawJSON() string { return r.JSON.raw } +func (r *BrowserComputerGetMousePositionResponse) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + // Generic OK response. type BrowserComputerSetCursorVisibilityResponse struct { // Indicates success. @@ -156,6 +203,244 @@ func (r *BrowserComputerSetCursorVisibilityResponse) UnmarshalJSON(data []byte) return apijson.UnmarshalRoot(data, r) } +type BrowserComputerBatchParams struct { + // Ordered list of actions to execute. Execution stops on the first error. + Actions []BrowserComputerBatchParamsAction `json:"actions,omitzero,required"` + paramObj +} + +func (r BrowserComputerBatchParams) MarshalJSON() (data []byte, err error) { + type shadow BrowserComputerBatchParams + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserComputerBatchParams) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// A single computer action to execute as part of a batch. The `type` field selects +// which action to perform, and the corresponding field contains the action +// parameters. Exactly one action field matching the type must be provided. +// +// The property Type is required. +type BrowserComputerBatchParamsAction struct { + // The type of action to perform. + // + // Any of "click_mouse", "move_mouse", "type_text", "press_key", "scroll", + // "drag_mouse", "set_cursor", "sleep". + Type string `json:"type,omitzero,required"` + ClickMouse BrowserComputerBatchParamsActionClickMouse `json:"click_mouse,omitzero"` + DragMouse BrowserComputerBatchParamsActionDragMouse `json:"drag_mouse,omitzero"` + MoveMouse BrowserComputerBatchParamsActionMoveMouse `json:"move_mouse,omitzero"` + PressKey BrowserComputerBatchParamsActionPressKey `json:"press_key,omitzero"` + Scroll BrowserComputerBatchParamsActionScroll `json:"scroll,omitzero"` + SetCursor BrowserComputerBatchParamsActionSetCursor `json:"set_cursor,omitzero"` + // Pause execution for a specified duration. + Sleep BrowserComputerBatchParamsActionSleep `json:"sleep,omitzero"` + TypeText BrowserComputerBatchParamsActionTypeText `json:"type_text,omitzero"` + paramObj +} + +func (r BrowserComputerBatchParamsAction) MarshalJSON() (data []byte, err error) { + type shadow BrowserComputerBatchParamsAction + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserComputerBatchParamsAction) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +func init() { + apijson.RegisterFieldValidator[BrowserComputerBatchParamsAction]( + "type", "click_mouse", "move_mouse", "type_text", "press_key", "scroll", "drag_mouse", "set_cursor", "sleep", + ) +} + +// The properties X, Y are required. +type BrowserComputerBatchParamsActionClickMouse struct { + // X coordinate of the click position + X int64 `json:"x,required"` + // Y coordinate of the click position + Y int64 `json:"y,required"` + // Number of times to repeat the click + NumClicks param.Opt[int64] `json:"num_clicks,omitzero"` + // Mouse button to interact with + // + // Any of "left", "right", "middle", "back", "forward". + Button string `json:"button,omitzero"` + // Type of click action + // + // Any of "down", "up", "click". + ClickType string `json:"click_type,omitzero"` + // Modifier keys to hold during the click + HoldKeys []string `json:"hold_keys,omitzero"` + paramObj +} + +func (r BrowserComputerBatchParamsActionClickMouse) MarshalJSON() (data []byte, err error) { + type shadow BrowserComputerBatchParamsActionClickMouse + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserComputerBatchParamsActionClickMouse) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +func init() { + apijson.RegisterFieldValidator[BrowserComputerBatchParamsActionClickMouse]( + "button", "left", "right", "middle", "back", "forward", + ) + apijson.RegisterFieldValidator[BrowserComputerBatchParamsActionClickMouse]( + "click_type", "down", "up", "click", + ) +} + +// The property Path is required. +type BrowserComputerBatchParamsActionDragMouse struct { + // Ordered list of [x, y] coordinate pairs to move through while dragging. Must + // contain at least 2 points. + Path [][]int64 `json:"path,omitzero,required"` + // Delay in milliseconds between button down and starting to move along the path. + Delay param.Opt[int64] `json:"delay,omitzero"` + // Delay in milliseconds between relative steps while dragging (not the initial + // delay). + StepDelayMs param.Opt[int64] `json:"step_delay_ms,omitzero"` + // Number of relative move steps per segment in the path. Minimum 1. + StepsPerSegment param.Opt[int64] `json:"steps_per_segment,omitzero"` + // Mouse button to drag with + // + // Any of "left", "middle", "right". + Button string `json:"button,omitzero"` + // Modifier keys to hold during the drag + HoldKeys []string `json:"hold_keys,omitzero"` + paramObj +} + +func (r BrowserComputerBatchParamsActionDragMouse) MarshalJSON() (data []byte, err error) { + type shadow BrowserComputerBatchParamsActionDragMouse + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserComputerBatchParamsActionDragMouse) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +func init() { + apijson.RegisterFieldValidator[BrowserComputerBatchParamsActionDragMouse]( + "button", "left", "middle", "right", + ) +} + +// The properties X, Y are required. +type BrowserComputerBatchParamsActionMoveMouse struct { + // X coordinate to move the cursor to + X int64 `json:"x,required"` + // Y coordinate to move the cursor to + Y int64 `json:"y,required"` + // Modifier keys to hold during the move + HoldKeys []string `json:"hold_keys,omitzero"` + paramObj +} + +func (r BrowserComputerBatchParamsActionMoveMouse) MarshalJSON() (data []byte, err error) { + type shadow BrowserComputerBatchParamsActionMoveMouse + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserComputerBatchParamsActionMoveMouse) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// The property Keys is required. +type BrowserComputerBatchParamsActionPressKey struct { + // List of key symbols to press. Each item should be a key symbol supported by + // xdotool (see X11 keysym definitions). Examples include "Return", "Shift", + // "Ctrl", "Alt", "F5". Items in this list could also be combinations, e.g. + // "Ctrl+t" or "Ctrl+Shift+Tab". + Keys []string `json:"keys,omitzero,required"` + // Duration to hold the keys down in milliseconds. If omitted or 0, keys are + // tapped. + Duration param.Opt[int64] `json:"duration,omitzero"` + // Optional modifier keys to hold during the key press sequence. + HoldKeys []string `json:"hold_keys,omitzero"` + paramObj +} + +func (r BrowserComputerBatchParamsActionPressKey) MarshalJSON() (data []byte, err error) { + type shadow BrowserComputerBatchParamsActionPressKey + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserComputerBatchParamsActionPressKey) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// The properties X, Y are required. +type BrowserComputerBatchParamsActionScroll struct { + // X coordinate at which to perform the scroll + X int64 `json:"x,required"` + // Y coordinate at which to perform the scroll + Y int64 `json:"y,required"` + // Horizontal scroll amount. Positive scrolls right, negative scrolls left. + DeltaX param.Opt[int64] `json:"delta_x,omitzero"` + // Vertical scroll amount. Positive scrolls down, negative scrolls up. + DeltaY param.Opt[int64] `json:"delta_y,omitzero"` + // Modifier keys to hold during the scroll + HoldKeys []string `json:"hold_keys,omitzero"` + paramObj +} + +func (r BrowserComputerBatchParamsActionScroll) MarshalJSON() (data []byte, err error) { + type shadow BrowserComputerBatchParamsActionScroll + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserComputerBatchParamsActionScroll) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// The property Hidden is required. +type BrowserComputerBatchParamsActionSetCursor struct { + // Whether the cursor should be hidden or visible + Hidden bool `json:"hidden,required"` + paramObj +} + +func (r BrowserComputerBatchParamsActionSetCursor) MarshalJSON() (data []byte, err error) { + type shadow BrowserComputerBatchParamsActionSetCursor + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserComputerBatchParamsActionSetCursor) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Pause execution for a specified duration. +// +// The property DurationMs is required. +type BrowserComputerBatchParamsActionSleep struct { + // Duration to sleep in milliseconds. + DurationMs int64 `json:"duration_ms,required"` + paramObj +} + +func (r BrowserComputerBatchParamsActionSleep) MarshalJSON() (data []byte, err error) { + type shadow BrowserComputerBatchParamsActionSleep + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserComputerBatchParamsActionSleep) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// The property Text is required. +type BrowserComputerBatchParamsActionTypeText struct { + // Text to type on the browser instance + Text string `json:"text,required"` + // Delay in milliseconds between keystrokes + Delay param.Opt[int64] `json:"delay,omitzero"` + paramObj +} + +func (r BrowserComputerBatchParamsActionTypeText) MarshalJSON() (data []byte, err error) { + type shadow BrowserComputerBatchParamsActionTypeText + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserComputerBatchParamsActionTypeText) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + type BrowserComputerCaptureScreenshotParams struct { Region BrowserComputerCaptureScreenshotParamsRegion `json:"region,omitzero"` paramObj diff --git a/browsercomputer_test.go b/browsercomputer_test.go index 20e699c..e39f5b5 100644 --- a/browsercomputer_test.go +++ b/browsercomputer_test.go @@ -17,6 +17,80 @@ import ( "github.com/kernel/kernel-go-sdk/option" ) +func TestBrowserComputerBatch(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.Browsers.Computer.Batch( + context.TODO(), + "id", + kernel.BrowserComputerBatchParams{ + Actions: []kernel.BrowserComputerBatchParamsAction{{ + Type: "click_mouse", + ClickMouse: kernel.BrowserComputerBatchParamsActionClickMouse{ + X: 0, + Y: 0, + Button: "left", + ClickType: "down", + HoldKeys: []string{"string"}, + NumClicks: kernel.Int(0), + }, + DragMouse: kernel.BrowserComputerBatchParamsActionDragMouse{ + Path: [][]int64{{0, 0}, {0, 0}}, + Button: "left", + Delay: kernel.Int(0), + HoldKeys: []string{"string"}, + StepDelayMs: kernel.Int(0), + StepsPerSegment: kernel.Int(1), + }, + MoveMouse: kernel.BrowserComputerBatchParamsActionMoveMouse{ + X: 0, + Y: 0, + HoldKeys: []string{"string"}, + }, + PressKey: kernel.BrowserComputerBatchParamsActionPressKey{ + Keys: []string{"string"}, + Duration: kernel.Int(0), + HoldKeys: []string{"string"}, + }, + Scroll: kernel.BrowserComputerBatchParamsActionScroll{ + X: 0, + Y: 0, + DeltaX: kernel.Int(0), + DeltaY: kernel.Int(0), + HoldKeys: []string{"string"}, + }, + SetCursor: kernel.BrowserComputerBatchParamsActionSetCursor{ + Hidden: true, + }, + Sleep: kernel.BrowserComputerBatchParamsActionSleep{ + DurationMs: 0, + }, + TypeText: kernel.BrowserComputerBatchParamsActionTypeText{ + Text: "text", + Delay: kernel.Int(0), + }, + }}, + }, + ) + if err != nil { + var apierr *kernel.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} + func TestBrowserComputerCaptureScreenshotWithOptionalParams(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) @@ -130,6 +204,29 @@ func TestBrowserComputerDragMouseWithOptionalParams(t *testing.T) { } } +func TestBrowserComputerGetMousePosition(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.Browsers.Computer.GetMousePosition(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 TestBrowserComputerMoveMouseWithOptionalParams(t *testing.T) { t.Skip("Prism tests are disabled") baseURL := "http://localhost:4010" From 869a805dfad0920b29108defd2ea09ccf44e5dfc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 18:44:56 +0000 Subject: [PATCH 3/3] release: 0.31.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 8 ++++++++ README.md | 2 +- internal/version.go | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 554e34b..f81bf99 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.30.0" + ".": "0.31.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 59f7eb0..3bb8760 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.31.0 (2026-02-06) + +Full Changelog: [v0.30.0...v0.31.0](https://github.com/kernel/kernel-go-sdk/compare/v0.30.0...v0.31.0) + +### Features + +* add batch computer action proxy endpoint ([19e11cc](https://github.com/kernel/kernel-go-sdk/commit/19e11cc10d4b9331a5342152ca745d06535809c7)) + ## 0.30.0 (2026-02-03) Full Changelog: [v0.29.0...v0.30.0](https://github.com/kernel/kernel-go-sdk/compare/v0.29.0...v0.30.0) diff --git a/README.md b/README.md index 2438978..467688c 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Or to pin the version: ```sh -go get -u 'github.com/kernel/kernel-go-sdk@v0.30.0' +go get -u 'github.com/kernel/kernel-go-sdk@v0.31.0' ``` diff --git a/internal/version.go b/internal/version.go index 7d5879c..d26ea0a 100644 --- a/internal/version.go +++ b/internal/version.go @@ -2,4 +2,4 @@ package internal -const PackageVersion = "0.30.0" // x-release-please-version +const PackageVersion = "0.31.0" // x-release-please-version