From 452da1a60c752c0bc423352073798ff635fbeba0 Mon Sep 17 00:00:00 2001 From: "kernel-internal[bot]" <260533166+kernel-internal[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 19:40:18 +0000 Subject: [PATCH 1/2] CLI: Update SDK to v0.44.0 and add clipboard commands - Updated kernel-go-sdk to v0.44.0 (b03de99) - Added `browsers computer read-clipboard ` command - Added `browsers computer write-clipboard --text ` command Tested: - browsers computer write-clipboard --text "test" - browsers computer read-clipboard - browsers computer read-clipboard -o json Made-with: Cursor --- cmd/browsers.go | 82 ++++++++++++++++++++++++++++++++++++++++++++++++- go.mod | 2 +- go.sum | 4 +-- 3 files changed, 84 insertions(+), 4 deletions(-) diff --git a/cmd/browsers.go b/cmd/browsers.go index d264922..b996b6c 100644 --- a/cmd/browsers.go +++ b/cmd/browsers.go @@ -99,9 +99,11 @@ type BrowserComputerService interface { GetMousePosition(ctx context.Context, id string, opts ...option.RequestOption) (res *kernel.BrowserComputerGetMousePositionResponse, err error) MoveMouse(ctx context.Context, id string, body kernel.BrowserComputerMoveMouseParams, opts ...option.RequestOption) (err error) PressKey(ctx context.Context, id string, body kernel.BrowserComputerPressKeyParams, opts ...option.RequestOption) (err error) + ReadClipboard(ctx context.Context, id string, opts ...option.RequestOption) (res *kernel.BrowserComputerReadClipboardResponse, err error) Scroll(ctx context.Context, id string, body kernel.BrowserComputerScrollParams, opts ...option.RequestOption) (err error) SetCursorVisibility(ctx context.Context, id string, body kernel.BrowserComputerSetCursorVisibilityParams, opts ...option.RequestOption) (res *kernel.BrowserComputerSetCursorVisibilityResponse, err error) TypeText(ctx context.Context, id string, body kernel.BrowserComputerTypeTextParams, opts ...option.RequestOption) (err error) + WriteClipboard(ctx context.Context, id string, body kernel.BrowserComputerWriteClipboardParams, opts ...option.RequestOption) (err error) } // BoolFlag captures whether a boolean flag was set explicitly and its value. @@ -784,6 +786,16 @@ type BrowsersComputerBatchInput struct { ActionsJSON string } +type BrowsersComputerReadClipboardInput struct { + Identifier string + Output string +} + +type BrowsersComputerWriteClipboardInput struct { + Identifier string + Text string +} + func (b BrowsersCmd) ComputerClickMouse(ctx context.Context, in BrowsersComputerClickMouseInput) error { if b.computer == nil { pterm.Error.Println("computer service not available") @@ -1063,6 +1075,47 @@ func (b BrowsersCmd) ComputerBatch(ctx context.Context, in BrowsersComputerBatch return nil } +func (b BrowsersCmd) ComputerReadClipboard(ctx context.Context, in BrowsersComputerReadClipboardInput) error { + if in.Output != "" && in.Output != "json" { + return fmt.Errorf("unsupported --output value: use 'json'") + } + if b.computer == nil { + pterm.Error.Println("computer service not available") + return nil + } + br, err := b.browsers.Get(ctx, in.Identifier, kernel.BrowserGetParams{}) + if err != nil { + return util.CleanedUpSdkError{Err: err} + } + res, err := b.computer.ReadClipboard(ctx, br.SessionID) + if err != nil { + return util.CleanedUpSdkError{Err: err} + } + if in.Output == "json" { + enc := json.NewEncoder(os.Stdout) + enc.SetIndent("", " ") + return enc.Encode(res) + } + fmt.Println(res.Text) + return nil +} + +func (b BrowsersCmd) ComputerWriteClipboard(ctx context.Context, in BrowsersComputerWriteClipboardInput) error { + if b.computer == nil { + pterm.Error.Println("computer service not available") + return nil + } + br, err := b.browsers.Get(ctx, in.Identifier, kernel.BrowserGetParams{}) + if err != nil { + return util.CleanedUpSdkError{Err: err} + } + if err := b.computer.WriteClipboard(ctx, br.SessionID, kernel.BrowserComputerWriteClipboardParams{Text: in.Text}); err != nil { + return util.CleanedUpSdkError{Err: err} + } + pterm.Success.Println("Text written to clipboard") + return nil +} + // Replays type BrowsersReplaysListInput struct { Identifier string @@ -2415,7 +2468,16 @@ func init() { computerBatch.Flags().String("actions", "", "JSON object with actions array (e.g., {\"actions\":[{\"type\":\"click_mouse\",...}]})") _ = computerBatch.MarkFlagRequired("actions") - computerRoot.AddCommand(computerClick, computerMove, computerScreenshot, computerType, computerPressKey, computerScroll, computerDrag, computerSetCursor, computerGetMousePosition, computerBatch) + // computer read-clipboard + computerReadClipboard := &cobra.Command{Use: "read-clipboard ", Short: "Read text from the browser clipboard", Args: cobra.ExactArgs(1), RunE: runBrowsersComputerReadClipboard} + computerReadClipboard.Flags().StringP("output", "o", "", "Output format: json for raw API response") + + // computer write-clipboard + computerWriteClipboard := &cobra.Command{Use: "write-clipboard ", Short: "Write text to the browser clipboard", Args: cobra.ExactArgs(1), RunE: runBrowsersComputerWriteClipboard} + computerWriteClipboard.Flags().String("text", "", "Text to write to the clipboard") + _ = computerWriteClipboard.MarkFlagRequired("text") + + computerRoot.AddCommand(computerClick, computerMove, computerScreenshot, computerType, computerPressKey, computerScroll, computerDrag, computerSetCursor, computerGetMousePosition, computerBatch, computerReadClipboard, computerWriteClipboard) browsersCmd.AddCommand(computerRoot) // playwright @@ -3159,6 +3221,24 @@ func runBrowsersComputerBatch(cmd *cobra.Command, args []string) error { return b.ComputerBatch(cmd.Context(), BrowsersComputerBatchInput{Identifier: args[0], ActionsJSON: actionsJSON}) } +func runBrowsersComputerReadClipboard(cmd *cobra.Command, args []string) error { + client := getKernelClient(cmd) + svc := client.Browsers + output, _ := cmd.Flags().GetString("output") + + b := BrowsersCmd{browsers: &svc, computer: &svc.Computer} + return b.ComputerReadClipboard(cmd.Context(), BrowsersComputerReadClipboardInput{Identifier: args[0], Output: output}) +} + +func runBrowsersComputerWriteClipboard(cmd *cobra.Command, args []string) error { + client := getKernelClient(cmd) + svc := client.Browsers + text, _ := cmd.Flags().GetString("text") + + b := BrowsersCmd{browsers: &svc, computer: &svc.Computer} + return b.ComputerWriteClipboard(cmd.Context(), BrowsersComputerWriteClipboardInput{Identifier: args[0], Text: text}) +} + func truncateURL(url string, maxLen int) string { if len(url) <= maxLen { return url diff --git a/go.mod b/go.mod index 5752bb5..941cc50 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.1 github.com/golang-jwt/jwt/v5 v5.2.2 github.com/joho/godotenv v1.5.1 - github.com/kernel/kernel-go-sdk v0.43.0 + github.com/kernel/kernel-go-sdk v0.44.0 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c github.com/pterm/pterm v0.12.80 github.com/samber/lo v1.51.0 diff --git a/go.sum b/go.sum index f078208..d0346f8 100644 --- a/go.sum +++ b/go.sum @@ -64,8 +64,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/kernel/kernel-go-sdk v0.43.0 h1:sbvOy5rHomG+0GQfQ6Qeoli1ZXr8jl61bTporsBIzKk= -github.com/kernel/kernel-go-sdk v0.43.0/go.mod h1:EeZzSuHZVeHKxKCPUzxou2bovNGhXaz0RXrSqKNf1AQ= +github.com/kernel/kernel-go-sdk v0.44.0 h1:GQKq4UAcI4WBgl2dTXBuuiEBZE3WCSTxe1S96MDru6w= +github.com/kernel/kernel-go-sdk v0.44.0/go.mod h1:EeZzSuHZVeHKxKCPUzxou2bovNGhXaz0RXrSqKNf1AQ= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= From a0837469738dd0a7f5b43af46319ef703b0f95c8 Mon Sep 17 00:00:00 2001 From: Mason Williams Date: Fri, 20 Mar 2026 17:47:29 -0400 Subject: [PATCH 2/2] Fix FakeComputerService to implement BrowserComputerService interface Add missing ReadClipboard and WriteClipboard methods to the test fake. Made-with: Cursor --- cmd/browsers_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cmd/browsers_test.go b/cmd/browsers_test.go index 63dfbb4..e37cce1 100644 --- a/cmd/browsers_test.go +++ b/cmd/browsers_test.go @@ -701,6 +701,8 @@ type FakeComputerService struct { DragMouseFunc func(ctx context.Context, id string, body kernel.BrowserComputerDragMouseParams, opts ...option.RequestOption) error TypeTextFunc func(ctx context.Context, id string, body kernel.BrowserComputerTypeTextParams, opts ...option.RequestOption) error SetCursorVisibilityFunc func(ctx context.Context, id string, body kernel.BrowserComputerSetCursorVisibilityParams, opts ...option.RequestOption) (*kernel.BrowserComputerSetCursorVisibilityResponse, error) + ReadClipboardFunc func(ctx context.Context, id string, opts ...option.RequestOption) (*kernel.BrowserComputerReadClipboardResponse, error) + WriteClipboardFunc func(ctx context.Context, id string, body kernel.BrowserComputerWriteClipboardParams, opts ...option.RequestOption) error } func (f *FakeComputerService) Batch(ctx context.Context, id string, body kernel.BrowserComputerBatchParams, opts ...option.RequestOption) error { @@ -764,6 +766,18 @@ func (f *FakeComputerService) SetCursorVisibility(ctx context.Context, id string } return &kernel.BrowserComputerSetCursorVisibilityResponse{}, nil } +func (f *FakeComputerService) ReadClipboard(ctx context.Context, id string, opts ...option.RequestOption) (*kernel.BrowserComputerReadClipboardResponse, error) { + if f.ReadClipboardFunc != nil { + return f.ReadClipboardFunc(ctx, id, opts...) + } + return &kernel.BrowserComputerReadClipboardResponse{}, nil +} +func (f *FakeComputerService) WriteClipboard(ctx context.Context, id string, body kernel.BrowserComputerWriteClipboardParams, opts ...option.RequestOption) error { + if f.WriteClipboardFunc != nil { + return f.WriteClipboardFunc(ctx, id, body, opts...) + } + return nil +} // --- Tests for Logs ---