Go · 2784 bytes Raw Blame History
1 package cmd
2
3 import (
4 "fmt"
5 "os"
6 "path/filepath"
7
8 "parrot/internal/config"
9 "parrot/internal/llm"
10
11 "github.com/spf13/cobra"
12 )
13
14 var firstrunCmd = &cobra.Command{
15 Use: "firstrun",
16 Short: "Check if this is the first run and guide setup",
17 Long: "Detects if parrot needs initial setup and guides the user",
18 Hidden: true, // Hide from help - internal command
19 Run: checkFirstRun,
20 }
21
22 func init() {
23 rootCmd.AddCommand(firstrunCmd)
24 }
25
26 func checkFirstRun(cmd *cobra.Command, args []string) {
27 if isFirstRun() {
28 fmt.Println("🦜 Welcome to Parrot!")
29 fmt.Println("====================")
30 fmt.Println("It looks like this is your first time running parrot.")
31 fmt.Println("Let's get you set up for maximum sass!")
32 fmt.Println()
33
34 fmt.Print("Would you like to run the setup wizard? [Y/n]: ")
35 var response string
36 fmt.Scanln(&response)
37
38 if response == "" || response == "y" || response == "Y" {
39 // Run setup
40 runSetup(cmd, args)
41 } else {
42 fmt.Println("⏭️ Skipped setup.")
43 fmt.Println("💡 Run 'parrot setup' anytime to configure backends.")
44 fmt.Println("🔄 Parrot works with fallback responses right now!")
45 }
46
47 // Mark as not first run
48 markSetupComplete()
49 } else {
50 fmt.Println("✅ Parrot already set up!")
51 fmt.Println("💡 Use 'parrot status' to check current configuration.")
52 }
53 }
54
55 func isFirstRun() bool {
56 // Check multiple indicators of setup completion
57 cfg, err := config.LoadConfig()
58 if err != nil {
59 // No config file found - likely first run
60 return true
61 }
62
63 // Check if any intelligent backend is available
64 manager := llm.NewLLMManager(cfg)
65 status := manager.GetStatus()
66
67 hasAPI := status["api_available"].(bool)
68 hasLocal := status["local_available"].(bool)
69
70 // If no AI backends are working, consider it first run
71 if !hasAPI && !hasLocal {
72 return true
73 }
74
75 // Check for setup marker file
76 markerPath := getSetupMarkerPath()
77 if _, err := os.Stat(markerPath); os.IsNotExist(err) {
78 return true
79 }
80
81 return false
82 }
83
84 func markSetupComplete() {
85 markerPath := getSetupMarkerPath()
86
87 // Create marker directory if needed
88 if err := os.MkdirAll(filepath.Dir(markerPath), 0755); err != nil {
89 return // Fail silently
90 }
91
92 // Create marker file
93 file, err := os.Create(markerPath)
94 if err != nil {
95 return // Fail silently
96 }
97 defer file.Close()
98
99 file.WriteString("setup_complete\n")
100 }
101
102 func getSetupMarkerPath() string {
103 configDir, err := os.UserConfigDir()
104 if err != nil {
105 // Fallback to home directory
106 homeDir, _ := os.UserHomeDir()
107 return filepath.Join(homeDir, ".parrot_setup_complete")
108 }
109 return filepath.Join(configDir, "parrot", ".setup_complete")
110 }
111
112 // IsParrotSetup is a helper function for other commands to check setup status
113 func IsParrotSetup() bool {
114 return !isFirstRun()
115 }