@@ -940,7 +940,6 @@ function createBuiltinProxyRuntimeController(deps = {}) {
940940 'n' ,
941941 'modalities' ,
942942 'audio' ,
943- 'reasoning' ,
944943 'reasoning_effort' ,
945944 'service_tier'
946945 ] ;
@@ -964,10 +963,15 @@ function createBuiltinProxyRuntimeController(deps = {}) {
964963 if ( isRecord ( source . text ) && asTrimmedString ( source . text . verbosity ) ) {
965964 chatBody . verbosity = asTrimmedString ( source . text . verbosity ) ;
966965 }
966+ if ( isRecord ( source . reasoning ) && asTrimmedString ( source . reasoning . effort ) ) {
967+ chatBody . reasoning_effort = asTrimmedString ( source . reasoning . effort ) ;
968+ }
967969
968970 pruneInvalidChatToolChoice ( chatBody ) ;
969971
970- if ( Object . prototype . hasOwnProperty . call ( source , 'max_tokens' ) ) {
972+ if ( Object . prototype . hasOwnProperty . call ( source , 'max_completion_tokens' ) ) {
973+ chatBody . max_tokens = Math . max ( 128 , Number ( source . max_completion_tokens ) || 0 ) ;
974+ } else if ( Object . prototype . hasOwnProperty . call ( source , 'max_tokens' ) ) {
971975 chatBody . max_tokens = source . max_tokens ;
972976 } else if ( source . max_output_tokens != null ) {
973977 chatBody . max_tokens = source . max_output_tokens ;
@@ -976,6 +980,18 @@ function createBuiltinProxyRuntimeController(deps = {}) {
976980 return chatBody ;
977981 }
978982
983+ function normalizeResponsesPayloadForUpstream ( payload , stream ) {
984+ const source = isRecord ( payload ) ? payload : { } ;
985+ const normalized = { ...source , stream } ;
986+ if ( isRecord ( source . reasoning ) ) {
987+ const include = Array . isArray ( source . include ) ? source . include . filter ( ( item ) => typeof item === 'string' ) : [ ] ;
988+ if ( ! include . includes ( 'reasoning.encrypted_content' ) ) {
989+ normalized . include = [ ...include , 'reasoning.encrypted_content' ] ;
990+ }
991+ }
992+ return normalized ;
993+ }
994+
979995 function ensureResponseMetadata ( payload ) {
980996 const base = payload && typeof payload === 'object' && ! Array . isArray ( payload ) ? payload : { } ;
981997 const id = typeof base . id === 'string' && base . id . trim ( )
@@ -1001,6 +1017,112 @@ function createBuiltinProxyRuntimeController(deps = {}) {
10011017 res . write ( `data: ${ JSON . stringify ( dataObj ) } \n\n` ) ;
10021018 }
10031019
1020+ function buildResponsesSseItem ( item , fallbackId ) {
1021+ const source = isRecord ( item ) ? item : { } ;
1022+ const itemId = asTrimmedString ( source . id || source . call_id ) || fallbackId || `item_${ crypto . randomBytes ( 8 ) . toString ( 'hex' ) } ` ;
1023+ if ( source . type === 'message' ) {
1024+ return {
1025+ ...source ,
1026+ id : itemId ,
1027+ role : source . role || 'assistant' ,
1028+ content : Array . isArray ( source . content )
1029+ ? source . content . map ( ( part ) => {
1030+ if ( ! isRecord ( part ) ) return part ;
1031+ if ( part . type !== 'output_text' ) return cloneJsonValue ( part ) ;
1032+ return {
1033+ ...part ,
1034+ text : typeof part . text === 'string' ? part . text : '' ,
1035+ annotations : Array . isArray ( part . annotations ) ? part . annotations : [ ] ,
1036+ logprobs : Array . isArray ( part . logprobs ) ? part . logprobs : [ ]
1037+ } ;
1038+ } )
1039+ : [ ]
1040+ } ;
1041+ }
1042+ if ( source . type === 'reasoning' ) {
1043+ return {
1044+ ...source ,
1045+ id : itemId ,
1046+ summary : Array . isArray ( source . summary ) ? source . summary : [ ]
1047+ } ;
1048+ }
1049+ if ( source . type === 'function_call' ) {
1050+ return {
1051+ ...source ,
1052+ id : itemId ,
1053+ call_id : asTrimmedString ( source . call_id ) || itemId ,
1054+ name : asTrimmedString ( source . name ) ,
1055+ arguments : typeof source . arguments === 'string' ? source . arguments : ''
1056+ } ;
1057+ }
1058+ if ( source . type === 'custom_tool_call' ) {
1059+ return {
1060+ ...source ,
1061+ id : itemId ,
1062+ call_id : asTrimmedString ( source . call_id ) || itemId ,
1063+ name : asTrimmedString ( source . name ) ,
1064+ input : typeof source . input === 'string' ? source . input : ''
1065+ } ;
1066+ }
1067+ return { ...source , id : itemId } ;
1068+ }
1069+
1070+ function emitResponsesTextPartAdded ( res , itemId , outputIndex , contentIndex , nextSeq ) {
1071+ writeSse ( res , 'response.content_part.added' , {
1072+ type : 'response.content_part.added' ,
1073+ item_id : itemId ,
1074+ output_index : outputIndex ,
1075+ content_index : contentIndex ,
1076+ part : { type : 'output_text' , text : '' , annotations : [ ] , logprobs : [ ] } ,
1077+ sequence_number : nextSeq ( )
1078+ } ) ;
1079+ }
1080+
1081+ function emitResponsesTextPartDone ( res , itemId , outputIndex , contentIndex , text , nextSeq ) {
1082+ writeSse ( res , 'response.content_part.done' , {
1083+ type : 'response.content_part.done' ,
1084+ item_id : itemId ,
1085+ output_index : outputIndex ,
1086+ content_index : contentIndex ,
1087+ part : { type : 'output_text' , text : typeof text === 'string' ? text : '' , annotations : [ ] , logprobs : [ ] } ,
1088+ sequence_number : nextSeq ( )
1089+ } ) ;
1090+ }
1091+
1092+ function emitResponsesToolArgumentEvents ( res , item , outputIndex , nextSeq ) {
1093+ const eventType = item . type === 'custom_tool_call'
1094+ ? 'response.custom_tool_call_input.delta'
1095+ : 'response.function_call_arguments.delta' ;
1096+ const doneType = item . type === 'custom_tool_call'
1097+ ? ''
1098+ : 'response.function_call_arguments.done' ;
1099+ const value = item . type === 'custom_tool_call'
1100+ ? ( typeof item . input === 'string' ? item . input : '' )
1101+ : ( typeof item . arguments === 'string' ? item . arguments : '' ) ;
1102+ if ( value ) {
1103+ writeSse ( res , eventType , {
1104+ type : eventType ,
1105+ item_id : item . id ,
1106+ output_index : outputIndex ,
1107+ call_id : item . call_id ,
1108+ name : item . name ,
1109+ delta : value ,
1110+ sequence_number : nextSeq ( )
1111+ } ) ;
1112+ }
1113+ if ( doneType ) {
1114+ writeSse ( res , doneType , {
1115+ type : doneType ,
1116+ item_id : item . id ,
1117+ output_index : outputIndex ,
1118+ call_id : item . call_id ,
1119+ name : item . name ,
1120+ arguments : value ,
1121+ sequence_number : nextSeq ( )
1122+ } ) ;
1123+ }
1124+ }
1125+
10041126 function sendResponsesSse ( res , responsePayload ) {
10051127 const response = ensureResponseMetadata ( responsePayload ) ;
10061128 const responseId = response . id ;
@@ -1027,12 +1149,14 @@ function createBuiltinProxyRuntimeController(deps = {}) {
10271149 const itemType = typeof item . type === 'string' ? item . type : '' ;
10281150 const itemId = typeof item . id === 'string' && item . id . trim ( )
10291151 ? item . id . trim ( )
1030- : `item_${ crypto . randomBytes ( 8 ) . toString ( 'hex' ) } ` ;
1152+ : ( typeof item . call_id === 'string' && item . call_id . trim ( ) ? item . call_id . trim ( ) : `item_${ crypto . randomBytes ( 8 ) . toString ( 'hex' ) } ` ) ;
1153+ const wireItem = buildResponsesSseItem ( item , itemId ) ;
10311154
10321155 writeSse ( res , 'response.output_item.added' , {
10331156 type : 'response.output_item.added' ,
10341157 output_index : outputIndex ,
1035- item : { ...item , id : itemId }
1158+ item : wireItem ,
1159+ sequence_number : nextSeq ( )
10361160 } ) ;
10371161
10381162 if ( itemType === 'message' ) {
@@ -1042,6 +1166,7 @@ function createBuiltinProxyRuntimeController(deps = {}) {
10421166 if ( ! block || typeof block !== 'object' ) continue ;
10431167 if ( block . type !== 'output_text' ) continue ;
10441168 const text = typeof block . text === 'string' ? block . text : '' ;
1169+ emitResponsesTextPartAdded ( res , itemId , outputIndex , contentIndex , nextSeq ) ;
10451170 if ( text ) {
10461171 writeSse ( res , 'response.output_text.delta' , {
10471172 type : 'response.output_text.delta' ,
@@ -1060,13 +1185,40 @@ function createBuiltinProxyRuntimeController(deps = {}) {
10601185 text,
10611186 sequence_number : nextSeq ( )
10621187 } ) ;
1188+ emitResponsesTextPartDone ( res , itemId , outputIndex , contentIndex , text , nextSeq ) ;
1189+ }
1190+ } else if ( itemType === 'function_call' || itemType === 'custom_tool_call' ) {
1191+ emitResponsesToolArgumentEvents ( res , wireItem , outputIndex , nextSeq ) ;
1192+ } else if ( itemType === 'reasoning' ) {
1193+ const summary = Array . isArray ( item . summary ) ? item . summary : [ ] ;
1194+ for ( let summaryIndex = 0 ; summaryIndex < summary . length ; summaryIndex += 1 ) {
1195+ const block = summary [ summaryIndex ] ;
1196+ const text = block && typeof block . text === 'string' ? block . text : '' ;
1197+ if ( text ) {
1198+ writeSse ( res , 'response.reasoning_summary_text.delta' , {
1199+ type : 'response.reasoning_summary_text.delta' ,
1200+ item_id : itemId ,
1201+ output_index : outputIndex ,
1202+ summary_index : summaryIndex ,
1203+ delta : text ,
1204+ sequence_number : nextSeq ( )
1205+ } ) ;
1206+ }
1207+ writeSse ( res , 'response.reasoning_summary_text.done' , {
1208+ type : 'response.reasoning_summary_text.done' ,
1209+ item_id : itemId ,
1210+ output_index : outputIndex ,
1211+ summary_index : summaryIndex ,
1212+ text,
1213+ sequence_number : nextSeq ( )
1214+ } ) ;
10631215 }
10641216 }
10651217
10661218 writeSse ( res , 'response.output_item.done' , {
10671219 type : 'response.output_item.done' ,
10681220 output_index : outputIndex ,
1069- item : { ... item , id : itemId } ,
1221+ item : wireItem ,
10701222 sequence_number : nextSeq ( )
10711223 } ) ;
10721224 }
@@ -1105,6 +1257,40 @@ function createBuiltinProxyRuntimeController(deps = {}) {
11051257 const delta = choice && choice . delta && typeof choice . delta === 'object' ? choice . delta : null ;
11061258 if ( ! delta ) continue ;
11071259
1260+ const reasoningSegment = typeof delta . reasoning_content === 'string'
1261+ ? delta . reasoning_content
1262+ : ( typeof delta . reasoning === 'string'
1263+ ? delta . reasoning
1264+ : ( typeof delta . reasoning_text === 'string' ? delta . reasoning_text : '' ) ) ;
1265+ if ( reasoningSegment ) {
1266+ if ( ! state . reasoningItem ) {
1267+ state . reasoningItem = {
1268+ id : `rs_${ crypto . randomBytes ( 8 ) . toString ( 'hex' ) } ` ,
1269+ type : 'reasoning' ,
1270+ summary : [ { type : 'summary_text' , text : '' } ]
1271+ } ;
1272+ state . output . push ( state . reasoningItem ) ;
1273+ state . outputStarted = true ;
1274+ beginChatStreamResponsesSse ( state ) ;
1275+ writeSse ( state . res , 'response.output_item.added' , {
1276+ type : 'response.output_item.added' ,
1277+ output_index : state . output . length - 1 ,
1278+ item : buildResponsesSseItem ( state . reasoningItem , state . reasoningItem . id ) ,
1279+ sequence_number : state . nextSeq ( )
1280+ } ) ;
1281+ }
1282+ state . reasoningText += reasoningSegment ;
1283+ state . reasoningItem . summary [ 0 ] . text = state . reasoningText ;
1284+ writeSse ( state . res , 'response.reasoning_summary_text.delta' , {
1285+ type : 'response.reasoning_summary_text.delta' ,
1286+ item_id : state . reasoningItem . id ,
1287+ output_index : state . output . indexOf ( state . reasoningItem ) ,
1288+ summary_index : 0 ,
1289+ delta : reasoningSegment ,
1290+ sequence_number : state . nextSeq ( )
1291+ } ) ;
1292+ }
1293+
11081294 if ( typeof delta . content === 'string' && delta . content ) {
11091295 if ( ! state . messageItem ) {
11101296 state . messageItem = {
@@ -1119,8 +1305,10 @@ function createBuiltinProxyRuntimeController(deps = {}) {
11191305 writeSse ( state . res , 'response.output_item.added' , {
11201306 type : 'response.output_item.added' ,
11211307 output_index : state . output . length - 1 ,
1122- item : state . messageItem
1308+ item : buildResponsesSseItem ( state . messageItem , state . messageItem . id ) ,
1309+ sequence_number : state . nextSeq ( )
11231310 } ) ;
1311+ emitResponsesTextPartAdded ( state . res , state . messageItem . id , state . output . length - 1 , 0 , state . nextSeq ) ;
11241312 }
11251313 state . messageText += delta . content ;
11261314 state . messageItem . content [ 0 ] . text = state . messageText ;
@@ -1172,6 +1360,24 @@ function createBuiltinProxyRuntimeController(deps = {}) {
11721360 state . finished = true ;
11731361 stopChatStreamHeartbeat ( state ) ;
11741362
1363+ if ( state . reasoningItem ) {
1364+ const outputIndex = state . output . indexOf ( state . reasoningItem ) ;
1365+ writeSse ( state . res , 'response.reasoning_summary_text.done' , {
1366+ type : 'response.reasoning_summary_text.done' ,
1367+ item_id : state . reasoningItem . id ,
1368+ output_index : outputIndex ,
1369+ summary_index : 0 ,
1370+ text : state . reasoningText ,
1371+ sequence_number : state . nextSeq ( )
1372+ } ) ;
1373+ writeSse ( state . res , 'response.output_item.done' , {
1374+ type : 'response.output_item.done' ,
1375+ output_index : outputIndex ,
1376+ item : buildResponsesSseItem ( state . reasoningItem , state . reasoningItem . id ) ,
1377+ sequence_number : state . nextSeq ( )
1378+ } ) ;
1379+ }
1380+
11751381 if ( state . messageItem ) {
11761382 const outputIndex = state . output . indexOf ( state . messageItem ) ;
11771383 writeSse ( state . res , 'response.output_text.done' , {
@@ -1182,10 +1388,11 @@ function createBuiltinProxyRuntimeController(deps = {}) {
11821388 text : state . messageText ,
11831389 sequence_number : state . nextSeq ( )
11841390 } ) ;
1391+ emitResponsesTextPartDone ( state . res , state . messageItem . id , outputIndex , 0 , state . messageText , state . nextSeq ) ;
11851392 writeSse ( state . res , 'response.output_item.done' , {
11861393 type : 'response.output_item.done' ,
11871394 output_index : outputIndex ,
1188- item : state . messageItem ,
1395+ item : buildResponsesSseItem ( state . messageItem , state . messageItem . id ) ,
11891396 sequence_number : state . nextSeq ( )
11901397 } ) ;
11911398 }
@@ -1200,12 +1407,14 @@ function createBuiltinProxyRuntimeController(deps = {}) {
12001407 writeSse ( state . res , 'response.output_item.added' , {
12011408 type : 'response.output_item.added' ,
12021409 output_index : outputIndex ,
1203- item
1410+ item : buildResponsesSseItem ( item , item . call_id ) ,
1411+ sequence_number : state . nextSeq ( )
12041412 } ) ;
1413+ emitResponsesToolArgumentEvents ( state . res , buildResponsesSseItem ( item , item . call_id ) , outputIndex , state . nextSeq ) ;
12051414 writeSse ( state . res , 'response.output_item.done' , {
12061415 type : 'response.output_item.done' ,
12071416 output_index : outputIndex ,
1208- item,
1417+ item : buildResponsesSseItem ( item , item . call_id ) ,
12091418 sequence_number : state . nextSeq ( )
12101419 } ) ;
12111420 }
@@ -1282,6 +1491,8 @@ function createBuiltinProxyRuntimeController(deps = {}) {
12821491 output : [ ] ,
12831492 messageItem : null ,
12841493 messageText : '' ,
1494+ reasoningItem : null ,
1495+ reasoningText : '' ,
12851496 toolCalls : [ ] ,
12861497 toolTypesByName : options . toolTypesByName || { } ,
12871498 finished : false ,
@@ -1983,7 +2194,7 @@ function createBuiltinProxyRuntimeController(deps = {}) {
19832194 method : 'POST' ,
19842195 headers : commonHeaders ,
19852196 timeoutMs,
1986- body : { ... payload , stream : true } ,
2197+ body : normalizeResponsesPayloadForUpstream ( payload , true ) ,
19872198 res,
19882199 model
19892200 } ) ;
@@ -2031,7 +2242,7 @@ function createBuiltinProxyRuntimeController(deps = {}) {
20312242 method : 'POST' ,
20322243 headers : commonHeaders ,
20332244 timeoutMs,
2034- body : { ... payload , stream : false }
2245+ body : normalizeResponsesPayloadForUpstream ( payload , false )
20352246 } ) ;
20362247
20372248 // 优先走上游 /responses(如果支持)。若上游报错且不是“端点不支持”,则直接透传错误。
0 commit comments