Skip to content

Commit 1a74824

Browse files
authored
feat: add --force flag to browsers update viewport resize (#131)
## Summary - Bumps `kernel-go-sdk` from v0.40.0 to v0.42.1 - Adds `--force` flag to `kernel browsers update` command - When `--force` is used with `--viewport`, the viewport resize proceeds even when a live view or recording/replay is active — active recordings are gracefully stopped and restarted as separate segments at the new resolution - Default behavior (without `--force`) is unchanged — resize is refused when a live view or recording is active Corresponds to [kernel/kernel#1407](kernel/kernel@f0caf13). <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Bumps the Kernel Go SDK and changes the shape of the `BrowserUpdateParams` viewport payload, which could affect runtime behavior/compatibility with the API. The new `--force` path explicitly alters how viewport updates are applied during active live views/recordings. > > **Overview** > **Adds forced viewport resizing for running browser sessions.** `kernel browsers update` now accepts `--force` (only valid with `--viewport`) and passes a `force=true` option in the update payload to allow resizing even when live view/recording is active. > > **Updates dependencies and tests.** Upgrades `github.com/kernel/kernel-go-sdk` to `v0.42.1`, adjusts the viewport update params type accordingly, and adds unit tests covering `--force` behavior and validation errors. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit b77a4b1. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent f64b9af commit 1a74824

File tree

4 files changed

+95
-6
lines changed

4 files changed

+95
-6
lines changed

cmd/browsers.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ type BrowsersUpdateInput struct {
207207
ProfileName string
208208
ProfileSaveChanges BoolFlag
209209
Viewport string
210+
Force bool
210211
Output string
211212
}
212213

@@ -589,6 +590,11 @@ func (b BrowsersCmd) Update(ctx context.Context, in BrowsersUpdateInput) error {
589590
return fmt.Errorf("--save-changes requires --profile-id or --profile-name")
590591
}
591592

593+
// Validate --force is only used with a viewport change
594+
if in.Force && !hasViewportChange {
595+
return fmt.Errorf("--force requires --viewport")
596+
}
597+
592598
// Validate that at least one update option is provided
593599
if !hasProxyChange && !hasProfileChange && !hasViewportChange {
594600
return fmt.Errorf("must specify at least one of: --proxy-id, --clear-proxy, --profile-id, --profile-name, or --viewport")
@@ -622,13 +628,18 @@ func (b BrowsersCmd) Update(ctx context.Context, in BrowsersUpdateInput) error {
622628
if err != nil {
623629
return fmt.Errorf("invalid viewport format: %v", err)
624630
}
625-
params.Viewport = shared.BrowserViewportParam{
626-
Width: width,
627-
Height: height,
631+
params.Viewport = kernel.BrowserUpdateParamsViewport{
632+
BrowserViewportParam: shared.BrowserViewportParam{
633+
Width: width,
634+
Height: height,
635+
},
628636
}
629637
if refreshRate > 0 {
630638
params.Viewport.RefreshRate = kernel.Opt(refreshRate)
631639
}
640+
if in.Force {
641+
params.Viewport.Force = kernel.Opt(true)
642+
}
632643
}
633644

634645
if in.Output != "json" {
@@ -2122,6 +2133,7 @@ Supported operations:
21222133
- Change or remove proxy (--proxy-id or --clear-proxy)
21232134
- Load a profile into a session that doesn't have one (--profile-id or --profile-name)
21242135
- Change viewport dimensions (--viewport)
2136+
- Force viewport resize during active live view or recording (--force with --viewport)
21252137
21262138
Note: Profiles can only be loaded into sessions that don't already have a profile.`,
21272139
Args: func(cmd *cobra.Command, args []string) error {
@@ -2159,6 +2171,7 @@ func init() {
21592171
browsersUpdateCmd.Flags().String("profile-name", "", "Profile name to load into the browser session (mutually exclusive with --profile-id)")
21602172
browsersUpdateCmd.Flags().Bool("save-changes", false, "If set, save changes back to the profile when the session ends")
21612173
browsersUpdateCmd.Flags().String("viewport", "", "Browser viewport size (e.g., 1920x1080@25). Supported: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, 1024x768@60, 1200x800@60, 1280x800@60")
2174+
browsersUpdateCmd.Flags().Bool("force", false, "Force viewport resize even when a live view or recording/replay is active")
21622175

21632176
browsersCmd.AddCommand(browsersListCmd)
21642177
browsersCmd.AddCommand(browsersCreateCmd)
@@ -2619,6 +2632,7 @@ func runBrowsersUpdate(cmd *cobra.Command, args []string) error {
26192632
profileName, _ := cmd.Flags().GetString("profile-name")
26202633
saveChanges, _ := cmd.Flags().GetBool("save-changes")
26212634
viewport, _ := cmd.Flags().GetString("viewport")
2635+
force, _ := cmd.Flags().GetBool("force")
26222636

26232637
svc := client.Browsers
26242638
b := BrowsersCmd{browsers: &svc}
@@ -2630,6 +2644,7 @@ func runBrowsersUpdate(cmd *cobra.Command, args []string) error {
26302644
ProfileName: profileName,
26312645
ProfileSaveChanges: BoolFlag{Set: cmd.Flags().Changed("save-changes"), Value: saveChanges},
26322646
Viewport: viewport,
2647+
Force: force,
26332648
Output: out,
26342649
})
26352650
}

cmd/browsers_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,3 +1242,77 @@ func TestBrowsersCreate_WithInvalidViewport(t *testing.T) {
12421242
out := outBuf.String()
12431243
assert.Contains(t, out, "Invalid viewport format")
12441244
}
1245+
1246+
func TestBrowsersUpdate_WithViewportAndForce(t *testing.T) {
1247+
setupStdoutCapture(t)
1248+
var captured kernel.BrowserUpdateParams
1249+
fake := &FakeBrowsersService{UpdateFunc: func(ctx context.Context, id string, body kernel.BrowserUpdateParams, opts ...option.RequestOption) (*kernel.BrowserUpdateResponse, error) {
1250+
captured = body
1251+
return &kernel.BrowserUpdateResponse{SessionID: "session123"}, nil
1252+
}}
1253+
b := BrowsersCmd{browsers: fake}
1254+
1255+
err := b.Update(context.Background(), BrowsersUpdateInput{
1256+
Identifier: "session123",
1257+
Viewport: "1920x1080@25",
1258+
Force: true,
1259+
})
1260+
1261+
assert.NoError(t, err)
1262+
assert.Equal(t, int64(1920), captured.Viewport.Width)
1263+
assert.Equal(t, int64(1080), captured.Viewport.Height)
1264+
assert.True(t, captured.Viewport.RefreshRate.Valid())
1265+
assert.Equal(t, int64(25), captured.Viewport.RefreshRate.Value)
1266+
assert.True(t, captured.Viewport.Force.Valid())
1267+
assert.True(t, captured.Viewport.Force.Value)
1268+
}
1269+
1270+
func TestBrowsersUpdate_WithViewportNoForce(t *testing.T) {
1271+
setupStdoutCapture(t)
1272+
var captured kernel.BrowserUpdateParams
1273+
fake := &FakeBrowsersService{UpdateFunc: func(ctx context.Context, id string, body kernel.BrowserUpdateParams, opts ...option.RequestOption) (*kernel.BrowserUpdateResponse, error) {
1274+
captured = body
1275+
return &kernel.BrowserUpdateResponse{SessionID: "session123"}, nil
1276+
}}
1277+
b := BrowsersCmd{browsers: fake}
1278+
1279+
err := b.Update(context.Background(), BrowsersUpdateInput{
1280+
Identifier: "session123",
1281+
Viewport: "1920x1080@25",
1282+
Force: false,
1283+
})
1284+
1285+
assert.NoError(t, err)
1286+
assert.Equal(t, int64(1920), captured.Viewport.Width)
1287+
assert.Equal(t, int64(1080), captured.Viewport.Height)
1288+
assert.False(t, captured.Viewport.Force.Valid())
1289+
}
1290+
1291+
func TestBrowsersUpdate_ForceWithoutViewport_Errors(t *testing.T) {
1292+
setupStdoutCapture(t)
1293+
fake := &FakeBrowsersService{}
1294+
b := BrowsersCmd{browsers: fake}
1295+
1296+
err := b.Update(context.Background(), BrowsersUpdateInput{
1297+
Identifier: "session123",
1298+
Force: true,
1299+
})
1300+
1301+
assert.Error(t, err)
1302+
assert.Contains(t, err.Error(), "--force requires --viewport")
1303+
}
1304+
1305+
func TestBrowsersUpdate_ForceWithProxyButNoViewport_Errors(t *testing.T) {
1306+
setupStdoutCapture(t)
1307+
fake := &FakeBrowsersService{}
1308+
b := BrowsersCmd{browsers: fake}
1309+
1310+
err := b.Update(context.Background(), BrowsersUpdateInput{
1311+
Identifier: "session123",
1312+
ProxyID: "proxy-123",
1313+
Force: true,
1314+
})
1315+
1316+
assert.Error(t, err)
1317+
assert.Contains(t, err.Error(), "--force requires --viewport")
1318+
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ require (
99
github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.1
1010
github.com/golang-jwt/jwt/v5 v5.2.2
1111
github.com/joho/godotenv v1.5.1
12-
github.com/kernel/kernel-go-sdk v0.40.0
12+
github.com/kernel/kernel-go-sdk v0.42.1
1313
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
1414
github.com/pterm/pterm v0.12.80
1515
github.com/samber/lo v1.51.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
6464
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
6565
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
6666
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
67-
github.com/kernel/kernel-go-sdk v0.40.0 h1:RQON4dE9HwvEcF5wM3WVKs/Om0PCH0eTDEB3iwjOvy4=
68-
github.com/kernel/kernel-go-sdk v0.40.0/go.mod h1:EeZzSuHZVeHKxKCPUzxou2bovNGhXaz0RXrSqKNf1AQ=
67+
github.com/kernel/kernel-go-sdk v0.42.1 h1:uDoMNXyfS59fkZ9laJO/qKFAysRrqdg06zNB3uLEdEk=
68+
github.com/kernel/kernel-go-sdk v0.42.1/go.mod h1:EeZzSuHZVeHKxKCPUzxou2bovNGhXaz0RXrSqKNf1AQ=
6969
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
7070
github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
7171
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=

0 commit comments

Comments
 (0)