diff --git a/cmd/browsers.go b/cmd/browsers.go index d8827a4..f07b6e7 100644 --- a/cmd/browsers.go +++ b/cmd/browsers.go @@ -18,6 +18,7 @@ import ( "github.com/onkernel/cli/pkg/util" "github.com/onkernel/kernel-go-sdk" "github.com/onkernel/kernel-go-sdk/option" + "github.com/onkernel/kernel-go-sdk/packages/pagination" "github.com/onkernel/kernel-go-sdk/packages/ssestream" "github.com/onkernel/kernel-go-sdk/shared" "github.com/pterm/pterm" @@ -27,7 +28,7 @@ import ( // BrowsersService defines the subset of the Kernel SDK browser client that we use. // See https://github.com/onkernel/kernel-go-sdk/blob/main/browser.go type BrowsersService interface { - List(ctx context.Context, opts ...option.RequestOption) (res *[]kernel.BrowserListResponse, err error) + List(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (res *pagination.OffsetPagination[kernel.BrowserListResponse], err error) New(ctx context.Context, body kernel.BrowserNewParams, opts ...option.RequestOption) (res *kernel.BrowserNewResponse, err error) Delete(ctx context.Context, body kernel.BrowserDeleteParams, opts ...option.RequestOption) (err error) DeleteByID(ctx context.Context, id string, opts ...option.RequestOption) (err error) @@ -183,7 +184,10 @@ type BrowsersCmd struct { } type BrowsersListInput struct { - Output string + Output string + IncludeDeleted bool + Limit int + Offset int } func (b BrowsersCmd) List(ctx context.Context, in BrowsersListInput) error { @@ -192,17 +196,30 @@ func (b BrowsersCmd) List(ctx context.Context, in BrowsersListInput) error { return nil } - browsers, err := b.browsers.List(ctx) + params := kernel.BrowserListParams{} + if in.IncludeDeleted { + params.IncludeDeleted = kernel.Opt(true) + } + if in.Limit > 0 { + params.Limit = kernel.Opt(int64(in.Limit)) + } + if in.Offset > 0 { + params.Offset = kernel.Opt(int64(in.Offset)) + } + + page, err := b.browsers.List(ctx, params) if err != nil { return util.CleanedUpSdkError{Err: err} } + browsers := page.Items + if in.Output == "json" { if browsers == nil { fmt.Println("[]") return nil } - bs, err := json.MarshalIndent(*browsers, "", " ") + bs, err := json.MarshalIndent(browsers, "", " ") if err != nil { return err } @@ -210,17 +227,19 @@ func (b BrowsersCmd) List(ctx context.Context, in BrowsersListInput) error { return nil } - if browsers == nil || len(*browsers) == 0 { + if browsers == nil || len(browsers) == 0 { pterm.Info.Println("No running or persistent browsers found") return nil } // Prepare table data - tableData := pterm.TableData{ - {"Browser ID", "Created At", "Persistent ID", "Profile", "CDP WS URL", "Live View URL"}, + headers := []string{"Browser ID", "Created At", "Persistent ID", "Profile", "CDP WS URL", "Live View URL"} + if in.IncludeDeleted { + headers = append(headers, "Deleted At") } + tableData := pterm.TableData{headers} - for _, browser := range *browsers { + for _, browser := range browsers { persistentID := "-" if browser.Persistence.ID != "" { persistentID = browser.Persistence.ID @@ -233,14 +252,24 @@ func (b BrowsersCmd) List(ctx context.Context, in BrowsersListInput) error { profile = browser.Profile.ID } - tableData = append(tableData, []string{ + row := []string{ browser.SessionID, util.FormatLocal(browser.CreatedAt), persistentID, profile, truncateURL(browser.CdpWsURL, 50), truncateURL(browser.BrowserLiveViewURL, 50), - }) + } + + if in.IncludeDeleted { + deletedAt := "-" + if !browser.DeletedAt.IsZero() { + deletedAt = util.FormatLocal(browser.DeletedAt) + } + row = append(row, deletedAt) + } + + tableData = append(tableData, row) } PrintTableNoPad(tableData, true) @@ -349,17 +378,17 @@ func (b BrowsersCmd) Create(ctx context.Context, in BrowsersCreateInput) error { func (b BrowsersCmd) Delete(ctx context.Context, in BrowsersDeleteInput) error { if !in.SkipConfirm { - browsers, err := b.browsers.List(ctx) + page, err := b.browsers.List(ctx, kernel.BrowserListParams{}) if err != nil { return util.CleanedUpSdkError{Err: err} } - if browsers == nil || len(*browsers) == 0 { + if page == nil || page.Items == nil || len(page.Items) == 0 { pterm.Error.Println("No browsers found") return nil } var found *kernel.BrowserListResponse - for _, br := range *browsers { + for _, br := range page.Items { if br.SessionID == in.Identifier || br.Persistence.ID == in.Identifier { bCopy := br found = &bCopy @@ -431,18 +460,18 @@ func (b BrowsersCmd) Delete(ctx context.Context, in BrowsersDeleteInput) error { } func (b BrowsersCmd) View(ctx context.Context, in BrowsersViewInput) error { - browsers, err := b.browsers.List(ctx) + page, err := b.browsers.List(ctx, kernel.BrowserListParams{}) if err != nil { return util.CleanedUpSdkError{Err: err} } - if browsers == nil || len(*browsers) == 0 { + if page == nil || page.Items == nil || len(page.Items) == 0 { pterm.Error.Println("No browsers found") return nil } var foundBrowser *kernel.BrowserListResponse - for _, browser := range *browsers { + for _, browser := range page.Items { if browser.Persistence.ID == in.Identifier || browser.SessionID == in.Identifier { foundBrowser = &browser break @@ -1806,6 +1835,9 @@ var browsersViewCmd = &cobra.Command{ func init() { // list flags browsersListCmd.Flags().StringP("output", "o", "", "Output format: json for raw API response") + browsersListCmd.Flags().Bool("include-deleted", false, "Include soft-deleted browser sessions in the results") + browsersListCmd.Flags().Int("limit", 0, "Maximum number of results to return (default 20, max 100)") + browsersListCmd.Flags().Int("offset", 0, "Number of results to skip (for pagination)") browsersCmd.AddCommand(browsersListCmd) browsersCmd.AddCommand(browsersCreateCmd) @@ -2028,7 +2060,15 @@ func runBrowsersList(cmd *cobra.Command, args []string) error { svc := client.Browsers b := BrowsersCmd{browsers: &svc} out, _ := cmd.Flags().GetString("output") - return b.List(cmd.Context(), BrowsersListInput{Output: out}) + includeDeleted, _ := cmd.Flags().GetBool("include-deleted") + limit, _ := cmd.Flags().GetInt("limit") + offset, _ := cmd.Flags().GetInt("offset") + return b.List(cmd.Context(), BrowsersListInput{ + Output: out, + IncludeDeleted: includeDeleted, + Limit: limit, + Offset: offset, + }) } func runBrowsersCreate(cmd *cobra.Command, args []string) error { @@ -2529,14 +2569,14 @@ func truncateURL(url string, maxLen int) string { // resolveBrowserByIdentifier finds a browser by session ID or persistent ID. func (b BrowsersCmd) resolveBrowserByIdentifier(ctx context.Context, identifier string) (*kernel.BrowserListResponse, error) { - browsers, err := b.browsers.List(ctx) + page, err := b.browsers.List(ctx, kernel.BrowserListParams{}) if err != nil { return nil, err } - if browsers == nil { + if page == nil || page.Items == nil { return nil, nil } - for _, br := range *browsers { + for _, br := range page.Items { if br.SessionID == identifier || br.Persistence.ID == identifier { bCopy := br return &bCopy, nil diff --git a/cmd/browsers_test.go b/cmd/browsers_test.go index 7415b40..faf5035 100644 --- a/cmd/browsers_test.go +++ b/cmd/browsers_test.go @@ -15,6 +15,7 @@ import ( "github.com/onkernel/kernel-go-sdk" "github.com/onkernel/kernel-go-sdk/option" + "github.com/onkernel/kernel-go-sdk/packages/pagination" "github.com/onkernel/kernel-go-sdk/packages/ssestream" "github.com/onkernel/kernel-go-sdk/shared" "github.com/pterm/pterm" @@ -53,18 +54,18 @@ func setupStdoutCapture(t *testing.T) { // FakeBrowsersService is a configurable fake implementing BrowsersService. type FakeBrowsersService struct { - ListFunc func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) + ListFunc func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) NewFunc func(ctx context.Context, body kernel.BrowserNewParams, opts ...option.RequestOption) (*kernel.BrowserNewResponse, error) DeleteFunc func(ctx context.Context, body kernel.BrowserDeleteParams, opts ...option.RequestOption) error DeleteByIDFunc func(ctx context.Context, id string, opts ...option.RequestOption) error LoadExtensionsFunc func(ctx context.Context, id string, body kernel.BrowserLoadExtensionsParams, opts ...option.RequestOption) error } -func (f *FakeBrowsersService) List(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { +func (f *FakeBrowsersService) List(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { if f.ListFunc != nil { - return f.ListFunc(ctx, opts...) + return f.ListFunc(ctx, query, opts...) } - return &[]kernel.BrowserListResponse{}, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: []kernel.BrowserListResponse{}}, nil } func (f *FakeBrowsersService) New(ctx context.Context, body kernel.BrowserNewParams, opts ...option.RequestOption) (*kernel.BrowserNewResponse, error) { @@ -99,9 +100,9 @@ func TestBrowsersList_PrintsEmptyMessage(t *testing.T) { setupStdoutCapture(t) fake := &FakeBrowsersService{ - ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { empty := []kernel.BrowserListResponse{} - return &empty, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: empty}, nil }, } b := BrowsersCmd{browsers: fake} @@ -133,8 +134,8 @@ func TestBrowsersList_PrintsTableWithRows(t *testing.T) { } fake := &FakeBrowsersService{ - ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { - return &rows, nil + ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }, } b := BrowsersCmd{browsers: fake} @@ -150,7 +151,7 @@ func TestBrowsersList_PrintsErrorOnFailure(t *testing.T) { setupStdoutCapture(t) fake := &FakeBrowsersService{ - ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { return nil, errors.New("list failed") }, } @@ -253,8 +254,8 @@ func TestBrowsersDelete_WithConfirm_NotFound(t *testing.T) { list := []kernel.BrowserListResponse{{SessionID: "s-1", Persistence: kernel.BrowserPersistence{ID: "p-1"}}} fake := &FakeBrowsersService{ - ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { - return &list, nil + ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: list}, nil }, } b := BrowsersCmd{browsers: fake} @@ -272,8 +273,8 @@ func TestBrowsersView_ByID_PrintsURL(t *testing.T) { BrowserLiveViewURL: "http://live-url", }} fake := &FakeBrowsersService{ - ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { - return &list, nil + ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: list}, nil }, } b := BrowsersCmd{browsers: fake} @@ -288,8 +289,8 @@ func TestBrowsersView_NotFound_ByEither(t *testing.T) { list := []kernel.BrowserListResponse{{SessionID: "abc", Persistence: kernel.BrowserPersistence{ID: "pid-xyz"}}} fake := &FakeBrowsersService{ - ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { - return &list, nil + ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: list}, nil }, } b := BrowsersCmd{browsers: fake} @@ -303,7 +304,7 @@ func TestBrowsersView_PrintsErrorOnListFailure(t *testing.T) { setupStdoutCapture(t) fake := &FakeBrowsersService{ - ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { return nil, errors.New("list error") }, } @@ -590,9 +591,9 @@ func (f *FakeComputerService) SetCursorVisibility(ctx context.Context, id string func TestBrowsersLogsStream_PrintsEvents(t *testing.T) { setupStdoutCapture(t) - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, logs: &FakeLogService{}} _ = b.LogsStream(context.Background(), BrowsersLogsStreamInput{Identifier: "id", Source: string(kernel.BrowserLogStreamParamsSourcePath), Follow: BoolFlag{Set: true, Value: true}, Path: "/var/log.txt"}) @@ -610,9 +611,9 @@ func TestBrowsersReplaysList_PrintsRows(t *testing.T) { fake := &FakeReplaysService{ListFunc: func(ctx context.Context, id string, opts ...option.RequestOption) (*[]kernel.BrowserReplayListResponse, error) { return &replays, nil }} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, replays: fake} _ = b.ReplaysList(context.Background(), BrowsersReplaysListInput{Identifier: "id"}) @@ -626,9 +627,9 @@ func TestBrowsersReplaysStart_PrintsInfo(t *testing.T) { fake := &FakeReplaysService{StartFunc: func(ctx context.Context, id string, body kernel.BrowserReplayStartParams, opts ...option.RequestOption) (*kernel.BrowserReplayStartResponse, error) { return &kernel.BrowserReplayStartResponse{ReplayID: "rid", ReplayViewURL: "http://view", StartedAt: time.Unix(0, 0)}, nil }} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, replays: fake} _ = b.ReplaysStart(context.Background(), BrowsersReplaysStartInput{Identifier: "id", Framerate: 30, MaxDurationSeconds: 60}) @@ -640,9 +641,9 @@ func TestBrowsersReplaysStart_PrintsInfo(t *testing.T) { func TestBrowsersReplaysStop_PrintsSuccess(t *testing.T) { setupStdoutCapture(t) fake := &FakeReplaysService{} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, replays: fake} _ = b.ReplaysStop(context.Background(), BrowsersReplaysStopInput{Identifier: "id", ReplayID: "rid"}) @@ -657,9 +658,9 @@ func TestBrowsersReplaysDownload_SavesFile(t *testing.T) { fake := &FakeReplaysService{DownloadFunc: func(ctx context.Context, replayID string, query kernel.BrowserReplayDownloadParams, opts ...option.RequestOption) (*http.Response, error) { return &http.Response{StatusCode: 200, Header: http.Header{"Content-Type": []string{"video/mp4"}}, Body: io.NopCloser(strings.NewReader("mp4data"))}, nil }} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, replays: fake} _ = b.ReplaysDownload(context.Background(), BrowsersReplaysDownloadInput{Identifier: "id", ReplayID: "rid", Output: outPath}) @@ -673,9 +674,9 @@ func TestBrowsersReplaysDownload_SavesFile(t *testing.T) { func TestBrowsersProcessExec_PrintsSummary(t *testing.T) { setupStdoutCapture(t) fake := &FakeProcessService{} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, process: fake} _ = b.ProcessExec(context.Background(), BrowsersProcessExecInput{Identifier: "id", Command: "echo"}) @@ -687,9 +688,9 @@ func TestBrowsersProcessExec_PrintsSummary(t *testing.T) { func TestBrowsersProcessSpawn_PrintsInfo(t *testing.T) { setupStdoutCapture(t) fake := &FakeProcessService{} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, process: fake} _ = b.ProcessSpawn(context.Background(), BrowsersProcessSpawnInput{Identifier: "id", Command: "sleep"}) @@ -701,9 +702,9 @@ func TestBrowsersProcessSpawn_PrintsInfo(t *testing.T) { func TestBrowsersProcessKill_PrintsSuccess(t *testing.T) { setupStdoutCapture(t) fake := &FakeProcessService{} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, process: fake} _ = b.ProcessKill(context.Background(), BrowsersProcessKillInput{Identifier: "id", ProcessID: "proc", Signal: "TERM"}) @@ -714,9 +715,9 @@ func TestBrowsersProcessKill_PrintsSuccess(t *testing.T) { func TestBrowsersProcessStatus_PrintsFields(t *testing.T) { setupStdoutCapture(t) fake := &FakeProcessService{} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, process: fake} _ = b.ProcessStatus(context.Background(), BrowsersProcessStatusInput{Identifier: "id", ProcessID: "proc"}) @@ -729,9 +730,9 @@ func TestBrowsersProcessStatus_PrintsFields(t *testing.T) { func TestBrowsersProcessStdin_PrintsSuccess(t *testing.T) { setupStdoutCapture(t) fake := &FakeProcessService{} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, process: fake} _ = b.ProcessStdin(context.Background(), BrowsersProcessStdinInput{Identifier: "id", ProcessID: "proc", DataB64: "ZGF0YQ=="}) @@ -742,9 +743,9 @@ func TestBrowsersProcessStdin_PrintsSuccess(t *testing.T) { func TestBrowsersProcessStdoutStream_PrintsExit(t *testing.T) { setupStdoutCapture(t) fake := &FakeProcessService{} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, process: fake} _ = b.ProcessStdoutStream(context.Background(), BrowsersProcessStdoutStreamInput{Identifier: "id", ProcessID: "proc"}) @@ -757,9 +758,9 @@ func TestBrowsersProcessStdoutStream_PrintsExit(t *testing.T) { func TestBrowsersFSNewDirectory_PrintsSuccess(t *testing.T) { setupStdoutCapture(t) fake := &FakeFSService{} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, fs: fake} _ = b.FSNewDirectory(context.Background(), BrowsersFSNewDirInput{Identifier: "id", Path: "/tmp/x"}) @@ -770,9 +771,9 @@ func TestBrowsersFSNewDirectory_PrintsSuccess(t *testing.T) { func TestBrowsersFSDeleteDirectory_PrintsSuccess(t *testing.T) { setupStdoutCapture(t) fake := &FakeFSService{} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, fs: fake} _ = b.FSDeleteDirectory(context.Background(), BrowsersFSDeleteDirInput{Identifier: "id", Path: "/tmp/x"}) @@ -783,9 +784,9 @@ func TestBrowsersFSDeleteDirectory_PrintsSuccess(t *testing.T) { func TestBrowsersFSDeleteFile_PrintsSuccess(t *testing.T) { setupStdoutCapture(t) fake := &FakeFSService{} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, fs: fake} _ = b.FSDeleteFile(context.Background(), BrowsersFSDeleteFileInput{Identifier: "id", Path: "/tmp/file"}) @@ -797,9 +798,9 @@ func TestBrowsersFSDownloadDirZip_SavesFile(t *testing.T) { dir := t.TempDir() outPath := filepath.Join(dir, "out.zip") fake := &FakeFSService{} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, fs: fake} _ = b.FSDownloadDirZip(context.Background(), BrowsersFSDownloadDirZipInput{Identifier: "id", Path: "/tmp", Output: outPath}) @@ -813,9 +814,9 @@ func TestBrowsersFSFileInfo_PrintsFields(t *testing.T) { fake := &FakeFSService{FileInfoFunc: func(ctx context.Context, id string, query kernel.BrowserFFileInfoParams, opts ...option.RequestOption) (*kernel.BrowserFFileInfoResponse, error) { return &kernel.BrowserFFileInfoResponse{Path: "/tmp/a", Name: "a", Mode: "-rw-r--r--", IsDir: false, SizeBytes: 1, ModTime: time.Unix(0, 0)}, nil }} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, fs: fake} _ = b.FSFileInfo(context.Background(), BrowsersFSFileInfoInput{Identifier: "id", Path: "/tmp/a"}) @@ -827,9 +828,9 @@ func TestBrowsersFSFileInfo_PrintsFields(t *testing.T) { func TestBrowsersFSListFiles_PrintsRows(t *testing.T) { setupStdoutCapture(t) fake := &FakeFSService{} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, fs: fake} _ = b.FSListFiles(context.Background(), BrowsersFSListFilesInput{Identifier: "id", Path: "/"}) @@ -841,9 +842,9 @@ func TestBrowsersFSListFiles_PrintsRows(t *testing.T) { func TestBrowsersFSMove_PrintsSuccess(t *testing.T) { setupStdoutCapture(t) fake := &FakeFSService{} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, fs: fake} _ = b.FSMove(context.Background(), BrowsersFSMoveInput{Identifier: "id", SrcPath: "/a", DestPath: "/b"}) @@ -855,9 +856,9 @@ func TestBrowsersFSReadFile_SavesFile(t *testing.T) { dir := t.TempDir() outPath := filepath.Join(dir, "file.txt") fake := &FakeFSService{} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, fs: fake} _ = b.FSReadFile(context.Background(), BrowsersFSReadFileInput{Identifier: "id", Path: "/tmp/x", Output: outPath}) @@ -869,9 +870,9 @@ func TestBrowsersFSReadFile_SavesFile(t *testing.T) { func TestBrowsersFSSetPermissions_PrintsSuccess(t *testing.T) { setupStdoutCapture(t) fake := &FakeFSService{} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, fs: fake} _ = b.FSSetPermissions(context.Background(), BrowsersFSSetPermsInput{Identifier: "id", Path: "/tmp/a", Mode: "644"}) @@ -886,9 +887,9 @@ func TestBrowsersFSUpload_MappingAndDestDir_Success(t *testing.T) { captured = body return nil }} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, fs: fake} in := BrowsersFSUploadInput{Identifier: "id", Mappings: []struct { @@ -907,9 +908,9 @@ func TestBrowsersFSUploadZip_Success(t *testing.T) { fake := &FakeFSService{UploadZipFunc: func(ctx context.Context, id string, body kernel.BrowserFUploadZipParams, opts ...option.RequestOption) error { return nil }} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, fs: fake} _ = b.FSUploadZip(context.Background(), BrowsersFSUploadZipInput{Identifier: "id", ZipPath: z, DestDir: "/dst"}) @@ -922,9 +923,9 @@ func TestBrowsersFSWriteFile_FromBase64_And_FromInput(t *testing.T) { fake := &FakeFSService{WriteFileFunc: func(ctx context.Context, id string, contents io.Reader, body kernel.BrowserFWriteFileParams, opts ...option.RequestOption) error { return nil }} - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} b := BrowsersCmd{browsers: fakeBrowsers, fs: fake} // input mode @@ -949,9 +950,9 @@ func __writeTempFile(t *testing.T, data string) string { func TestBrowsersComputerClickMouse_PrintsSuccess(t *testing.T) { setupStdoutCapture(t) - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} fakeComp := &FakeComputerService{} b := BrowsersCmd{browsers: fakeBrowsers, computer: fakeComp} @@ -962,9 +963,9 @@ func TestBrowsersComputerClickMouse_PrintsSuccess(t *testing.T) { func TestBrowsersComputerMoveMouse_PrintsSuccess(t *testing.T) { setupStdoutCapture(t) - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} fakeComp := &FakeComputerService{} b := BrowsersCmd{browsers: fakeBrowsers, computer: fakeComp} @@ -977,9 +978,9 @@ func TestBrowsersComputerScreenshot_SavesFile(t *testing.T) { setupStdoutCapture(t) dir := t.TempDir() outPath := filepath.Join(dir, "shot.png") - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} fakeComp := &FakeComputerService{CaptureScreenshotFunc: func(ctx context.Context, id string, body kernel.BrowserComputerCaptureScreenshotParams, opts ...option.RequestOption) (*http.Response, error) { return &http.Response{StatusCode: 200, Header: http.Header{"Content-Type": []string{"image/png"}}, Body: io.NopCloser(strings.NewReader("pngDATA"))}, nil @@ -993,9 +994,9 @@ func TestBrowsersComputerScreenshot_SavesFile(t *testing.T) { func TestBrowsersComputerPressKey_PrintsSuccess(t *testing.T) { setupStdoutCapture(t) - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} fakeComp := &FakeComputerService{} b := BrowsersCmd{browsers: fakeBrowsers, computer: fakeComp} @@ -1006,9 +1007,9 @@ func TestBrowsersComputerPressKey_PrintsSuccess(t *testing.T) { func TestBrowsersComputerScroll_PrintsSuccess(t *testing.T) { setupStdoutCapture(t) - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} fakeComp := &FakeComputerService{} b := BrowsersCmd{browsers: fakeBrowsers, computer: fakeComp} @@ -1019,9 +1020,9 @@ func TestBrowsersComputerScroll_PrintsSuccess(t *testing.T) { func TestBrowsersComputerDragMouse_PrintsSuccess(t *testing.T) { setupStdoutCapture(t) - fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, opts ...option.RequestOption) (*[]kernel.BrowserListResponse, error) { + fakeBrowsers := &FakeBrowsersService{ListFunc: func(ctx context.Context, query kernel.BrowserListParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserListResponse], error) { rows := []kernel.BrowserListResponse{{SessionID: "id"}} - return &rows, nil + return &pagination.OffsetPagination[kernel.BrowserListResponse]{Items: rows}, nil }} fakeComp := &FakeComputerService{} b := BrowsersCmd{browsers: fakeBrowsers, computer: fakeComp} diff --git a/go.mod b/go.mod index 6fe8743..cdbc232 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/charmbracelet/fang v0.2.0 github.com/golang-jwt/jwt/v5 v5.2.2 github.com/joho/godotenv v1.5.1 - github.com/onkernel/kernel-go-sdk v0.19.0 + github.com/onkernel/kernel-go-sdk v0.20.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 a69902e..e1ca8b8 100644 --- a/go.sum +++ b/go.sum @@ -91,8 +91,8 @@ github.com/muesli/mango-pflag v0.1.0 h1:UADqbYgpUyRoBja3g6LUL+3LErjpsOwaC9ywvBWe github.com/muesli/mango-pflag v0.1.0/go.mod h1:YEQomTxaCUp8PrbhFh10UfbhbQrM/xJ4i2PB8VTLLW0= github.com/muesli/roff v0.1.0 h1:YD0lalCotmYuF5HhZliKWlIx7IEhiXeSfq7hNjFqGF8= github.com/muesli/roff v0.1.0/go.mod h1:pjAHQM9hdUUwm/krAfrLGgJkXJ+YuhtsfZ42kieB2Ig= -github.com/onkernel/kernel-go-sdk v0.19.0 h1:kfLHmcye/zEF9INP3zIXffmVLGFVZiZNFs4NeVAgya0= -github.com/onkernel/kernel-go-sdk v0.19.0/go.mod h1:t80buN1uCA/hwvm4D2SpjTJzZWcV7bWOFo9d7qdXD8M= +github.com/onkernel/kernel-go-sdk v0.20.0 h1:KBMBjs54QlzlbQOFZLcN0PHD2QR8wJIrpzEfBaf6YZ0= +github.com/onkernel/kernel-go-sdk v0.20.0/go.mod h1:t80buN1uCA/hwvm4D2SpjTJzZWcV7bWOFo9d7qdXD8M= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=