Skip to content

Commit f87e893

Browse files
committed
feat: add --force flag to browsers update viewport resize
Bump go-sdk to v0.42.1 and expose the new `force` parameter on `PATCH /browsers/{id}` viewport updates. When `--force` is passed alongside `--viewport`, the 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. Made-with: Cursor
1 parent f64b9af commit f87e893

4 files changed

Lines changed: 75 additions & 6 deletions

File tree

cmd/browsers.go

Lines changed: 13 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

@@ -622,13 +623,18 @@ func (b BrowsersCmd) Update(ctx context.Context, in BrowsersUpdateInput) error {
622623
if err != nil {
623624
return fmt.Errorf("invalid viewport format: %v", err)
624625
}
625-
params.Viewport = shared.BrowserViewportParam{
626-
Width: width,
627-
Height: height,
626+
params.Viewport = kernel.BrowserUpdateParamsViewport{
627+
BrowserViewportParam: shared.BrowserViewportParam{
628+
Width: width,
629+
Height: height,
630+
},
628631
}
629632
if refreshRate > 0 {
630633
params.Viewport.RefreshRate = kernel.Opt(refreshRate)
631634
}
635+
if in.Force {
636+
params.Viewport.Force = kernel.Opt(true)
637+
}
632638
}
633639

634640
if in.Output != "json" {
@@ -2122,6 +2128,7 @@ Supported operations:
21222128
- Change or remove proxy (--proxy-id or --clear-proxy)
21232129
- Load a profile into a session that doesn't have one (--profile-id or --profile-name)
21242130
- Change viewport dimensions (--viewport)
2131+
- Force viewport resize during active live view or recording (--force with --viewport)
21252132
21262133
Note: Profiles can only be loaded into sessions that don't already have a profile.`,
21272134
Args: func(cmd *cobra.Command, args []string) error {
@@ -2159,6 +2166,7 @@ func init() {
21592166
browsersUpdateCmd.Flags().String("profile-name", "", "Profile name to load into the browser session (mutually exclusive with --profile-id)")
21602167
browsersUpdateCmd.Flags().Bool("save-changes", false, "If set, save changes back to the profile when the session ends")
21612168
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")
2169+
browsersUpdateCmd.Flags().Bool("force", false, "Force viewport resize even when a live view or recording/replay is active")
21622170

21632171
browsersCmd.AddCommand(browsersListCmd)
21642172
browsersCmd.AddCommand(browsersCreateCmd)
@@ -2619,6 +2627,7 @@ func runBrowsersUpdate(cmd *cobra.Command, args []string) error {
26192627
profileName, _ := cmd.Flags().GetString("profile-name")
26202628
saveChanges, _ := cmd.Flags().GetBool("save-changes")
26212629
viewport, _ := cmd.Flags().GetString("viewport")
2630+
force, _ := cmd.Flags().GetBool("force")
26222631

26232632
svc := client.Browsers
26242633
b := BrowsersCmd{browsers: &svc}
@@ -2630,6 +2639,7 @@ func runBrowsersUpdate(cmd *cobra.Command, args []string) error {
26302639
ProfileName: profileName,
26312640
ProfileSaveChanges: BoolFlag{Set: cmd.Flags().Changed("save-changes"), Value: saveChanges},
26322641
Viewport: viewport,
2642+
Force: force,
26332643
Output: out,
26342644
})
26352645
}

cmd/browsers_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,3 +1242,62 @@ 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(), "must specify at least one of")
1303+
}

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)