Skip to content

Commit 01dc4cd

Browse files
authored
feat allow to include deleted browser with pagination (#38)
## Description Upgrades kernel-go-sdk to v0.20.0 and adds support for viewing soft-deleted browser sessions via the new --include-deleted flag, which displays a Deleted At column in the output when enabled. Also adds --limit and --offset flags to the browsers list command for pagination support, and updates all code and tests to work with the SDK's new pagination-based API that returns OffsetPagination[BrowserListResponse] instead of simple arrays. ## Tested Browsers list still works compatible with past changes ```sh ./bin/kernel browsers list Browser ID | Created At | Persistent ID | Profile | CDP WS URL | Live View URL p835ki3pbs1sk9b6q1vcgibs | 2025-11-14 15:50:01 EST | my ID foo1 | - | httof idle browser instances in the pops://apte... | https://apterygial-multiflorous-magaly.ngrok-fr... ejymvj2soco5pel6av5swxc8 | 2025-11-14 15:50:16 EST | my ID bizz 1223 | - | httof idle browser instances in the pops://apte... | ``` We can paginate ```sh ./bin/kernel browsers list --limit 1 --offset 1 Browser ID | Created At | Persistent ID | Profile | CDP WS URL | Live View URL ejymvj2soco5pel6av5swxc8 | 2025-11-14 15:50:16 EST | my ID bizz 1223 | - | httof idle browser instances in the pops://apte... | ``` We can now include deleted browsers in results ```sh ./bin/kernel browsers list --include-deleted Browser ID | Created At | Persistent ID | Profile | CDP WS URL | Live View URL | Deleted At odfy1z875hwwmazk8cneelzy | 2025-10-07 10:46:40 EDT | - | - | httof idle browser instances in the pops://apte... | https://apterygial-multiflorous-magaly.ngrok-fr... | 2025-10-07 10:59:02 EDT ... mpk6qwzh16s14hye4lownrj3 | 2025-10-07 15:30:51 EDT | - | - | httof idle browser instances in the pops://apte... | https://apterygial-multiflorous-magaly.ngrok-fr... | 2025-10-07 15:31:54 EDT yeu77dw14cgoqroau0uxyv4q | 2025-10-07 15:31:20 EDT | test | - | httof idle browser instances in the pops://apte... | https://apterygial-multiflorous-magaly.ngrok-fr... | 2025-10-07 16:15:28 EDT ``` We can paginate including deleted browsers: ```sh ./bin/kernel browsers list --limit 10 --offset 2 --include-deleted Browser ID | Created At | Persistent ID | Profile | CDP WS URL | Live View URL | Deleted At y9h4g7v2lqed9dyzbs5we06z | 2025-10-07 15:12:31 EDT | - | - | httof idle browser instances in the pops://apte... | https://apterygial-multiflorous-magaly.ngrok-fr... | 2025-10-07 15:13:49 EDT ec2od894vuu0iyvrop00zre9 | 2025-10-07 15:20:19 EDT | - | - | httof idle browser instances in the pops://apte... | | 2025-10-07 15:25:22 EDT xvmidx982o0otg0snu2wddmh | 2025-10-07 15:20:32 EDT | - | - | httof idle browser instances in the pops://apte... | https://apterygial-multiflorous-magaly.ngrok-fr... | 2025-10-07 15:21:36 EDT kiopeonodwd97g6nnrs003e2 | 2025-10-07 15:20:40 EDT | - | - | httof idle browser instances in the pops://apte... | https://apterygial-multiflorous-magaly.ngrok-fr... | 2025-10-07 15:21:44 EDT ozygmi7ieaajmu3bdsh06rx8 | 2025-10-07 15:21:49 EDT | - | - | httof idle browser instances in the pops://apte... | https://apterygial-multiflorous-magaly.ngrok-fr... | 2025-10-07 15:22:57 EDT m8bkktjdf8p5yteewy798vyj | 2025-10-07 15:23:53 EDT | - | - | httof idle browser instances in the pops://apte... | https://apterygial-multiflorous-magaly.ngrok-fr... | 2025-10-07 15:24:57 EDT jcytgllgbkyr695cdlmdsznp | 2025-10-07 15:23:56 EDT | - | - | httof idle browser instances in the pops://apte... | https://apterygial-multiflorous-magaly.ngrok-fr... | 2025-10-07 15:24:59 EDT y3cngz01vcsfundzs2wi0pc8 | 2025-10-07 15:23:58 EDT | - | - | httof idle browser instances in the pops://apte... | https://apterygial-multiflorous-magaly.ngrok-fr... | 2025-10-07 15:28:51 EDT e3rmbrdi8agxsugs1ym3mx1a | 2025-10-07 15:24:01 EDT | - | - | httof idle browser instances in the pops://apte... | https://apterygial-multiflorous-magaly.ngrok-fr... | 2025-10-07 15:25:05 EDT ok1p7d4l1pqvyndv9ukmz3sp | 2025-10-07 15:27:22 EDT | - | - | httof idle browser instances in the pops://apte... | https://apterygial-multiflorous-magaly.ngrok-fr... | 2025-10-07 15:33:05 EDT ```
1 parent c27e844 commit 01dc4cd

File tree

4 files changed

+138
-97
lines changed

4 files changed

+138
-97
lines changed

cmd/browsers.go

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/onkernel/cli/pkg/util"
1919
"github.com/onkernel/kernel-go-sdk"
2020
"github.com/onkernel/kernel-go-sdk/option"
21+
"github.com/onkernel/kernel-go-sdk/packages/pagination"
2122
"github.com/onkernel/kernel-go-sdk/packages/ssestream"
2223
"github.com/onkernel/kernel-go-sdk/shared"
2324
"github.com/pterm/pterm"
@@ -27,7 +28,7 @@ import (
2728
// BrowsersService defines the subset of the Kernel SDK browser client that we use.
2829
// See https://github.com/onkernel/kernel-go-sdk/blob/main/browser.go
2930
type BrowsersService interface {
30-
List(ctx context.Context, opts ...option.RequestOption) (res *[]kernel.BrowserListResponse, err error)
31+
List(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (res *pagination.OffsetPagination[kernel.BrowserListResponse], err error)
3132
New(ctx context.Context, body kernel.BrowserNewParams, opts ...option.RequestOption) (res *kernel.BrowserNewResponse, err error)
3233
Delete(ctx context.Context, body kernel.BrowserDeleteParams, opts ...option.RequestOption) (err error)
3334
DeleteByID(ctx context.Context, id string, opts ...option.RequestOption) (err error)
@@ -183,7 +184,10 @@ type BrowsersCmd struct {
183184
}
184185

185186
type BrowsersListInput struct {
186-
Output string
187+
Output string
188+
IncludeDeleted bool
189+
Limit int
190+
Offset int
187191
}
188192

189193
func (b BrowsersCmd) List(ctx context.Context, in BrowsersListInput) error {
@@ -192,35 +196,50 @@ func (b BrowsersCmd) List(ctx context.Context, in BrowsersListInput) error {
192196
return nil
193197
}
194198

195-
browsers, err := b.browsers.List(ctx)
199+
params := kernel.BrowserListParams{}
200+
if in.IncludeDeleted {
201+
params.IncludeDeleted = kernel.Opt(true)
202+
}
203+
if in.Limit > 0 {
204+
params.Limit = kernel.Opt(int64(in.Limit))
205+
}
206+
if in.Offset > 0 {
207+
params.Offset = kernel.Opt(int64(in.Offset))
208+
}
209+
210+
page, err := b.browsers.List(ctx, params)
196211
if err != nil {
197212
return util.CleanedUpSdkError{Err: err}
198213
}
199214

215+
browsers := page.Items
216+
200217
if in.Output == "json" {
201218
if browsers == nil {
202219
fmt.Println("[]")
203220
return nil
204221
}
205-
bs, err := json.MarshalIndent(*browsers, "", " ")
222+
bs, err := json.MarshalIndent(browsers, "", " ")
206223
if err != nil {
207224
return err
208225
}
209226
fmt.Println(string(bs))
210227
return nil
211228
}
212229

213-
if browsers == nil || len(*browsers) == 0 {
230+
if browsers == nil || len(browsers) == 0 {
214231
pterm.Info.Println("No running or persistent browsers found")
215232
return nil
216233
}
217234

218235
// Prepare table data
219-
tableData := pterm.TableData{
220-
{"Browser ID", "Created At", "Persistent ID", "Profile", "CDP WS URL", "Live View URL"},
236+
headers := []string{"Browser ID", "Created At", "Persistent ID", "Profile", "CDP WS URL", "Live View URL"}
237+
if in.IncludeDeleted {
238+
headers = append(headers, "Deleted At")
221239
}
240+
tableData := pterm.TableData{headers}
222241

223-
for _, browser := range *browsers {
242+
for _, browser := range browsers {
224243
persistentID := "-"
225244
if browser.Persistence.ID != "" {
226245
persistentID = browser.Persistence.ID
@@ -233,14 +252,24 @@ func (b BrowsersCmd) List(ctx context.Context, in BrowsersListInput) error {
233252
profile = browser.Profile.ID
234253
}
235254

236-
tableData = append(tableData, []string{
255+
row := []string{
237256
browser.SessionID,
238257
util.FormatLocal(browser.CreatedAt),
239258
persistentID,
240259
profile,
241260
truncateURL(browser.CdpWsURL, 50),
242261
truncateURL(browser.BrowserLiveViewURL, 50),
243-
})
262+
}
263+
264+
if in.IncludeDeleted {
265+
deletedAt := "-"
266+
if !browser.DeletedAt.IsZero() {
267+
deletedAt = util.FormatLocal(browser.DeletedAt)
268+
}
269+
row = append(row, deletedAt)
270+
}
271+
272+
tableData = append(tableData, row)
244273
}
245274

246275
PrintTableNoPad(tableData, true)
@@ -349,17 +378,17 @@ func (b BrowsersCmd) Create(ctx context.Context, in BrowsersCreateInput) error {
349378

350379
func (b BrowsersCmd) Delete(ctx context.Context, in BrowsersDeleteInput) error {
351380
if !in.SkipConfirm {
352-
browsers, err := b.browsers.List(ctx)
381+
page, err := b.browsers.List(ctx, kernel.BrowserListParams{})
353382
if err != nil {
354383
return util.CleanedUpSdkError{Err: err}
355384
}
356-
if browsers == nil || len(*browsers) == 0 {
385+
if page == nil || page.Items == nil || len(page.Items) == 0 {
357386
pterm.Error.Println("No browsers found")
358387
return nil
359388
}
360389

361390
var found *kernel.BrowserListResponse
362-
for _, br := range *browsers {
391+
for _, br := range page.Items {
363392
if br.SessionID == in.Identifier || br.Persistence.ID == in.Identifier {
364393
bCopy := br
365394
found = &bCopy
@@ -431,18 +460,18 @@ func (b BrowsersCmd) Delete(ctx context.Context, in BrowsersDeleteInput) error {
431460
}
432461

433462
func (b BrowsersCmd) View(ctx context.Context, in BrowsersViewInput) error {
434-
browsers, err := b.browsers.List(ctx)
463+
page, err := b.browsers.List(ctx, kernel.BrowserListParams{})
435464
if err != nil {
436465
return util.CleanedUpSdkError{Err: err}
437466
}
438467

439-
if browsers == nil || len(*browsers) == 0 {
468+
if page == nil || page.Items == nil || len(page.Items) == 0 {
440469
pterm.Error.Println("No browsers found")
441470
return nil
442471
}
443472

444473
var foundBrowser *kernel.BrowserListResponse
445-
for _, browser := range *browsers {
474+
for _, browser := range page.Items {
446475
if browser.Persistence.ID == in.Identifier || browser.SessionID == in.Identifier {
447476
foundBrowser = &browser
448477
break
@@ -1806,6 +1835,9 @@ var browsersViewCmd = &cobra.Command{
18061835
func init() {
18071836
// list flags
18081837
browsersListCmd.Flags().StringP("output", "o", "", "Output format: json for raw API response")
1838+
browsersListCmd.Flags().Bool("include-deleted", false, "Include soft-deleted browser sessions in the results")
1839+
browsersListCmd.Flags().Int("limit", 0, "Maximum number of results to return (default 20, max 100)")
1840+
browsersListCmd.Flags().Int("offset", 0, "Number of results to skip (for pagination)")
18091841

18101842
browsersCmd.AddCommand(browsersListCmd)
18111843
browsersCmd.AddCommand(browsersCreateCmd)
@@ -2028,7 +2060,15 @@ func runBrowsersList(cmd *cobra.Command, args []string) error {
20282060
svc := client.Browsers
20292061
b := BrowsersCmd{browsers: &svc}
20302062
out, _ := cmd.Flags().GetString("output")
2031-
return b.List(cmd.Context(), BrowsersListInput{Output: out})
2063+
includeDeleted, _ := cmd.Flags().GetBool("include-deleted")
2064+
limit, _ := cmd.Flags().GetInt("limit")
2065+
offset, _ := cmd.Flags().GetInt("offset")
2066+
return b.List(cmd.Context(), BrowsersListInput{
2067+
Output: out,
2068+
IncludeDeleted: includeDeleted,
2069+
Limit: limit,
2070+
Offset: offset,
2071+
})
20322072
}
20332073

20342074
func runBrowsersCreate(cmd *cobra.Command, args []string) error {
@@ -2529,14 +2569,14 @@ func truncateURL(url string, maxLen int) string {
25292569

25302570
// resolveBrowserByIdentifier finds a browser by session ID or persistent ID.
25312571
func (b BrowsersCmd) resolveBrowserByIdentifier(ctx context.Context, identifier string) (*kernel.BrowserListResponse, error) {
2532-
browsers, err := b.browsers.List(ctx)
2572+
page, err := b.browsers.List(ctx, kernel.BrowserListParams{})
25332573
if err != nil {
25342574
return nil, err
25352575
}
2536-
if browsers == nil {
2576+
if page == nil || page.Items == nil {
25372577
return nil, nil
25382578
}
2539-
for _, br := range *browsers {
2579+
for _, br := range page.Items {
25402580
if br.SessionID == identifier || br.Persistence.ID == identifier {
25412581
bCopy := br
25422582
return &bCopy, nil

0 commit comments

Comments
 (0)