@@ -1231,6 +1231,80 @@ describe("codex bin wrapper", () => {
12311231 ) ;
12321232 } ) ;
12331233
1234+ it ( "honors explicit capture output override for unsupported-model retries" , ( ) => {
1235+ const fixtureRoot = createWrapperFixture ( ) ;
1236+ const stateDir = join ( fixtureRoot , "retry-state-capture-override" ) ;
1237+ mkdirSync ( stateDir , { recursive : true } ) ;
1238+ const fakeBin = createCustomFakeCodexBin ( fixtureRoot , [
1239+ "const fs = require('node:fs');" ,
1240+ "const path = require('node:path');" ,
1241+ "const counterPath = path.join(process.env.CODEX_MULTI_AUTH_TEST_STATE_DIR, 'attempt.txt');" ,
1242+ "const attempt = fs.existsSync(counterPath) ? Number(fs.readFileSync(counterPath, 'utf8')) : 0;" ,
1243+ "fs.writeFileSync(counterPath, String(attempt + 1), 'utf8');" ,
1244+ "const args = process.argv.slice(2);" ,
1245+ "const modelIndex = args.indexOf('--model');" ,
1246+ "const requestedModel = modelIndex >= 0 ? args[modelIndex + 1] : 'unknown-model';" ,
1247+ "if (attempt === 0) {" ,
1248+ ` console.error("ERROR: {\\\"type\\\":\\\"error\\\",\\\"status\\\":400,\\\"error\\\":{\\\"type\\\":\\\"invalid_request_error\\\",\\\"message\\\":\\\"The '" + requestedModel + "' model is not supported when using Codex with a ChatGPT account.\\\"}}");` ,
1249+ " process.exit(1);" ,
1250+ "}" ,
1251+ "console.log(`FORWARDED:${args.join(' ')}`);" ,
1252+ "process.exit(0);" ,
1253+ ] ) ;
1254+ const originalHome = join ( fixtureRoot , "codex-home" ) ;
1255+ mkdirSync ( originalHome , { recursive : true } ) ;
1256+ writeFileSync ( join ( originalHome , "auth.json" ) , "{}\n" , "utf8" ) ;
1257+ writeFileSync ( join ( originalHome , "config.toml" ) , "" , "utf8" ) ;
1258+
1259+ const result = runWrapper ( fixtureRoot , [ "exec" , "status" , "--model" , "gpt-5.5" ] , {
1260+ CODEX_MULTI_AUTH_CAPTURE_FORWARD_OUTPUT : "1" ,
1261+ CODEX_MULTI_AUTH_REAL_CODEX_BIN : fakeBin ,
1262+ CODEX_MULTI_AUTH_TEST_STATE_DIR : stateDir ,
1263+ CODEX_HOME : originalHome ,
1264+ } ) ;
1265+
1266+ const output = combinedOutput ( result ) ;
1267+ expect ( result . status ) . toBe ( 0 ) ;
1268+ expect ( readFileSync ( join ( stateDir , "attempt.txt" ) , "utf8" ) ) . toBe ( "2" ) ;
1269+ expect ( output ) . toContain ( "Retrying with gpt-5.4" ) ;
1270+ expect ( output ) . toContain (
1271+ 'FORWARDED:exec status --model gpt-5.4 -c cli_auth_credentials_store="file"' ,
1272+ ) ;
1273+ } ) ;
1274+
1275+ it ( "can forward without capturing child stdio for terminal-sensitive Codex runs" , ( ) => {
1276+ const fixtureRoot = createWrapperFixture ( ) ;
1277+ const stateDir = join ( fixtureRoot , "no-capture-state" ) ;
1278+ mkdirSync ( stateDir , { recursive : true } ) ;
1279+ const originalHome = join ( fixtureRoot , "codex-home" ) ;
1280+ mkdirSync ( originalHome , { recursive : true } ) ;
1281+ writeFileSync ( join ( originalHome , "config.toml" ) , "" , "utf8" ) ;
1282+ const fakeBin = createCustomFakeCodexBin ( fixtureRoot , [
1283+ "const fs = require('node:fs');" ,
1284+ "const path = require('node:path');" ,
1285+ "const counterPath = path.join(process.env.CODEX_MULTI_AUTH_TEST_STATE_DIR, 'attempt.txt');" ,
1286+ "const attempt = fs.existsSync(counterPath) ? Number(fs.readFileSync(counterPath, 'utf8')) : 0;" ,
1287+ "fs.writeFileSync(counterPath, String(attempt + 1), 'utf8');" ,
1288+ "console.error(\"The 'gpt-5.5' model is not supported when using Codex with a ChatGPT account.\");" ,
1289+ "process.exit(1);" ,
1290+ ] ) ;
1291+
1292+ const result = runWrapper ( fixtureRoot , [ "exec" , "status" , "--model" , "gpt-5.5" ] , {
1293+ CODEX_MULTI_AUTH_CAPTURE_FORWARD_OUTPUT : "0" ,
1294+ CODEX_MULTI_AUTH_REAL_CODEX_BIN : fakeBin ,
1295+ CODEX_MULTI_AUTH_TEST_STATE_DIR : stateDir ,
1296+ CODEX_HOME : originalHome ,
1297+ } ) ;
1298+
1299+ const output = combinedOutput ( result ) ;
1300+ expect ( result . status ) . toBe ( 1 ) ;
1301+ expect ( readFileSync ( join ( stateDir , "attempt.txt" ) , "utf8" ) ) . toBe ( "1" ) ;
1302+ expect ( output ) . toContain (
1303+ "The 'gpt-5.5' model is not supported when using Codex with a ChatGPT account." ,
1304+ ) ;
1305+ expect ( output ) . not . toContain ( "Retrying with gpt-5.4" ) ;
1306+ } ) ;
1307+
12341308 it ( "retries GPT-5.5 after access-denied style model errors" , ( ) => {
12351309 const fixtureRoot = createWrapperFixture ( ) ;
12361310 const stateDir = join ( fixtureRoot , "retry-state-access" ) ;
0 commit comments