@@ -38,6 +38,29 @@ var codexModelMap = map[string]string{
3838 "gpt-5.2-medium" : "gpt-5.2" ,
3939 "gpt-5.2-high" : "gpt-5.2" ,
4040 "gpt-5.2-xhigh" : "gpt-5.2" ,
41+ "gpt-5" : "gpt-5.4" ,
42+ "gpt-5-mini" : "gpt-5.4" ,
43+ "gpt-5-nano" : "gpt-5.4" ,
44+ "gpt-5.1" : "gpt-5.4" ,
45+ "gpt-5.1-codex" : "gpt-5.3-codex" ,
46+ "gpt-5.1-codex-max" : "gpt-5.3-codex" ,
47+ "gpt-5.1-codex-mini" : "gpt-5.3-codex" ,
48+ "gpt-5.2-codex" : "gpt-5.2" ,
49+ "codex-mini-latest" : "gpt-5.3-codex" ,
50+ "gpt-5-codex" : "gpt-5.3-codex" ,
51+ }
52+
53+ var codexVersionModelPrefixes = []struct {
54+ prefix string
55+ target string
56+ }{
57+ {prefix : "gpt-5.3-codex-spark" , target : "gpt-5.3-codex-spark" },
58+ {prefix : "gpt-5.3-codex" , target : "gpt-5.3-codex" },
59+ {prefix : "gpt-5.4-mini" , target : "gpt-5.4-mini" },
60+ {prefix : "gpt-5.4-nano" , target : "gpt-5.4-nano" },
61+ {prefix : "gpt-5.5" , target : "gpt-5.5" },
62+ {prefix : "gpt-5.4" , target : "gpt-5.4" },
63+ {prefix : "gpt-5.2" , target : "gpt-5.2" },
4164}
4265
4366type codexTransformResult struct {
@@ -447,8 +470,19 @@ func normalizeCodexModel(model string) string {
447470 if model == "" {
448471 return "gpt-5.4"
449472 }
473+ if mapped , ok := normalizeKnownCodexModel (model ); ok {
474+ return mapped
475+ }
476+ return model
477+ }
478+
479+ func normalizeKnownCodexModel (model string ) (string , bool ) {
480+ model = strings .TrimSpace (model )
481+ if model == "" {
482+ return "" , false
483+ }
450484 if isOpenAIImageGenerationModel (model ) {
451- return model
485+ return model , true
452486 }
453487
454488 modelID := model
@@ -457,41 +491,58 @@ func normalizeCodexModel(model string) string {
457491 modelID = parts [len (parts )- 1 ]
458492 }
459493
460- if mapped := getNormalizedCodexModel (modelID ); mapped != "" {
461- return mapped
494+ key := codexModelLookupKey (modelID )
495+ if key == "" {
496+ return "" , false
462497 }
463-
464- normalized := strings .ToLower (modelID )
465-
466- if strings .Contains (normalized , "gpt-5.5" ) || strings .Contains (normalized , "gpt 5.5" ) {
467- return "gpt-5.5"
468- }
469- if strings .Contains (normalized , "gpt-5.4-mini" ) || strings .Contains (normalized , "gpt 5.4 mini" ) {
470- return "gpt-5.4-mini"
471- }
472- if strings .Contains (normalized , "gpt-5.4" ) || strings .Contains (normalized , "gpt 5.4" ) {
473- return "gpt-5.4"
498+ if mapped := getNormalizedCodexModel (key ); mapped != "" {
499+ return mapped , true
474500 }
475- if strings .Contains (normalized , "gpt-5.2" ) || strings .Contains (normalized , "gpt 5.2" ) {
476- return "gpt-5.2"
501+ for _ , item := range codexVersionModelPrefixes {
502+ if key == item .prefix {
503+ return item .target , true
504+ }
505+ suffix , ok := strings .CutPrefix (key , item .prefix + "-" )
506+ if ok && isKnownCodexModelSuffix (suffix ) {
507+ return item .target , true
508+ }
477509 }
478- if strings .Contains (normalized , "gpt-5.3-codex-spark" ) || strings .Contains (normalized , "gpt 5.3 codex spark" ) {
479- return "gpt-5.3-codex-spark"
510+ return "" , false
511+ }
512+
513+ func codexModelLookupKey (modelID string ) string {
514+ modelID = strings .TrimSpace (modelID )
515+ if modelID == "" {
516+ return ""
480517 }
481- if strings .Contains (normalized , "gpt-5.3-codex" ) || strings .Contains (normalized , "gpt 5.3 codex" ) {
482- return "gpt-5.3-codex"
518+ if strings .Contains (modelID , "/" ) {
519+ parts := strings .Split (modelID , "/" )
520+ modelID = parts [len (parts )- 1 ]
483521 }
484- if strings .Contains (normalized , "gpt-5.3" ) || strings .Contains (normalized , "gpt 5.3" ) {
485- return "gpt-5.3-codex"
522+ return strings .ToLower (strings .Join (strings .Fields (modelID ), "-" ))
523+ }
524+
525+ func isKnownCodexModelSuffix (suffix string ) bool {
526+ switch suffix {
527+ case "none" , "minimal" , "low" , "medium" , "high" , "xhigh" :
528+ return true
486529 }
487- if strings .Contains (normalized , "codex" ) {
488- return "gpt-5.3-codex"
530+ return isCodexDateSuffix (suffix )
531+ }
532+
533+ func isCodexDateSuffix (suffix string ) bool {
534+ parts := strings .Split (suffix , "-" )
535+ if len (parts ) != 3 || len (parts [0 ]) != 4 || len (parts [1 ]) != 2 || len (parts [2 ]) != 2 {
536+ return false
489537 }
490- if strings .Contains (normalized , "gpt-5" ) || strings .Contains (normalized , "gpt 5" ) {
491- return "gpt-5.4"
538+ for _ , part := range parts {
539+ for _ , r := range part {
540+ if r < '0' || r > '9' {
541+ return false
542+ }
543+ }
492544 }
493-
494- return "gpt-5.4"
545+ return true
495546}
496547
497548func isCodexSparkModel (model string ) bool {
@@ -789,18 +840,13 @@ func SupportsVerbosity(model string) bool {
789840}
790841
791842func getNormalizedCodexModel (modelID string ) string {
792- if modelID == "" {
843+ key := codexModelLookupKey (modelID )
844+ if key == "" {
793845 return ""
794846 }
795- if mapped , ok := codexModelMap [modelID ]; ok {
847+ if mapped , ok := codexModelMap [key ]; ok {
796848 return mapped
797849 }
798- lower := strings .ToLower (modelID )
799- for key , value := range codexModelMap {
800- if strings .ToLower (key ) == lower {
801- return value
802- }
803- }
804850 return ""
805851}
806852
0 commit comments