@@ -139,124 +139,167 @@ func runConfigInit(cmd *cobra.Command, _ []string) error {
139139}
140140
141141func runConfigShow (cmd * cobra.Command , _ []string ) error {
142- if ! cfgMgr .Exists () {
143- color .Yellow ("No configuration found. Run 'cco config init' or 'cco config generate' to create one." )
144- return nil
145- }
146-
147- cfg , err := cfgMgr .Load ()
148- if err != nil {
149- return fmt .Errorf ("failed to load configuration: %w" , err )
150- }
151-
152- color .Blue ("Current Configuration:" )
153- fmt .Printf (" %-15s: %s\n " , "Host" , cfg .Host )
154- fmt .Printf (" %-15s: %d\n " , "Port" , cfg .Port )
155- fmt .Printf (" %-15s: %s\n " , "API Key" , maskString (cfg .APIKey ))
156- fmt .Printf (" %-15s: %s\n " , "Config Path" , cfgMgr .GetPath ())
157-
158- // Show config file type
159- configType := "JSON"
160- if cfgMgr .HasYAML () {
161- configType = "YAML"
162- }
163-
164- fmt .Printf (" %-15s: %s\n " , "Format" , configType )
165-
166- fmt .Println ("\n Providers:" )
167-
168- for _ , provider := range cfg .Providers {
169- fmt .Printf (" - Name: %s\n " , provider .Name )
170- fmt .Printf (" URL: %s\n " , provider .APIBase )
171- fmt .Printf (" API Key: %s\n " , maskString (provider .APIKey ))
172-
173- if len (provider .DefaultModels ) > 0 {
174- fmt .Printf (" Default Models: %v\n " , provider .DefaultModels )
175- }
176-
177- if len (provider .ModelWhitelist ) > 0 {
178- fmt .Printf (" Model Whitelist: %v\n " , provider .ModelWhitelist )
179- }
180-
181- if len (provider .Models ) > 0 {
182- fmt .Printf (" Models: %v\n " , provider .Models )
183- }
184-
185- fmt .Println ()
186- }
187-
188- fmt .Println ("Router Configuration:" )
189- fmt .Printf (" %-15s: %s\n " , "Default" , cfg .Router .Default )
190-
191- if cfg .Router .Think != "" {
192- fmt .Printf (" %-15s: %s\n " , "Think" , cfg .Router .Think )
193- }
194-
195- if cfg .Router .Background != "" {
196- fmt .Printf (" %-15s: %s\n " , "Background" , cfg .Router .Background )
197- }
198-
199- if cfg .Router .LongContext != "" {
200- fmt .Printf (" %-15s: %s\n " , "Long Context" , cfg .Router .LongContext )
201- }
202-
203- if cfg .Router .WebSearch != "" {
204- fmt .Printf (" %-15s: %s\n " , "Web Search" , cfg .Router .WebSearch )
205- }
206-
207- return nil
142+ if ! cfgMgr .Exists () {
143+ color .Yellow ("No configuration found. Run 'cco config init' or 'cco config generate' to create one." )
144+ return nil
145+ }
146+
147+ cfg , err := cfgMgr .Load ()
148+ if err != nil {
149+ return fmt .Errorf ("failed to load configuration: %w" , err )
150+ }
151+
152+ color .Blue ("Current Configuration:" )
153+ fmt .Printf (" %-15s: %s\n " , "Host" , cfg .Host )
154+ fmt .Printf (" %-15s: %d\n " , "Port" , cfg .Port )
155+ fmt .Printf (" %-15s: %s\n " , "API Key" , maskString (cfg .APIKey ))
156+ fmt .Printf (" %-15s: %s\n " , "Config Path" , cfgMgr .GetPath ())
157+
158+ // Show config file type
159+ configType := "JSON"
160+ if cfgMgr .HasYAML () {
161+ configType = "YAML"
162+ }
163+ fmt .Printf (" %-15s: %s\n " , "Format" , configType )
164+
165+ // Show domain mappings if present
166+ if len (cfg .DomainMappings ) > 0 {
167+ fmt .Println ("\n Domain Mappings:" )
168+ for domain , provider := range cfg .DomainMappings {
169+ fmt .Printf (" %-15s → %s\n " , domain , provider )
170+ }
171+ }
172+
173+ fmt .Println ("\n Providers:" )
174+ for _ , provider := range cfg .Providers {
175+ fmt .Printf (" - Name: %s\n " , provider .Name )
176+ fmt .Printf (" URL: %s\n " , provider .APIBase )
177+ fmt .Printf (" API Key: %s\n " , maskString (provider .APIKey ))
178+
179+ if len (provider .DefaultModels ) > 0 {
180+ fmt .Printf (" Default Models: %v\n " , provider .DefaultModels )
181+ }
182+
183+ if len (provider .ModelWhitelist ) > 0 {
184+ fmt .Printf (" Model Whitelist: %v\n " , provider .ModelWhitelist )
185+ }
186+
187+ if len (provider .Models ) > 0 {
188+ fmt .Printf (" Models: %v\n " , provider .Models )
189+ }
190+
191+ fmt .Println ()
192+ }
193+
194+ fmt .Println ("Router Configuration:" )
195+ fmt .Printf (" %-15s: %s\n " , "Default" , cfg .Router .Default )
196+
197+ if cfg .Router .Think != "" {
198+ fmt .Printf (" %-15s: %s\n " , "Think" , cfg .Router .Think )
199+ }
200+
201+ if cfg .Router .Background != "" {
202+ fmt .Printf (" %-15s: %s\n " , "Background" , cfg .Router .Background )
203+ }
204+
205+ if cfg .Router .LongContext != "" {
206+ fmt .Printf (" %-15s: %s\n " , "Long Context" , cfg .Router .LongContext )
207+ }
208+
209+ if cfg .Router .WebSearch != "" {
210+ fmt .Printf (" %-15s: %s\n " , "Web Search" , cfg .Router .WebSearch )
211+ }
212+
213+ return nil
208214}
209215
210- func runConfigValidate (cmd * cobra.Command , _ []string ) error {
211- if ! cfgMgr .Exists () {
212- return errors .New ("no configuration found" )
213- }
214-
215- cfg , err := cfgMgr .Load ()
216- if err != nil {
217- return fmt .Errorf ("failed to load configuration: %w" , err )
218- }
219-
220- // Validation logic
221- var validationErrors []string
222-
223- if len (cfg .Providers ) == 0 {
224- validationErrors = append (validationErrors , "no providers configured" )
225- }
226-
227- for i , provider := range cfg .Providers {
228- if provider .Name == "" {
229- validationErrors = append (validationErrors , fmt .Sprintf ("provider %d: name is required" , i ))
230- }
231-
232- if provider .APIBase == "" {
233- validationErrors = append (validationErrors , fmt .Sprintf ("provider %d: API base URL is required" , i ))
234- }
235-
236- if provider .APIKey == "" {
237- validationErrors = append (validationErrors , fmt .Sprintf ("provider %d: API key is required" , i ))
238- }
239- }
240-
241- if cfg .Router .Default == "" {
242- validationErrors = append (validationErrors , "default router model is required" )
243- }
244-
245- if len (validationErrors ) > 0 {
246- color .Red ("Configuration validation failed:" )
247-
248- for _ , err := range validationErrors {
249- fmt .Printf (" - %s\n " , err )
250- }
251216
252- return errors .New ("configuration validation failed" )
253- }
254-
255- color .Green ("Configuration is valid!" )
256-
257- return nil
217+ func runConfigValidate (cmd * cobra.Command , _ []string ) error {
218+ if ! cfgMgr .Exists () {
219+ return errors .New ("no configuration found" )
220+ }
221+
222+ cfg , err := cfgMgr .Load ()
223+ if err != nil {
224+ return fmt .Errorf ("failed to load configuration: %w" , err )
225+ }
226+
227+ // Validation logic
228+ var validationErrors []string
229+
230+ if len (cfg .Providers ) == 0 {
231+ validationErrors = append (validationErrors , "no providers configured" )
232+ }
233+
234+ // Validate providers
235+ providerNames := make (map [string ]bool )
236+ for i , provider := range cfg .Providers {
237+ if provider .Name == "" {
238+ validationErrors = append (validationErrors , fmt .Sprintf ("provider %d: name is required" , i ))
239+ } else {
240+ providerNames [provider .Name ] = true
241+ }
242+
243+ if provider .APIBase == "" {
244+ validationErrors = append (validationErrors , fmt .Sprintf ("provider %d: API base URL is required" , i ))
245+ }
246+
247+ if provider .APIKey == "" {
248+ validationErrors = append (validationErrors , fmt .Sprintf ("provider %d: API key is required" , i ))
249+ }
250+ }
251+
252+ // Validate domain mappings reference valid providers
253+ if len (cfg .DomainMappings ) > 0 {
254+ for domain , providerName := range cfg .DomainMappings {
255+ if domain == "" {
256+ validationErrors = append (validationErrors , "domain mapping: empty domain not allowed" )
257+ continue
258+ }
259+
260+ // Check if referenced provider exists (either in config or built-in)
261+ builtInProviders := map [string ]bool {
262+ "openrouter" : true ,
263+ "openai" : true ,
264+ "anthropic" : true ,
265+ "nvidia" : true ,
266+ "gemini" : true ,
267+ }
268+
269+ if ! providerNames [providerName ] && ! builtInProviders [providerName ] {
270+ validationErrors = append (validationErrors ,
271+ fmt .Sprintf ("domain mapping '%s → %s': provider '%s' not found" ,
272+ domain , providerName , providerName ))
273+ }
274+ }
275+ }
276+
277+ if cfg .Router .Default == "" {
278+ validationErrors = append (validationErrors , "default router model is required" )
279+ }
280+
281+ if len (validationErrors ) > 0 {
282+ color .Red ("Configuration validation failed:" )
283+ for _ , err := range validationErrors {
284+ fmt .Printf (" - %s\n " , err )
285+ }
286+ return errors .New ("configuration validation failed" )
287+ }
288+
289+ color .Green ("Configuration is valid!" )
290+
291+ // Show additional info about domain mappings if present
292+ if len (cfg .DomainMappings ) > 0 {
293+ color .Cyan ("\n Domain mappings configured:" )
294+ for domain , provider := range cfg .DomainMappings {
295+ fmt .Printf (" %s → %s\n " , domain , provider )
296+ }
297+ }
298+
299+ return nil
258300}
259301
302+
260303func runConfigGenerate (cmd * cobra.Command , _ []string ) error {
261304 force , err := cmd .Flags ().GetBool ("force" )
262305 if err != nil {
@@ -276,26 +319,26 @@ func runConfigGenerate(cmd *cobra.Command, _ []string) error {
276319 return nil
277320 }
278321
279- // Generate example YAML config
280- if err := cfgMgr .CreateExampleYAML (); err != nil {
281- return fmt .Errorf ("failed to create example configuration: %w" , err )
282- }
283-
284- color .Green ("Example YAML configuration created: %s" , cfgMgr .GetYAMLPath ())
285- color .Cyan ("\n Next steps:" )
286- fmt .Println ("1. Edit the configuration file to add your API keys" )
287- fmt .Println ("2. Customize provider settings and model whitelists as needed" )
288- fmt .Println ("3. Run 'cco config validate' to check your configuration " )
289- fmt .Println ("4. Start the router with 'cco start' " )
290-
291- color . Yellow ( " \n Note: The configuration includes all 5 supported providers:" )
292- fmt . Println ( "- OpenRouter (access to multiple models) " )
293- fmt .Println ("- OpenAI (GPT models )" )
294- fmt .Println ("- Anthropic (Claude models )" )
295- fmt .Println ("- Nvidia (Nemotron models) " )
296- fmt .Println ("- Google Gemini (Gemini models) " )
297-
298- return nil
322+ // Generate example YAML config
323+ if err := cfgMgr .CreateExampleYAML (); err != nil {
324+ return fmt .Errorf ("failed to create example configuration: %w" , err )
325+ }
326+
327+ color .Green ("Example YAML configuration created: %s" , cfgMgr .GetYAMLPath ())
328+ color .Cyan ("\n Next steps:" )
329+ fmt .Println ("1. Edit the configuration file to add your API keys" )
330+ fmt .Println ("2. Customize provider settings and model whitelists as needed" )
331+ fmt .Println ("3. Configure domain_mappings to route local servers to providers " )
332+ fmt .Println ("4. Run 'cco config validate' to check your configuration " )
333+ fmt . Println ( "5. Start the router with 'cco start'" )
334+
335+ color . Yellow ( " \n Note: The configuration includes: " )
336+ fmt .Println ("- All 5 supported providers (OpenRouter, OpenAI, Anthropic, Nvidia, Gemini )" )
337+ fmt .Println ("- Domain mappings for local model support (localhost, 127.0.0.1, etc. )" )
338+ fmt .Println ("- Example local LM Studio provider configuration " )
339+ fmt .Println ("- Router configuration for different use cases " )
340+
341+ return nil
299342}
300343
301344func maskString (s string ) string {
0 commit comments