@@ -3,7 +3,6 @@ package cmd
33import (
44 "context"
55 "encoding/base64"
6- "errors"
76 "fmt"
87 "io"
98 "net/http"
@@ -76,10 +75,13 @@ type BoolFlag struct {
7675
7776// Inputs for each command
7877type BrowsersCreateInput struct {
79- PersistenceID string
80- TimeoutSeconds int
81- Stealth BoolFlag
82- Headless BoolFlag
78+ PersistenceID string
79+ TimeoutSeconds int
80+ Stealth BoolFlag
81+ Headless BoolFlag
82+ ProfileID string
83+ ProfileName string
84+ ProfileSaveChanges BoolFlag
8385}
8486
8587type BrowsersDeleteInput struct {
@@ -115,7 +117,7 @@ func (b BrowsersCmd) List(ctx context.Context) error {
115117
116118 // Prepare table data
117119 tableData := pterm.TableData {
118- {"Browser ID" , "Created At" , "Persistent ID" , "CDP WS URL" , "Live View URL" },
120+ {"Browser ID" , "Created At" , "Persistent ID" , "Profile" , " CDP WS URL" , "Live View URL" },
119121 }
120122
121123 for _ , browser := range * browsers {
@@ -124,10 +126,18 @@ func (b BrowsersCmd) List(ctx context.Context) error {
124126 persistentID = browser .Persistence .ID
125127 }
126128
129+ profile := "-"
130+ if browser .Profile .Name != "" {
131+ profile = browser .Profile .Name
132+ } else if browser .Profile .ID != "" {
133+ profile = browser .Profile .ID
134+ }
135+
127136 tableData = append (tableData , []string {
128137 browser .SessionID ,
129- browser .CreatedAt . Format ( "2006-01-02 15:04:05" ),
138+ util . FormatLocal ( browser .CreatedAt ),
130139 persistentID ,
140+ profile ,
131141 truncateURL (browser .CdpWsURL , 50 ),
132142 truncateURL (browser .BrowserLiveViewURL , 50 ),
133143 })
@@ -153,6 +163,21 @@ func (b BrowsersCmd) Create(ctx context.Context, in BrowsersCreateInput) error {
153163 params .Headless = kernel .Opt (in .Headless .Value )
154164 }
155165
166+ // Validate profile selection: at most one of profile-id or profile-name must be provided
167+ if in .ProfileID != "" && in .ProfileName != "" {
168+ pterm .Error .Println ("must specify at most one of --profile-id or --profile-name" )
169+ return nil
170+ } else if in .ProfileID != "" || in .ProfileName != "" {
171+ params .Profile = kernel.BrowserNewParamsProfile {
172+ SaveChanges : kernel .Opt (in .ProfileSaveChanges .Value ),
173+ }
174+ if in .ProfileID != "" {
175+ params .Profile .ID = kernel .Opt (in .ProfileID )
176+ } else if in .ProfileName != "" {
177+ params .Profile .Name = kernel .Opt (in .ProfileName )
178+ }
179+ }
180+
156181 browser , err := b .browsers .New (ctx , params )
157182 if err != nil {
158183 return util.CleanedUpSdkError {Err : err }
@@ -169,23 +194,19 @@ func (b BrowsersCmd) Create(ctx context.Context, in BrowsersCreateInput) error {
169194 if browser .Persistence .ID != "" {
170195 tableData = append (tableData , []string {"Persistent ID" , browser .Persistence .ID })
171196 }
197+ if browser .Profile .ID != "" || browser .Profile .Name != "" {
198+ profVal := browser .Profile .Name
199+ if profVal == "" {
200+ profVal = browser .Profile .ID
201+ }
202+ tableData = append (tableData , []string {"Profile" , profVal })
203+ }
172204
173205 printTableNoPad (tableData , true )
174206 return nil
175207}
176208
177209func (b BrowsersCmd ) Delete (ctx context.Context , in BrowsersDeleteInput ) error {
178- isNotFound := func (err error ) bool {
179- if err == nil {
180- return false
181- }
182- var apierr * kernel.Error
183- if errors .As (err , & apierr ) {
184- return apierr != nil && apierr .StatusCode == http .StatusNotFound
185- }
186- return false
187- }
188-
189210 if ! in .SkipConfirm {
190211 browsers , err := b .browsers .List (ctx )
191212 if err != nil {
@@ -225,7 +246,7 @@ func (b BrowsersCmd) Delete(ctx context.Context, in BrowsersDeleteInput) error {
225246 if found .Persistence .ID == in .Identifier {
226247 pterm .Info .Printf ("Deleting browser with persistent ID: %s\n " , in .Identifier )
227248 err = b .browsers .Delete (ctx , kernel.BrowserDeleteParams {PersistentID : in .Identifier })
228- if err != nil && ! isNotFound (err ) {
249+ if err != nil && ! util . IsNotFound (err ) {
229250 return util.CleanedUpSdkError {Err : err }
230251 }
231252 pterm .Success .Printf ("Successfully deleted browser with persistent ID: %s\n " , in .Identifier )
@@ -234,7 +255,7 @@ func (b BrowsersCmd) Delete(ctx context.Context, in BrowsersDeleteInput) error {
234255
235256 pterm .Info .Printf ("Deleting browser with ID: %s\n " , in .Identifier )
236257 err = b .browsers .DeleteByID (ctx , in .Identifier )
237- if err != nil && ! isNotFound (err ) {
258+ if err != nil && ! util . IsNotFound (err ) {
238259 return util.CleanedUpSdkError {Err : err }
239260 }
240261 pterm .Success .Printf ("Successfully deleted browser with ID: %s\n " , in .Identifier )
@@ -247,14 +268,14 @@ func (b BrowsersCmd) Delete(ctx context.Context, in BrowsersDeleteInput) error {
247268
248269 // Attempt by session ID
249270 if err := b .browsers .DeleteByID (ctx , in .Identifier ); err != nil {
250- if ! isNotFound (err ) {
271+ if ! util . IsNotFound (err ) {
251272 nonNotFoundErrors = append (nonNotFoundErrors , err )
252273 }
253274 }
254275
255276 // Attempt by persistent ID
256277 if err := b .browsers .Delete (ctx , kernel.BrowserDeleteParams {PersistentID : in .Identifier }); err != nil {
257- if ! isNotFound (err ) {
278+ if ! util . IsNotFound (err ) {
258279 nonNotFoundErrors = append (nonNotFoundErrors , err )
259280 }
260281 }
@@ -337,7 +358,7 @@ func (b BrowsersCmd) LogsStream(ctx context.Context, in BrowsersLogsStreamInput)
337358 defer stream .Close ()
338359 for stream .Next () {
339360 ev := stream .Current ()
340- pterm .Println (fmt .Sprintf ("[%s] %s" , ev .Timestamp . Format ( "2006-01-02 15:04:05" ), ev .Message ))
361+ pterm .Println (fmt .Sprintf ("[%s] %s" , util . FormatLocal ( ev .Timestamp ), ev .Message ))
341362 }
342363 if err := stream .Err (); err != nil {
343364 return util.CleanedUpSdkError {Err : err }
@@ -386,7 +407,7 @@ func (b BrowsersCmd) ReplaysList(ctx context.Context, in BrowsersReplaysListInpu
386407 }
387408 rows := pterm.TableData {{"Replay ID" , "Started At" , "Finished At" , "View URL" }}
388409 for _ , r := range * items {
389- rows = append (rows , []string {r .ReplayID , r .StartedAt . Format ( "2006-01-02 15:04:05" ), r .FinishedAt . Format ( "2006-01-02 15:04:05" ), truncateURL (r .ReplayViewURL , 60 )})
410+ rows = append (rows , []string {r .ReplayID , util . FormatLocal ( r .StartedAt ), util . FormatLocal ( r .FinishedAt ), truncateURL (r .ReplayViewURL , 60 )})
390411 }
391412 printTableNoPad (rows , true )
392413 return nil
@@ -412,7 +433,7 @@ func (b BrowsersCmd) ReplaysStart(ctx context.Context, in BrowsersReplaysStartIn
412433 if err != nil {
413434 return util.CleanedUpSdkError {Err : err }
414435 }
415- rows := pterm.TableData {{"Property" , "Value" }, {"Replay ID" , res .ReplayID }, {"View URL" , res .ReplayViewURL }, {"Started At" , res .StartedAt . Format ( "2006-01-02 15:04:05" )}}
436+ rows := pterm.TableData {{"Property" , "Value" }, {"Replay ID" , res .ReplayID }, {"View URL" , res .ReplayViewURL }, {"Started At" , util . FormatLocal ( res .StartedAt )}}
416437 printTableNoPad (rows , true )
417438 return nil
418439}
@@ -597,7 +618,7 @@ func (b BrowsersCmd) ProcessSpawn(ctx context.Context, in BrowsersProcessSpawnIn
597618 if err != nil {
598619 return util.CleanedUpSdkError {Err : err }
599620 }
600- rows := pterm.TableData {{"Property" , "Value" }, {"Process ID" , res .ProcessID }, {"PID" , fmt .Sprintf ("%d" , res .Pid )}, {"Started At" , res .StartedAt . Format ( "2006-01-02 15:04:05" )}}
621+ rows := pterm.TableData {{"Property" , "Value" }, {"Process ID" , res .ProcessID }, {"PID" , fmt .Sprintf ("%d" , res .Pid )}, {"Started At" , util . FormatLocal ( res .StartedAt )}}
601622 printTableNoPad (rows , true )
602623 return nil
603624}
@@ -900,7 +921,7 @@ func (b BrowsersCmd) FSFileInfo(ctx context.Context, in BrowsersFSFileInfoInput)
900921 if err != nil {
901922 return util.CleanedUpSdkError {Err : err }
902923 }
903- rows := pterm.TableData {{"Property" , "Value" }, {"Path" , res .Path }, {"Name" , res .Name }, {"Mode" , res .Mode }, {"IsDir" , fmt .Sprintf ("%t" , res .IsDir )}, {"SizeBytes" , fmt .Sprintf ("%d" , res .SizeBytes )}, {"ModTime" , res .ModTime . Format ( "2006-01-02 15:04:05" )}}
924+ rows := pterm.TableData {{"Property" , "Value" }, {"Path" , res .Path }, {"Name" , res .Name }, {"Mode" , res .Mode }, {"IsDir" , fmt .Sprintf ("%t" , res .IsDir )}, {"SizeBytes" , fmt .Sprintf ("%d" , res .SizeBytes )}, {"ModTime" , util . FormatLocal ( res .ModTime )}}
904925 printTableNoPad (rows , true )
905926 return nil
906927}
@@ -928,7 +949,7 @@ func (b BrowsersCmd) FSListFiles(ctx context.Context, in BrowsersFSListFilesInpu
928949 }
929950 rows := pterm.TableData {{"Mode" , "Size" , "ModTime" , "Name" , "Path" }}
930951 for _ , f := range * res {
931- rows = append (rows , []string {f .Mode , fmt .Sprintf ("%d" , f .SizeBytes ), f .ModTime . Format ( "2006-01-02 15:04:05" ), f .Name , f .Path })
952+ rows = append (rows , []string {f .Mode , fmt .Sprintf ("%d" , f .SizeBytes ), util . FormatLocal ( f .ModTime ), f .Name , f .Path })
932953 }
933954 printTableNoPad (rows , true )
934955 return nil
@@ -1297,6 +1318,9 @@ func init() {
12971318 browsersCreateCmd .Flags ().BoolP ("stealth" , "s" , false , "Launch browser in stealth mode to avoid detection" )
12981319 browsersCreateCmd .Flags ().BoolP ("headless" , "H" , false , "Launch browser without GUI access" )
12991320 browsersCreateCmd .Flags ().IntP ("timeout" , "t" , 60 , "Timeout in seconds for the browser session" )
1321+ browsersCreateCmd .Flags ().String ("profile-id" , "" , "Profile ID to load into the browser session (mutually exclusive with --profile-name)" )
1322+ browsersCreateCmd .Flags ().String ("profile-name" , "" , "Profile name to load into the browser session (mutually exclusive with --profile-id)" )
1323+ browsersCreateCmd .Flags ().Bool ("save-changes" , false , "If set, save changes back to the profile when the session ends" )
13001324
13011325 // Add flags for delete command
13021326 browsersDeleteCmd .Flags ().BoolP ("yes" , "y" , false , "Skip confirmation prompt" )
@@ -1319,12 +1343,18 @@ func runBrowsersCreate(cmd *cobra.Command, args []string) error {
13191343 stealthVal , _ := cmd .Flags ().GetBool ("stealth" )
13201344 headlessVal , _ := cmd .Flags ().GetBool ("headless" )
13211345 timeout , _ := cmd .Flags ().GetInt ("timeout" )
1346+ profileID , _ := cmd .Flags ().GetString ("profile-id" )
1347+ profileName , _ := cmd .Flags ().GetString ("profile-name" )
1348+ saveChanges , _ := cmd .Flags ().GetBool ("save-changes" )
13221349
13231350 in := BrowsersCreateInput {
1324- PersistenceID : persistenceID ,
1325- TimeoutSeconds : timeout ,
1326- Stealth : BoolFlag {Set : cmd .Flags ().Changed ("stealth" ), Value : stealthVal },
1327- Headless : BoolFlag {Set : cmd .Flags ().Changed ("headless" ), Value : headlessVal },
1351+ PersistenceID : persistenceID ,
1352+ TimeoutSeconds : timeout ,
1353+ Stealth : BoolFlag {Set : cmd .Flags ().Changed ("stealth" ), Value : stealthVal },
1354+ Headless : BoolFlag {Set : cmd .Flags ().Changed ("headless" ), Value : headlessVal },
1355+ ProfileID : profileID ,
1356+ ProfileName : profileName ,
1357+ ProfileSaveChanges : BoolFlag {Set : cmd .Flags ().Changed ("save-changes" ), Value : saveChanges },
13281358 }
13291359
13301360 svc := client .Browsers
0 commit comments