@@ -483,19 +483,15 @@ func createAgentConfig(ctx context.Context, cmd *cli.Command) error {
483483}
484484
485485func deployAgent (ctx context.Context , cmd * cli.Command ) error {
486- configExists , err := requireConfig (workingDir , tomlFilename )
486+ var req * lkproto.DeployAgentRequest
487+
488+ agentId , err := getAgentID (ctx , cmd , workingDir , tomlFilename )
487489 if err != nil {
488490 return err
489491 }
490- if ! configExists {
491- return fmt .Errorf ("config file [%s] required to update agent" , util .Accented (tomlFilename ))
492- }
493- if ! lkConfig .HasAgent () {
494- return fmt .Errorf ("no agent config found in [%s]" , tomlFilename )
495- }
496492
497- req : = & lkproto.DeployAgentRequest {
498- AgentId : lkConfig . Agent . ID ,
493+ req = & lkproto.DeployAgentRequest {
494+ AgentId : agentId ,
499495 }
500496
501497 secrets , err := requireSecrets (ctx , cmd , false , true )
@@ -537,7 +533,7 @@ func deployAgent(ctx context.Context, cmd *cli.Command) error {
537533}
538534
539535func getAgentStatus (ctx context.Context , cmd * cli.Command ) error {
540- agentID , err := getAgentID (cmd , workingDir , tomlFilename )
536+ agentID , err := getAgentID (ctx , cmd , workingDir , tomlFilename )
541537 if err != nil {
542538 return err
543539 }
@@ -577,9 +573,11 @@ func getAgentStatus(ctx context.Context, cmd *cli.Command) error {
577573 }
578574
579575 rows = append (rows , []string {
576+ agent .AgentId ,
577+ agent .Version ,
580578 regionalAgent .Region ,
581579 regionalAgent .Status ,
582- fmt .Sprintf ("%.4g / %s" , curCPU , regionalAgent .CpuLimit ),
580+ fmt .Sprintf ("%s / %s" , curCPU , regionalAgent .CpuLimit ),
583581 fmt .Sprintf ("%s / %s" , curMem , memLimit ),
584582 fmt .Sprintf ("%d / %d / %d" , regionalAgent .Replicas , regionalAgent .MinReplicas , regionalAgent .MaxReplicas ),
585583 agent .DeployedAt .AsTime ().Format (time .RFC3339 ),
@@ -588,15 +586,15 @@ func getAgentStatus(ctx context.Context, cmd *cli.Command) error {
588586 }
589587
590588 t := util .CreateTable ().
591- Headers ("Region" , "Status" , "CPU" , "Mem" , "Replicas/Min/Max " , "Deployed At" ).
589+ Headers ("ID" , "Version" , " Region" , "Status" , "CPU" , "Mem" , "Replicas" , "Deployed At" ).
592590 Rows (rows ... )
593591
594592 fmt .Println (t )
595593 return nil
596594}
597595
598596func restartAgent (ctx context.Context , cmd * cli.Command ) error {
599- agentID , err := getAgentID (cmd , workingDir , tomlFilename )
597+ agentID , err := getAgentID (ctx , cmd , workingDir , tomlFilename )
600598 if err != nil {
601599 return err
602600 }
@@ -645,7 +643,10 @@ func updateAgent(ctx context.Context, cmd *cli.Command) error {
645643 req .Secrets = secrets
646644 }
647645
648- resp , err := agentsClient .UpdateAgent (ctx , req )
646+ var resp * lkproto.UpdateAgentResponse
647+ util .Await ("Updating agent [" + util .Accented (lkConfig .Agent .ID )+ "]" , func () {
648+ resp , err = agentsClient .UpdateAgent (ctx , req )
649+ })
649650 if err != nil {
650651 if twerr , ok := err .(twirp.Error ); ok {
651652 if twerr .Code () == twirp .PermissionDenied {
@@ -665,14 +666,17 @@ func updateAgent(ctx context.Context, cmd *cli.Command) error {
665666}
666667
667668func rollbackAgent (ctx context.Context , cmd * cli.Command ) error {
668- agentID , err := getAgentID (cmd , workingDir , tomlFilename )
669+ agentID , err := getAgentID (ctx , cmd , workingDir , tomlFilename )
669670 if err != nil {
670671 return err
671672 }
672673
673- resp , err := agentsClient .RollbackAgent (ctx , & lkproto.RollbackAgentRequest {
674- AgentId : agentID ,
675- Version : cmd .String ("version" ),
674+ var resp * lkproto.RollbackAgentResponse
675+ util .Await ("Rolling back agent [" + util .Accented (agentID )+ "]" , func () {
676+ resp , err = agentsClient .RollbackAgent (ctx , & lkproto.RollbackAgentRequest {
677+ AgentId : agentID ,
678+ Version : cmd .String ("version" ),
679+ })
676680 })
677681
678682 if err != nil {
@@ -688,13 +692,13 @@ func rollbackAgent(ctx context.Context, cmd *cli.Command) error {
688692 return fmt .Errorf ("failed to rollback agent %s" , resp .Message )
689693 }
690694
691- fmt .Printf ("Rolled back agent [%s] to version %s \n " , util .Accented (agentID ), cmd .String ("version" ))
695+ fmt .Printf ("Rolled back agent [%s] to version [%s] \n " , util .Accented (agentID ), util . Accented ( cmd .String ("version" ) ))
692696
693697 return nil
694698}
695699
696700func getLogs (ctx context.Context , cmd * cli.Command ) error {
697- agentID , err := getAgentID (cmd , workingDir , tomlFilename )
701+ agentID , err := getAgentID (ctx , cmd , workingDir , tomlFilename )
698702 if err != nil {
699703 return err
700704 }
@@ -703,7 +707,7 @@ func getLogs(ctx context.Context, cmd *cli.Command) error {
703707}
704708
705709func deleteAgent (ctx context.Context , cmd * cli.Command ) error {
706- agentID , err := getAgentID (cmd , workingDir , tomlFilename )
710+ agentID , err := getAgentID (ctx , cmd , workingDir , tomlFilename )
707711 if err != nil {
708712 return err
709713 }
@@ -758,7 +762,7 @@ func deleteAgent(ctx context.Context, cmd *cli.Command) error {
758762}
759763
760764func listAgentVersions (ctx context.Context , cmd * cli.Command ) error {
761- agentID , err := getAgentID (cmd , workingDir , tomlFilename )
765+ agentID , err := getAgentID (ctx , cmd , workingDir , tomlFilename )
762766 if err != nil {
763767 return err
764768 }
@@ -778,14 +782,14 @@ func listAgentVersions(ctx context.Context, cmd *cli.Command) error {
778782 }
779783
780784 table := util .CreateTable ().
781- Headers ("Version" , "Current" , "Created At" )
785+ Headers ("Version" , "Current" , "Deployed At" )
782786
783- // Sort versions by created date ascending
787+ // Sort versions by created date descending
784788 slices .SortFunc (versions .Versions , func (a , b * lkproto.AgentVersion ) int {
785- return a .CreatedAt .AsTime ().Compare (b .CreatedAt .AsTime ())
789+ return b .CreatedAt .AsTime ().Compare (a .CreatedAt .AsTime ())
786790 })
787791 for _ , version := range versions .Versions {
788- table .Row (version .Version , fmt .Sprintf ("%t" , version .Current ), fmt . Sprintf ( "%v" , version .CreatedAt .AsTime ().Format (time .RFC3339 ) ))
792+ table .Row (version .Version , fmt .Sprintf ("%t" , version .Current ), version .CreatedAt .AsTime ().Format (time .RFC3339 ))
789793 }
790794
791795 fmt .Println (table )
@@ -830,25 +834,34 @@ func listAgents(ctx context.Context, cmd *cli.Command) error {
830834 return nil
831835 }
832836
837+ slices .SortFunc (items , func (a , b * lkproto.AgentInfo ) int {
838+ return b .DeployedAt .AsTime ().Compare (a .DeployedAt .AsTime ())
839+ })
840+
833841 var rows [][]string
834842 for _ , agent := range items {
835843 var regions []string
836844 for _ , regionalAgent := range agent .AgentDeployments {
837845 regions = append (regions , regionalAgent .Region )
838846 }
839- rows = append (rows , []string {agent .AgentId , strings .Join (regions , "," )})
847+ rows = append (rows , []string {
848+ agent .AgentId ,
849+ strings .Join (regions , "," ),
850+ agent .Version ,
851+ agent .DeployedAt .AsTime ().Format (time .RFC3339 ),
852+ })
840853 }
841854
842855 t := util .CreateTable ().
843- Headers ("ID" , "Regions" ).
856+ Headers ("ID" , "Regions" , "Version" , "Deployed At" ).
844857 Rows (rows ... )
845858
846859 fmt .Println (t )
847860 return nil
848861}
849862
850863func listAgentSecrets (ctx context.Context , cmd * cli.Command ) error {
851- agentID , err := getAgentID (cmd , workingDir , tomlFilename )
864+ agentID , err := getAgentID (ctx , cmd , workingDir , tomlFilename )
852865 if err != nil {
853866 return err
854867 }
@@ -883,7 +896,7 @@ func listAgentSecrets(ctx context.Context, cmd *cli.Command) error {
883896}
884897
885898func updateAgentSecrets (ctx context.Context , cmd * cli.Command ) error {
886- agentID , err := getAgentID (cmd , workingDir , tomlFilename )
899+ agentID , err := getAgentID (ctx , cmd , workingDir , tomlFilename )
887900 if err != nil {
888901 return err
889902 }
@@ -917,31 +930,76 @@ func updateAgentSecrets(ctx context.Context, cmd *cli.Command) error {
917930 return fmt .Errorf ("failed to update agent secrets: %s" , resp .Message )
918931}
919932
920- func getAgentID (cmd * cli.Command , agentDir string , tomlFileName string ) (string , error ) {
933+ func getAgentID (ctx context. Context , cmd * cli.Command , agentDir string , tomlFileName string ) (string , error ) {
921934 agentID := cmd .String ("id" )
922935 if agentID == "" {
923936 configExists , err := requireConfig (agentDir , tomlFileName )
924937 if err != nil && configExists {
925938 return "" , err
926939 }
927- if ! configExists {
928- return "" , fmt .Errorf ("config file [%s] required to update agent" , tomlFileName )
929- }
930- if ! lkConfig .HasAgent () {
931- return "" , fmt .Errorf ("no agent config found in [%s]" , tomlFileName )
932- }
933940
934- agentID = lkConfig .Agent .ID
941+ if configExists {
942+ if ! lkConfig .HasAgent () {
943+ return "" , fmt .Errorf ("no agent config found in [%s]" , tomlFilename )
944+ }
945+ agentID = lkConfig .Agent .ID
946+ } else {
947+ agentID , err = selectAgent (ctx , cmd )
948+ if err != nil {
949+ return "" , err
950+ }
951+ }
935952 }
936953
937954 if agentID == "" {
938955 // shouldn't happen, but check to ensure we have a name
939- return "" , fmt .Errorf ("agent ID or %s required" , tomlFileName )
956+ return "" , fmt .Errorf ("agent ID or [%s] required" , util . Accented ( tomlFileName ) )
940957 }
941958
959+ fmt .Printf ("Using agent [%s]\n " , util .Accented (agentID ))
960+
942961 return agentID , nil
943962}
944963
964+ func selectAgent (ctx context.Context , _ * cli.Command ) (string , error ) {
965+ var agents * lkproto.ListAgentsResponse
966+ var err error
967+
968+ util .Await ("No agent ID provided, selecting from available agents..." , func () {
969+ agents , err = agentsClient .ListAgents (ctx , & lkproto.ListAgentsRequest {})
970+ })
971+ if err != nil {
972+ if twerr , ok := err .(twirp.Error ); ok {
973+ if twerr .Code () == twirp .PermissionDenied {
974+ return "" , fmt .Errorf ("agent hosting is disabled for this project -- join the beta program here [%s]" , cloudAgentsBetaSignupURL )
975+ }
976+ }
977+ return "" , err
978+ }
979+
980+ if len (agents .Agents ) == 0 {
981+ return "" , fmt .Errorf ("no agents found" )
982+ }
983+
984+ var agentNames []huh.Option [string ]
985+ for _ , agent := range agents .Agents {
986+ name := agent .AgentId + " " + util .Dimmed ("deployed " + agent .DeployedAt .AsTime ().Format (time .RFC3339 ))
987+ agentNames = append (agentNames , huh.Option [string ]{Key : name , Value : agent .AgentId })
988+ }
989+
990+ var selectedAgent string
991+ if err := huh .NewSelect [string ]().
992+ Title ("Select an agent" ).
993+ Options (agentNames ... ).
994+ Value (& selectedAgent ).
995+ WithTheme (util .Theme ).
996+ Run (); err != nil {
997+ return "" , err
998+ }
999+
1000+ return selectedAgent , nil
1001+ }
1002+
9451003func requireSecrets (_ context.Context , cmd * cli.Command , required , lazy bool ) ([]* lkproto.AgentSecret , error ) {
9461004 silent := cmd .Bool ("silent" )
9471005 secrets := make (map [string ]* lkproto.AgentSecret )
0 commit comments