@@ -41,12 +41,18 @@ type ProjectConfig struct {
4141 YoloMode bool `json:"yolo_mode"`
4242}
4343
44+ type ToolConfig struct {
45+ CurrentModel string `json:"current_model"`
46+ Models []ModelConfig `json:"models"`
47+ }
48+
4449type AppConfig struct {
45- CurrentModel string `json:"current_model "`
46- ProjectDir string `json:"project_dir"` // Deprecated, kept for migration
47- Models [] ModelConfig `json:"models "`
50+ Claude ToolConfig `json:"claude "`
51+ Gemini ToolConfig `json:"gemini"`
52+ Codex ToolConfig `json:"codex "`
4853 Projects []ProjectConfig `json:"projects"`
4954 CurrentProject string `json:"current_project"` // ID of the current project
55+ ActiveTool string `json:"active_tool"` // "claude", "gemini", or "codex"
5056}
5157
5258// NewApp creates a new App application struct
@@ -182,8 +188,8 @@ func (a *App) syncToClaudeSettings(config AppConfig) error {
182188 settingsPath := filepath .Join (claudeDir , "settings.json" )
183189
184190 var selectedModel * ModelConfig
185- for _ , m := range config .Models {
186- if m .ModelName == config .CurrentModel {
191+ for _ , m := range config .Claude . Models {
192+ if m .ModelName == config .Claude . CurrentModel {
187193 selectedModel = & m
188194 break
189195 }
@@ -294,7 +300,7 @@ func (a *App) getConfigPath() (string, error) {
294300 if err != nil {
295301 return "" , err
296302 }
297- return filepath .Join (home , ".claude_model_config .json" ), nil
303+ return filepath .Join (home , ".aicoder_config .json" ), nil
298304}
299305
300306func (a * App ) LoadConfig () (AppConfig , error ) {
@@ -303,10 +309,75 @@ func (a *App) LoadConfig() (AppConfig, error) {
303309 return AppConfig {}, err
304310 }
305311
312+ // Helper for default models
313+ defaultClaudeModels := []ModelConfig {
314+ {ModelName : "GLM" , ModelUrl : "https://open.bigmodel.cn/api/anthropic" , ApiKey : "" },
315+ {ModelName : "kimi" , ModelUrl : "https://api.kimi.com/coding" , ApiKey : "" },
316+ {ModelName : "doubao" , ModelUrl : "https://ark.cn-beijing.volces.com/api/coding" , ApiKey : "" },
317+ {ModelName : "MiniMax" , ModelUrl : "https://api.minimaxi.com/anthropic" , ApiKey : "" },
318+ {ModelName : "Custom" , ModelUrl : "" , ApiKey : "" , IsCustom : true },
319+ }
320+ defaultGeminiModels := []ModelConfig {
321+ {ModelName : "Gemini 1.5 Pro" , ModelUrl : "" , ApiKey : "" },
322+ {ModelName : "Gemini 1.5 Flash" , ModelUrl : "" , ApiKey : "" },
323+ }
324+ defaultCodexModels := []ModelConfig {
325+ {ModelName : "Codex" , ModelUrl : "" , ApiKey : "" },
326+ }
327+
306328 if _ , err := os .Stat (path ); os .IsNotExist (err ) {
307- // Create default config
329+ // Check for old config file for migration
308330 home , _ := os .UserHomeDir ()
331+ oldPath := filepath .Join (home , ".claude_model_config.json" )
332+ if _ , err := os .Stat (oldPath ); err == nil {
333+ // Migrate old config
334+ data , err := os .ReadFile (oldPath )
335+ if err == nil {
336+ var oldConfig struct {
337+ CurrentModel string `json:"current_model"`
338+ Models []ModelConfig `json:"models"`
339+ Projects []ProjectConfig `json:"projects"`
340+ CurrentProj string `json:"current_project"`
341+ }
342+ if err := json .Unmarshal (data , & oldConfig ); err == nil {
343+ config := AppConfig {
344+ Claude : ToolConfig {
345+ CurrentModel : oldConfig .CurrentModel ,
346+ Models : oldConfig .Models ,
347+ },
348+ Gemini : ToolConfig {
349+ CurrentModel : "Gemini 1.5 Pro" ,
350+ Models : defaultGeminiModels ,
351+ },
352+ Codex : ToolConfig {
353+ CurrentModel : "Codex" ,
354+ Models : defaultCodexModels ,
355+ },
356+ Projects : oldConfig .Projects ,
357+ CurrentProject : oldConfig .CurrentProj ,
358+ ActiveTool : "claude" ,
359+ }
360+ a .SaveConfig (config )
361+ // Optional: os.Remove(oldPath)
362+ return config , nil
363+ }
364+ }
365+ }
366+
367+ // Create default config
309368 defaultConfig := AppConfig {
369+ Claude : ToolConfig {
370+ CurrentModel : "GLM" ,
371+ Models : defaultClaudeModels ,
372+ },
373+ Gemini : ToolConfig {
374+ CurrentModel : "Gemini 1.5 Pro" ,
375+ Models : defaultGeminiModels ,
376+ },
377+ Codex : ToolConfig {
378+ CurrentModel : "Codex" ,
379+ Models : defaultCodexModels ,
380+ },
310381 Projects : []ProjectConfig {
311382 {
312383 Id : "default" ,
@@ -316,37 +387,7 @@ func (a *App) LoadConfig() (AppConfig, error) {
316387 },
317388 },
318389 CurrentProject : "default" ,
319- Models : []ModelConfig {
320- {
321- ModelName : "GLM" ,
322- ModelUrl : "https://open.bigmodel.cn/api/anthropic" ,
323- ApiKey : "" ,
324- },
325- {
326- ModelName : "kimi" ,
327- ModelUrl : "https://api.kimi.com/coding" ,
328- ApiKey : "" ,
329- },
330- {
331- ModelName : "doubao" ,
332- ModelUrl : "https://ark.cn-beijing.volces.com/api/coding" ,
333- ApiKey : "" ,
334- },
335- {
336- ModelName : "MiniMax" ,
337- ModelUrl : "https://api.minimaxi.com/anthropic" ,
338- ApiKey : "" ,
339- },
340- {
341- ModelName : "Custom" ,
342- ModelUrl : "" ,
343- ApiKey : "" ,
344- IsCustom : true ,
345- },
346- },
347- }
348- if len (defaultConfig .Models ) > 0 {
349- defaultConfig .CurrentModel = defaultConfig .Models [0 ].ModelName
390+ ActiveTool : "claude" ,
350391 }
351392
352393 err = a .SaveConfig (defaultConfig )
@@ -364,110 +405,20 @@ func (a *App) LoadConfig() (AppConfig, error) {
364405 return config , err
365406 }
366407
367- if config .CurrentModel == "" && len (config .Models ) > 0 {
368- config .CurrentModel = config .Models [0 ].ModelName
369- }
370-
371- // Migration: If Projects list is empty but ProjectDir exists
372- if len (config .Projects ) == 0 {
373- pDir := config .ProjectDir
374- if pDir == "" {
375- pDir , _ = os .UserHomeDir ()
376- }
377- config .Projects = []ProjectConfig {
378- {
379- Id : "default" ,
380- Name : "Project 1" ,
381- Path : pDir ,
382- YoloMode : false , // Default to false for safety
383- },
384- }
385- config .CurrentProject = "default"
386- }
387-
388- // Ensure CurrentProject is valid
389- validProj := false
390- for _ , p := range config .Projects {
391- if p .Id == config .CurrentProject {
392- validProj = true
393- break
394- }
395- }
396- if ! validProj && len (config .Projects ) > 0 {
397- config .CurrentProject = config .Projects [0 ].Id
408+ // Ensure defaults for new fields
409+ if config .Claude .CurrentModel == "" && len (config .Claude .Models ) > 0 {
410+ config .Claude .CurrentModel = config .Claude .Models [0 ].ModelName
398411 }
399-
400- // Ensure ModelUrls are populated and migrate names for existing configs
401- hasCustom := false
402- hasMiniMax := false
403- for i := range config .Models {
404- // Migrate to "GLM" for display
405- lowerName := strings .ToLower (config .Models [i ].ModelName )
406- if lowerName == "glm" || lowerName == "glm-4.7" {
407- config .Models [i ].ModelName = "GLM"
408- if strings .ToLower (config .CurrentModel ) == "glm" || strings .ToLower (config .CurrentModel ) == "glm-4.7" {
409- config .CurrentModel = "GLM"
410- }
411- }
412-
413- if lowerName == "minimax" {
414- hasMiniMax = true
415- config .Models [i ].ModelName = "MiniMax"
416- if strings .ToLower (config .CurrentModel ) == "minimax" {
417- config .CurrentModel = "MiniMax"
418- }
419- }
420-
421- if config .Models [i ].IsCustom || config .Models [i ].ModelName == "Custom" {
422- hasCustom = true
423- config .Models [i ].IsCustom = true
424- }
425- if config .Models [i ].ModelUrl == "" {
426- switch strings .ToLower (config .Models [i ].ModelName ) {
427- case "glm" , "glm-4.7" :
428- config .Models [i ].ModelUrl = "https://open.bigmodel.cn/api/anthropic"
429- case "kimi" :
430- config .Models [i ].ModelUrl = "https://api.kimi.com/coding"
431- case "doubao" :
432- config .Models [i ].ModelUrl = "https://ark.cn-beijing.volces.com/api/coding"
433- case "minimax" :
434- config .Models [i ].ModelUrl = "https://api.minimaxi.com/anthropic"
435- }
436- }
412+ if config .Gemini .Models == nil {
413+ config .Gemini .Models = defaultGeminiModels
414+ config .Gemini .CurrentModel = "Gemini 1.5 Pro"
437415 }
438-
439- if ! hasMiniMax {
440- // Insert MiniMax before Custom if Custom exists, otherwise append
441- newModels := []ModelConfig {}
442- inserted := false
443- for _ , m := range config .Models {
444- if (m .IsCustom || m .ModelName == "Custom" ) && ! inserted {
445- newModels = append (newModels , ModelConfig {
446- ModelName : "MiniMax" ,
447- ModelUrl : "https://api.minimaxi.com/anthropic" ,
448- ApiKey : "your_minimax_api_key_here" ,
449- })
450- inserted = true
451- }
452- newModels = append (newModels , m )
453- }
454- if ! inserted {
455- newModels = append (newModels , ModelConfig {
456- ModelName : "MiniMax" ,
457- ModelUrl : "https://api.minimaxi.com/anthropic" ,
458- ApiKey : "your_minimax_api_key_here" ,
459- })
460- }
461- config .Models = newModels
416+ if config .Codex .Models == nil {
417+ config .Codex .Models = defaultCodexModels
418+ config .Codex .CurrentModel = "Codex"
462419 }
463-
464- if ! hasCustom {
465- config .Models = append (config .Models , ModelConfig {
466- ModelName : "Custom" ,
467- ModelUrl : "" ,
468- ApiKey : "" ,
469- IsCustom : true ,
470- })
420+ if config .ActiveTool == "" {
421+ config .ActiveTool = "claude"
471422 }
472423
473424 return config , nil
0 commit comments