@@ -11,37 +11,28 @@ import (
11
11
"github.com/spf13/viper"
12
12
)
13
13
14
- // ProviderConfig holds the configuration for a single LLM provider.
15
14
type ProviderConfig struct {
16
15
APIKey string `mapstructure:"api_key"`
17
16
Model string `mapstructure:"model"`
18
17
}
19
18
20
- // Config is the main configuration structure for the application.
21
19
type Config struct {
22
20
Providers map [string ]ProviderConfig `mapstructure:"providers"`
23
21
ActiveProvider string `mapstructure:"active_provider"`
24
22
}
25
23
26
24
var cfg * Config
27
25
28
- // InitConfig initializes the configuration from environment variables and config files.
29
26
func InitConfig () {
30
27
viper .SetConfigName (".lazycommit" )
31
28
viper .SetConfigType ("yaml" )
32
- home , err := os .UserHomeDir ()
33
- if err != nil {
34
- fmt .Println ("Error getting home directory:" , err )
35
- os .Exit (1 )
36
- }
37
- viper .AddConfigPath (home )
38
- viper .AddConfigPath ("." ) // Also look in the current directory
29
+ viper .AddConfigPath (getConfigDir ())
30
+ viper .SetConfigFile (filepath .Join (getConfigDir (), ".lazycommit.yaml" ))
39
31
40
- // Set defaults based on available credentials
41
32
if token , err := LoadGitHubToken (); err == nil && token != "" {
42
33
viper .SetDefault ("active_provider" , "copilot" )
43
34
viper .SetDefault ("providers.copilot.api_key" , token )
44
- viper .SetDefault ("providers.copilot.model" , "openai/gpt-4o" ) // Use GitHub Models format
35
+ viper .SetDefault ("providers.copilot.model" , "openai/gpt-4o" )
45
36
} else {
46
37
viper .SetDefault ("active_provider" , "openai" )
47
38
viper .SetDefault ("providers.openai.model" , "gpt-3.5-turbo" )
@@ -50,7 +41,17 @@ func InitConfig() {
50
41
viper .AutomaticEnv ()
51
42
52
43
if err := viper .ReadInConfig (); err != nil {
53
- if _ , ok := err .(viper.ConfigFileNotFoundError ); ! ok {
44
+ if _ , ok := err .(viper.ConfigFileNotFoundError ); ok {
45
+ cfgDir := getConfigDir ()
46
+ _ = os .MkdirAll (cfgDir , 0o755 )
47
+ cfgPath := filepath .Join (cfgDir , ".lazycommit.yaml" )
48
+ if writeErr := viper .WriteConfigAs (cfgPath ); writeErr != nil {
49
+ fmt .Println ("Error creating default config file:" , writeErr )
50
+ } else {
51
+ fmt .Printf ("Created default config at %s\n " , cfgPath )
52
+ }
53
+ _ = viper .ReadInConfig ()
54
+ } else {
54
55
fmt .Println ("Error reading config file:" , err )
55
56
}
56
57
}
@@ -61,15 +62,13 @@ func InitConfig() {
61
62
}
62
63
}
63
64
64
- // GetProvider returns the active provider's name.
65
65
func GetProvider () string {
66
66
if cfg == nil {
67
67
InitConfig ()
68
68
}
69
69
return cfg .ActiveProvider
70
70
}
71
71
72
- // GetActiveProviderConfig returns the configuration for the currently active provider.
73
72
func GetActiveProviderConfig () (* ProviderConfig , error ) {
74
73
if cfg == nil {
75
74
InitConfig ()
@@ -82,7 +81,6 @@ func GetActiveProviderConfig() (*ProviderConfig, error) {
82
81
return & providerConfig , nil
83
82
}
84
83
85
- // GetAPIKey returns the API key for the active provider.
86
84
func GetAPIKey () (string , error ) {
87
85
if cfg == nil {
88
86
InitConfig ()
@@ -115,7 +113,6 @@ func GetAPIKey() (string, error) {
115
113
return apiKey , nil
116
114
}
117
115
118
- // GetModel returns the model for the active provider.
119
116
func GetModel () (string , error ) {
120
117
providerConfig , err := GetActiveProviderConfig ()
121
118
if err != nil {
@@ -127,7 +124,6 @@ func GetModel() (string, error) {
127
124
return providerConfig .Model , nil
128
125
}
129
126
130
- // SetProvider sets the active provider and saves the config.
131
127
func SetProvider (provider string ) error {
132
128
if cfg == nil {
133
129
InitConfig ()
@@ -137,7 +133,6 @@ func SetProvider(provider string) error {
137
133
return viper .WriteConfig ()
138
134
}
139
135
140
- // SetModel sets the model for the active provider and saves the config.
141
136
func SetModel (model string ) error {
142
137
if cfg == nil {
143
138
InitConfig ()
@@ -147,7 +142,6 @@ func SetModel(model string) error {
147
142
return viper .WriteConfig ()
148
143
}
149
144
150
- // SetAPIKey sets the API key for a specific provider and saves the config.
151
145
func SetAPIKey (provider , apiKey string ) error {
152
146
if cfg == nil {
153
147
InitConfig ()
@@ -156,23 +150,17 @@ func SetAPIKey(provider, apiKey string) error {
156
150
return viper .WriteConfig ()
157
151
}
158
152
159
- // LoadGitHubToken tries to load a GitHub token with models scope from standard locations.
160
153
func LoadGitHubToken () (string , error ) {
161
- // First check environment variable (recommended approach)
162
154
if token := os .Getenv ("GITHUB_TOKEN" ); token != "" {
163
155
return token , nil
164
156
}
165
157
166
- // Also check for a GitHub Models specific token
167
158
if token := os .Getenv ("GITHUB_MODELS_TOKEN" ); token != "" {
168
159
return token , nil
169
160
}
170
161
171
- // Fallback: try to find tokens from GitHub Copilot IDE installations
172
- // Note: These tokens may not have the required 'models' scope
173
162
configDir := getConfigDir ()
174
163
175
- // Try both hosts.json and apps.json files
176
164
filePaths := []string {
177
165
filepath .Join (configDir , "github-copilot" , "hosts.json" ),
178
166
filepath .Join (configDir , "github-copilot" , "apps.json" ),
0 commit comments