@@ -89,33 +89,38 @@ export function normalizeModel(model: string | undefined): string {
8989 return "gpt-5.4-mini" ;
9090 }
9191
92- // 6. GPT-5.4 (general purpose)
92+ // 6. GPT-5.4 Nano (first-class model)
93+ if ( / \b g p t (?: - | ) 5 \. 4 (?: - | ) n a n o (?: \b | [ - ] ) / . test ( normalized ) ) {
94+ return "gpt-5.4-nano" ;
95+ }
96+
97+ // 7. GPT-5.4 (general purpose)
9398 if ( / \b g p t (?: - | ) 5 \. 4 (?: \b | [ - ] ) / . test ( normalized ) ) {
9499 return "gpt-5.4" ;
95100 }
96101
97- // 7 . GPT-5.2 (general purpose)
102+ // 8 . GPT-5.2 (general purpose)
98103 if ( normalized . includes ( "gpt-5.2" ) || normalized . includes ( "gpt 5.2" ) ) {
99104 return "gpt-5.2" ;
100105 }
101106
102- // 8 . GPT-5.1 Codex Max
107+ // 9 . GPT-5.1 Codex Max
103108 if (
104109 normalized . includes ( "gpt-5.1-codex-max" ) ||
105110 normalized . includes ( "gpt 5.1 codex max" )
106111 ) {
107112 return "gpt-5.1-codex-max" ;
108113 }
109114
110- // 9 . GPT-5.1 Codex Mini
115+ // 10 . GPT-5.1 Codex Mini
111116 if (
112117 normalized . includes ( "gpt-5.1-codex-mini" ) ||
113118 normalized . includes ( "gpt 5.1 codex mini" )
114119 ) {
115120 return "gpt-5.1-codex-mini" ;
116121 }
117122
118- // 10 . Legacy Codex Mini
123+ // 11 . Legacy Codex Mini
119124 if (
120125 normalized . includes ( "codex-mini-latest" ) ||
121126 normalized . includes ( "gpt-5-codex-mini" ) ||
@@ -124,33 +129,33 @@ export function normalizeModel(model: string | undefined): string {
124129 return "gpt-5.1-codex-mini" ;
125130 }
126131
127- // 11 . GPT-5 Codex canonical + GPT-5.1 Codex legacy alias
132+ // 12 . GPT-5 Codex canonical + GPT-5.1 Codex legacy alias
128133 if (
129134 normalized . includes ( "gpt-5-codex" ) ||
130135 normalized . includes ( "gpt 5 codex" )
131136 ) {
132137 return "gpt-5-codex" ;
133138 }
134139
135- // 12 . GPT-5.1 Codex (legacy alias)
140+ // 13 . GPT-5.1 Codex (legacy alias)
136141 if (
137142 normalized . includes ( "gpt-5.1-codex" ) ||
138143 normalized . includes ( "gpt 5.1 codex" )
139144 ) {
140145 return "gpt-5-codex" ;
141146 }
142147
143- // 13 . GPT-5.1 (general-purpose)
148+ // 14 . GPT-5.1 (general-purpose)
144149 if ( normalized . includes ( "gpt-5.1" ) || normalized . includes ( "gpt 5.1" ) ) {
145150 return "gpt-5.1" ;
146151 }
147152
148- // 14 . GPT-5 Codex family (any other variant with "codex")
153+ // 15 . GPT-5 Codex family (any other variant with "codex")
149154 if ( normalized . includes ( "codex" ) ) {
150155 return "gpt-5-codex" ;
151156 }
152157
153- // 15 . GPT-5 family (any variant) - default to 5.4 latest general model
158+ // 16 . GPT-5 family (any variant) - default to 5.4 latest general model
154159 if ( normalized . includes ( "gpt-5" ) || normalized . includes ( "gpt 5" ) ) {
155160 return "gpt-5.4" ;
156161 }
@@ -480,11 +485,15 @@ export function getReasoningConfig(
480485 // GPT-5.4 Mini is a first-class explicit model.
481486 const isGpt54Mini = canonicalModelName === "gpt-5.4-mini" ;
482487
488+ // GPT-5.4 Nano is a first-class explicit model.
489+ const isGpt54Nano = canonicalModelName === "gpt-5.4-nano" ;
490+
483491 // GPT-5.4 general purpose (latest default family)
484492 const isGpt54General =
485493 ( normalizedName . includes ( "gpt-5.4" ) || normalizedName . includes ( "gpt 5.4" ) ) &&
486494 ! isGpt54Pro &&
487- ! isGpt54Mini ;
495+ ! isGpt54Mini &&
496+ ! isGpt54Nano ;
488497
489498 // GPT-5.2 general purpose (not codex variant)
490499 const isGpt52General =
@@ -493,6 +502,7 @@ export function getReasoningConfig(
493502 const canonicalSupportsXhigh =
494503 canonicalModelName === "gpt-5.4" ||
495504 canonicalModelName === "gpt-5.4-mini" ||
505+ canonicalModelName === "gpt-5.4-nano" ||
496506 canonicalModelName === "gpt-5.4-pro" ||
497507 canonicalModelName === "gpt-5.2" ;
498508 const isCodexMax =
@@ -502,6 +512,7 @@ export function getReasoningConfig(
502512 const isCodex = normalizedName . includes ( "codex" ) && ! isCodexMini ;
503513 const isLightweight =
504514 ! isGpt54Mini &&
515+ ! isGpt54Nano &&
505516 ! isCodexMini &&
506517 / \b g p t (?: - | ) 5 (?: - | ) (?: m i n i | n a n o ) (?: \b | [ - ] ) / . test ( normalizedName ) ;
507518
@@ -525,6 +536,7 @@ export function getReasoningConfig(
525536 const supportsXhigh =
526537 isGpt54General ||
527538 isGpt54Mini ||
539+ isGpt54Nano ||
528540 isGpt54Pro ||
529541 isGpt52General ||
530542 isGpt53Codex ||
@@ -544,6 +556,7 @@ export function getReasoningConfig(
544556 const supportsNone =
545557 isGpt54General ||
546558 isGpt54Mini ||
559+ isGpt54Nano ||
547560 isGpt52General ||
548561 ( isGpt51General && ! isLightweight ) ;
549562
@@ -596,6 +609,12 @@ export function getReasoningConfig(
596609 effort = "low" ;
597610 }
598611
612+ // GPT-5.4 Pro only supports medium/high/xhigh reasoning
613+ if ( isGpt54Pro && effort === "low" ) {
614+ logWarn ( "GPT-5.4 Pro supports medium/high/xhigh only; coercing 'low' to 'medium'" ) ;
615+ effort = "medium" ;
616+ }
617+
599618 // Normalize "minimal" to "low" for Codex families
600619 // Codex CLI presets are low/medium/high (or xhigh for Codex Max / GPT-5.3/5.2 Codex)
601620 if ( isCodex && effort === "minimal" ) {
0 commit comments