Skip to content

Commit ff37ae4

Browse files
authored
feat(agents): confirm default project or choice before agent init (#704)
1 parent 03d2fcf commit ff37ae4

File tree

4 files changed

+54
-19
lines changed

4 files changed

+54
-19
lines changed

cmd/lk/agent.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,11 @@ var (
9292
Usage: "Manage LiveKit Cloud Agents",
9393
Commands: []*cli.Command{
9494
{
95-
Name: "init",
96-
Usage: "Initialize a new LiveKit Cloud agent project",
97-
Before: createAgentClient,
95+
Name: "init",
96+
Usage: "Initialize a new LiveKit Cloud agent project",
97+
Before: func(ctx context.Context, cmd *cli.Command) (context.Context, error) {
98+
return createAgentClientWithOpts(ctx, cmd, confirmProject)
99+
},
98100
Action: initAgent,
99101
MutuallyExclusiveFlags: []cli.MutuallyExclusiveFlags{{
100102
Flags: [][]cli.Flag{{
@@ -326,9 +328,13 @@ var (
326328
)
327329

328330
func createAgentClient(ctx context.Context, cmd *cli.Command) (context.Context, error) {
331+
return createAgentClientWithOpts(ctx, cmd)
332+
}
333+
334+
func createAgentClientWithOpts(ctx context.Context, cmd *cli.Command, opts ...loadOption) (context.Context, error) {
329335
var err error
330336

331-
if _, err := requireProject(ctx, cmd); err != nil {
337+
if _, err := requireProjectWithOpts(ctx, cmd, opts...); err != nil {
332338
return ctx, err
333339
}
334340

@@ -459,8 +465,9 @@ func createAgent(ctx context.Context, cmd *cli.Command) error {
459465
if !cmd.IsSet("project") {
460466
useProject := true
461467
if err := huh.NewForm(huh.NewGroup(huh.NewConfirm().
462-
Title(fmt.Sprintf("Use [%s] (%s) to create agent deployment?", project.Name, project.URL)).
468+
Title(fmt.Sprintf("Use project [%s] (%s) to create agent deployment?", project.Name, project.URL)).
463469
Value(&useProject).
470+
Negative("Select another").
464471
Inline(false).
465472
WithTheme(util.Theme))).
466473
Run(); err != nil {

cmd/lk/app.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ func requireProjectWithOpts(ctx context.Context, cmd *cli.Command, opts ...loadO
131131
// something is wrong with CLI config file
132132
return ctx, err
133133
}
134-
if project, err = loadProjectDetails(cmd); err != nil {
134+
if project, err = loadProjectDetails(cmd, opts...); err != nil {
135135
// something is wrong with project config file
136136
if errors.Is(err, config.ErrInvalidConfig) {
137137
return ctx, err
@@ -159,7 +159,7 @@ func selectProject(ctx context.Context, cmd *cli.Command) (context.Context, erro
159159
Value(&project).
160160
WithTheme(util.Theme))).
161161
Run(); err != nil {
162-
return nil, err
162+
return nil, fmt.Errorf("no project selected: %w", err)
163163
}
164164
fmt.Println("Using project [" + util.Accented(project.Name) + "]")
165165
} else {
@@ -170,12 +170,12 @@ func selectProject(ctx context.Context, cmd *cli.Command) (context.Context, erro
170170
Value(&shouldAuth).
171171
WithTheme(util.Theme))).
172172
Run(); err != nil {
173-
return nil, err
173+
return nil, fmt.Errorf("no project selected: %w", err)
174174
}
175175
if shouldAuth {
176176
initAuth(ctx, cmd)
177177
if err = tryAuthIfNeeded(ctx, cmd); err != nil {
178-
return nil, err
178+
return nil, fmt.Errorf("authentication failed: %w", err)
179179
}
180180
return requireProject(ctx, cmd)
181181
} else {

cmd/lk/utils.go

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@
1515
package main
1616

1717
import (
18+
"context"
1819
"errors"
1920
"fmt"
2021
"maps"
2122
"os"
2223
"strings"
2324

25+
"github.com/charmbracelet/huh"
2426
"github.com/joho/godotenv"
2527
"github.com/twitchtv/twirp"
2628
"github.com/urfave/cli/v3"
@@ -217,21 +219,27 @@ func parseKeyValuePairs(c *cli.Command, flag string) (map[string]string, error)
217219
}
218220

219221
type loadParams struct {
220-
requireURL bool
222+
requireURL bool
223+
confirmProject bool
221224
}
222225

223226
type loadOption func(*loadParams)
224227

225-
var ignoreURL = func(p *loadParams) {
226-
p.requireURL = false
227-
}
228+
var (
229+
ignoreURL = func(p *loadParams) {
230+
p.requireURL = false
231+
}
232+
confirmProject = func(p *loadParams) {
233+
p.confirmProject = true
234+
}
235+
)
228236

229237
// attempt to load connection config, it'll prioritize
230238
// 1. command line flags (or env var)
231239
// 2. config file (by default, livekit.toml)
232240
// 3. default project config
233241
func loadProjectDetails(c *cli.Command, opts ...loadOption) (*config.ProjectConfig, error) {
234-
p := loadParams{requireURL: true}
242+
p := loadParams{requireURL: true, confirmProject: false}
235243
for _, opt := range opts {
236244
opt(&p)
237245
}
@@ -327,9 +335,31 @@ func loadProjectDetails(c *cli.Command, opts ...loadOption) (*config.ProjectConf
327335
// load default project
328336
dp, err := config.LoadDefaultProject()
329337
if err == nil {
330-
if !c.Bool("silent") {
331-
fmt.Println("Using default project [" + util.Theme.Focused.Title.Render(dp.Name) + "]")
332-
logDetails(c, dp)
338+
if p.confirmProject {
339+
if dp != nil && len(cliConfig.Projects) > 1 && !c.Bool("silent") {
340+
useDefault := true
341+
if err := huh.NewForm(huh.NewGroup(huh.NewConfirm().
342+
Title(fmt.Sprintf("Use project [%s] (%s) to create agent?", dp.Name, dp.URL)).
343+
Value(&useDefault).
344+
Negative("Select another").
345+
Inline(false).
346+
WithTheme(util.Theme))).
347+
Run(); err != nil {
348+
return nil, fmt.Errorf("failed to confirm project: %w", err)
349+
}
350+
if !useDefault {
351+
if _, err = selectProject(context.Background(), c); err != nil {
352+
return nil, err
353+
}
354+
fmt.Printf("Using project [%s]\n", util.Accented(project.Name))
355+
return project, nil
356+
}
357+
}
358+
} else {
359+
if !c.Bool("silent") {
360+
fmt.Println("Using default project [" + util.Theme.Focused.Title.Render(dp.Name) + "]")
361+
logDetails(c, dp)
362+
}
333363
}
334364
return dp, nil
335365
}

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,6 @@ github.com/livekit/mageutil v0.0.0-20250511045019-0f1ff63f7731 h1:9x+U2HGLrSw5AT
274274
github.com/livekit/mageutil v0.0.0-20250511045019-0f1ff63f7731/go.mod h1:Rs3MhFwutWhGwmY1VQsygw28z5bWcnEYmS1OG9OxjOQ=
275275
github.com/livekit/mediatransportutil v0.0.0-20250825135402-7bc31f107ade h1:lpxPcglwzUWNB4J0S2qZuyMehzmR7vW9whzSwV4IGoI=
276276
github.com/livekit/mediatransportutil v0.0.0-20250825135402-7bc31f107ade/go.mod h1:mSNtYzSf6iY9xM3UX42VEI+STHvMgHmrYzEHPcdhB8A=
277-
github.com/livekit/protocol v1.42.1-0.20250929175250-2ddfb3ee7f7e h1:yytr+uwFXtJ8UxBV2q3j55jVKg7zslECuGeE4F56NoU=
278-
github.com/livekit/protocol v1.42.1-0.20250929175250-2ddfb3ee7f7e/go.mod h1:vhMS30QoEyH2p34vi6X1eWkC4EMV72ZGZwQb74ajY7A=
279277
github.com/livekit/protocol v1.42.1-0.20251008181454-49a136864c2d h1:ofC+CPiYDZ4LD+RgIJg4rUFLvKnWJqg66bn00FALKLI=
280278
github.com/livekit/protocol v1.42.1-0.20251008181454-49a136864c2d/go.mod h1:vhMS30QoEyH2p34vi6X1eWkC4EMV72ZGZwQb74ajY7A=
281279
github.com/livekit/psrpc v0.7.0 h1:rtfqfjYN06WJYloE/S0nmkJ/Y04x4pxLQLe8kQ4FVHU=

0 commit comments

Comments
 (0)