@@ -2785,6 +2785,101 @@ describe("openai transport stream", () => {
27852785 expect ( output . stopReason ) . toBe ( "stop" ) ;
27862786 } ) ;
27872787
2788+ it ( "surfaces chat-completions refusal deltas as visible assistant text" , async ( ) => {
2789+ const model = {
2790+ id : "gpt-5.5" ,
2791+ name : "GPT-5.5" ,
2792+ api : "openai-completions" as const ,
2793+ provider : "openai" ,
2794+ baseUrl : "https://api.openai.com/v1" ,
2795+ reasoning : false ,
2796+ input : [ "text" ] as const ,
2797+ cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 } ,
2798+ contextWindow : 128_000 ,
2799+ maxTokens : 4096 ,
2800+ } satisfies Model < "openai-completions" > ;
2801+ const output = createAssistantOutput ( model ) ;
2802+ const events : CapturedStreamEvent [ ] = [ ] ;
2803+
2804+ await testing . processOpenAICompletionsStream (
2805+ streamChunks ( [
2806+ {
2807+ id : "chatcmpl-refusal-delta" ,
2808+ object : "chat.completion.chunk" ,
2809+ created : 1 ,
2810+ model : model . id ,
2811+ choices : [
2812+ {
2813+ index : 0 ,
2814+ delta : { role : "assistant" , content : null , refusal : "I can't help with that." } ,
2815+ logprobs : null ,
2816+ finish_reason : "stop" ,
2817+ } ,
2818+ ] ,
2819+ } ,
2820+ ] ) ,
2821+ output ,
2822+ model ,
2823+ { push : ( event ) => events . push ( event as CapturedStreamEvent ) } ,
2824+ ) ;
2825+
2826+ expect ( output . content ) . toStrictEqual ( [ { type : "text" , text : "I can't help with that." } ] ) ;
2827+ expect ( output . stopReason ) . toBe ( "stop" ) ;
2828+ expect (
2829+ events . some (
2830+ ( event ) => event . type === "text_delta" && event . delta === "I can't help with that." ,
2831+ ) ,
2832+ ) . toBe ( true ) ;
2833+ } ) ;
2834+
2835+ it ( "surfaces aggregated chat-completions message.refusal as visible assistant text" , async ( ) => {
2836+ const model = {
2837+ id : "gpt-5.5" ,
2838+ name : "GPT-5.5" ,
2839+ api : "openai-completions" as const ,
2840+ provider : "openai" ,
2841+ baseUrl : "https://api.openai.com/v1" ,
2842+ reasoning : false ,
2843+ input : [ "text" ] as const ,
2844+ cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 } ,
2845+ contextWindow : 128_000 ,
2846+ maxTokens : 4096 ,
2847+ } satisfies Model < "openai-completions" > ;
2848+ const output = createAssistantOutput ( model ) ;
2849+
2850+ await testing . processOpenAICompletionsStream (
2851+ streamChunks ( [
2852+ {
2853+ id : "chatcmpl-refusal-message" ,
2854+ object : "chat.completion.chunk" ,
2855+ created : 1 ,
2856+ model : model . id ,
2857+ choices : [
2858+ {
2859+ index : 0 ,
2860+ // Some OpenAI-compatible endpoints deliver a full message instead of delta.
2861+ message : {
2862+ role : "assistant" ,
2863+ content : null ,
2864+ refusal : "Requests like this are not allowed." ,
2865+ } ,
2866+ logprobs : null ,
2867+ finish_reason : "stop" ,
2868+ } as unknown as ChatCompletionChunk [ "choices" ] [ number ] ,
2869+ ] ,
2870+ } ,
2871+ ] ) ,
2872+ output ,
2873+ model ,
2874+ { push ( ) { } } ,
2875+ ) ;
2876+
2877+ expect ( output . content ) . toStrictEqual ( [
2878+ { type : "text" , text : "Requests like this are not allowed." } ,
2879+ ] ) ;
2880+ expect ( output . stopReason ) . toBe ( "stop" ) ;
2881+ } ) ;
2882+
27882883 it ( "filters DeepSeek DSML content without disturbing native tool calls" , async ( ) => {
27892884 const model = createDeepSeekCompletionsModel ( ) ;
27902885 const output = createAssistantOutput ( model ) ;
0 commit comments