@@ -593,6 +593,238 @@ public async Task BasicRequestResponse_Streaming()
593593 Assert . Equal ( 36 , usage . Details . TotalTokenCount ) ;
594594 }
595595
596+ [ Fact ]
597+ public async Task MissingAbstractionResponse_NonStreaming ( )
598+ {
599+ const string Input =
600+ """
601+ {
602+ "model": "computer-use-preview",
603+ "reasoning":{"summary":"concise"},
604+ "tools": [
605+ {
606+ "type": "computer_use_preview",
607+ "environment": "browser",
608+ "display_width": 1024,
609+ "display_height": 768
610+ }
611+ ],
612+ "tool_choice": "auto",
613+ "input": [
614+ {
615+ "type": "message",
616+ "role": "user",
617+ "content": [
618+ {
619+ "type": "input_text",
620+ "text": "Search the web for the temperature today in Fremont"
621+ }
622+ ]
623+ }
624+ ]
625+ }
626+ """ ;
627+
628+ const string Output =
629+ """
630+ {
631+ "id": "resp_67d327649b288191aeb46a824e49dc40058a5e08c46a181d",
632+ "object": "response",
633+ "created_at": 1741891428,
634+ "status": "completed",
635+ "error": null,
636+ "incomplete_details": null,
637+ "instructions": null,
638+ "max_output_tokens": 20,
639+ "model": "computer-use-preview-2025-03-11",
640+ "output": [
641+ {
642+ "type": "reasoning",
643+ "id": "rs_67cc...",
644+ "summary": [
645+ {
646+ "type": "summary_text",
647+ "text": "Clicking on the browser address bar."
648+ }
649+ ]
650+ },
651+ {
652+ "type": "computer_call",
653+ "id": "cu_67cc...",
654+ "call_id": "call_zw3...",
655+ "action": {
656+ "type": "click",
657+ "button": "left",
658+ "x": 156,
659+ "y": 50
660+ },
661+ "pending_safety_checks": [],
662+ "status": "completed"
663+ }
664+ ],
665+ "parallel_tool_calls": true,
666+ "previous_response_id": null,
667+ "reasoning": {
668+ "generate_summary": "concise"
669+ },
670+ "store": true,
671+ "temperature": 1.0,
672+ "text": {
673+ "format": {
674+ "type": "text"
675+ }
676+ },
677+ "tool_choice": "auto",
678+ "tools": [],
679+ "top_p": 1.0,
680+ "usage": {
681+ "input_tokens": 18,
682+ "input_tokens_details": {
683+ "cached_tokens": 0
684+ },
685+ "output_tokens": 53,
686+ "output_tokens_details": {
687+ "reasoning_tokens": 12
688+ },
689+ "total_tokens": 71
690+ },
691+ "user": null,
692+ "metadata": {}
693+ }
694+ """ ;
695+
696+ using VerbatimHttpHandler handler = new ( Input , Output ) ;
697+ using HttpClient httpClient = new ( handler ) ;
698+ using IChatClient client = CreateResponseClient ( httpClient , "computer-use-preview" ) ;
699+
700+ ChatOptions chatOptions = new ( )
701+ {
702+ Tools = [ ResponseTool . CreateComputerTool ( ComputerToolEnvironment . Browser , 1024 , 768 ) . AsAITool ( ) ] ,
703+ RawRepresentationFactory = options => new ResponseCreationOptions
704+ {
705+ ReasoningOptions = new ( ) { ReasoningSummaryVerbosity = ResponseReasoningSummaryVerbosity . Concise } ,
706+ }
707+ } ;
708+ var response = await client . GetResponseAsync ( [ new ChatMessage ( ChatRole . User , "Search the web for the temperature today in Fremont" ) ] , chatOptions ) ;
709+ Assert . NotNull ( response ) ;
710+
711+ Assert . Equal ( "resp_67d327649b288191aeb46a824e49dc40058a5e08c46a181d" , response . ResponseId ) ;
712+ Assert . Equal ( "resp_67d327649b288191aeb46a824e49dc40058a5e08c46a181d" , response . ConversationId ) ;
713+ Assert . Empty ( response . Text ) ;
714+ Assert . Equal ( "computer-use-preview-2025-03-11" , response . ModelId ) ;
715+ Assert . Equal ( DateTimeOffset . FromUnixTimeSeconds ( 1_741_891_428 ) , response . CreatedAt ) ;
716+ Assert . Null ( response . FinishReason ) ;
717+ ChatMessage responseMessage = Assert . Single ( response . Messages ) ;
718+ Assert . Equal ( ChatRole . Assistant , responseMessage . Role ) ;
719+ Assert . Equal ( 2 , responseMessage . Contents . Count ) ;
720+ Assert . Single ( responseMessage . Contents , content => content is TextReasoningContent ) ;
721+ AIContent computerUserItem = Assert . Single ( responseMessage . Contents , content => content . GetType ( ) == typeof ( AIContent ) ) ;
722+ Assert . NotNull ( computerUserItem . RawRepresentation ) ;
723+ Assert . IsType < ComputerCallResponseItem > ( computerUserItem . RawRepresentation ) ;
724+ Assert . NotNull ( response . Usage ) ;
725+ Assert . Equal ( 18 , response . Usage . InputTokenCount ) ;
726+ Assert . Equal ( 53 , response . Usage . OutputTokenCount ) ;
727+ Assert . Equal ( 71 , response . Usage . TotalTokenCount ) ;
728+ }
729+
730+ [ Fact ]
731+ public async Task MissingAbstractionResponse_Streaming ( )
732+ {
733+ const string Input =
734+ """
735+ {
736+ "model": "computer-use-preview",
737+ "reasoning": {
738+ "summary": "concise"
739+ },
740+ "tools": [
741+ {
742+ "type": "computer_use_preview",
743+ "environment": "browser",
744+ "display_width": 1024,
745+ "display_height": 768
746+ }
747+ ],
748+ "tool_choice": "auto",
749+ "input": [
750+ {
751+ "type": "message",
752+ "role": "user",
753+ "content": [
754+ {
755+ "type": "input_text",
756+ "text": "Search the web for the temperature today in Fremont"
757+ }
758+ ]
759+ }
760+ ],
761+ "stream":true
762+ }
763+ """ ;
764+
765+ const string Output =
766+ """
767+ event: response.created
768+ data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_0b949080ec8e4b8a006920e0661d00819383ed81438ab11299","object":"response","created_at":1763762278,"status":"in_progress","background":false,"content_filters":null,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"computer-use-preview-2025-03-11","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":"medium","generate_summary":"concise","summary":"concise"},"safety_identifier":null,"service_tier":"auto","store":true,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":null,"tools":[{"type":"computer-use-preview-2025-03-11","environment":"browser","display_width":1024,"display_height":768}],"top_logprobs":0,"top_p":1.0,"truncation":"auto","usage":null,"user":null,"metadata":{}}}
769+
770+ event: response.in_progress
771+ data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_0b949080ec8e4b8a006920e0661d00819383ed81438ab11299","object":"response","created_at":1763762278,"status":"in_progress","background":false,"content_filters":null,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"computer-use-preview-2025-03-11","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":"medium","generate_summary":"concise","summary":"concise"},"safety_identifier":null,"service_tier":"auto","store":true,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":null,"tools":[{"type":"computer_use_preview","environment":"browser","display_width":1024,"display_height":768}],"top_logprobs":0,"top_p":1.0,"truncation":"auto","usage":null,"user":null,"metadata":{}}}
772+
773+ event: response.output_item.added
774+ data: {"type":"response.output_item.added","sequence_number":2,"output_index":0,"item":{"type":"computer_call","id":"cu_0b949080ec8e4b8a006920e067a7c0819384d047d21b484357","status":"in_progress","call_id":"call_p7K8YjFwNjqMgkKhSiExgFH6","action":{"type":"screenshot"},"pending_safety_checks":[]}}
775+
776+ event: response.output_item.done
777+ data: {"type":"response.output_item.done","sequence_number":3,"output_index":0,"item":{"type":"computer_call","id":"cu_0b949080ec8e4b8a006920e067a7c0819384d047d21b484357","status":"completed","call_id":"call_p7K8YjFwNjqMgkKhSiExgFH6","action":{"type":"screenshot"},"pending_safety_checks":[]}}
778+
779+ event: response.completed
780+ data: {"type":"response.completed","sequence_number":4,"response":{"id":"resp_0b949080ec8e4b8a006920e0661d00819383ed81438ab11299","object":"response","created_at":1763762278,"status":"completed","background":false,"content_filters":null,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"computer-use-preview-2025-03-11","output":[{"type":"computer_call","id":"cu_0b949080ec8e4b8a006920e067a7c0819384d047d21b484357","status":"completed","call_id":"call_p7K8YjFwNjqMgkKhSiExgFH6","action":{"type":"screenshot"},"pending_safety_checks":[]}],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":"medium","generate_summary":"concise","summary":"concise"},"safety_identifier":null,"service_tier":"default","store":true,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":null,"tools":[{"type":"computer-use-preview-2025-03-11","environment":"browser","display_width":1024,"display_height":768}],"top_logprobs":0,"top_p":1.0,"truncation":"auto","usage":{"input_tokens":18,"input_tokens_details":{"cached_tokens":0},"output_tokens":53,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":71},"user":null,"metadata":{}}}
781+
782+
783+ """ ;
784+
785+ using VerbatimHttpHandler handler = new ( Input , Output ) ;
786+ using HttpClient httpClient = new ( handler ) ;
787+ using IChatClient client = CreateResponseClient ( httpClient , "computer-use-preview" ) ;
788+
789+ ChatOptions chatOptions = new ( )
790+ {
791+ Tools = [ ResponseTool . CreateComputerTool ( ComputerToolEnvironment . Browser , 1024 , 768 ) . AsAITool ( ) ] ,
792+ RawRepresentationFactory = options => new ResponseCreationOptions
793+ {
794+ ReasoningOptions = new ( ) { ReasoningSummaryVerbosity = ResponseReasoningSummaryVerbosity . Concise } ,
795+ }
796+ } ;
797+
798+ List < ChatResponseUpdate > updates = [ ] ;
799+ await foreach ( var update in client . GetStreamingResponseAsync ( [ new ChatMessage ( ChatRole . User , "Search the web for the temperature today in Fremont" ) ] , chatOptions ) )
800+ {
801+ updates . Add ( update ) ;
802+ }
803+
804+ Assert . Equal ( 5 , updates . Count ) ;
805+ Assert . All ( updates , u => Assert . Empty ( u . Text ) ) ;
806+
807+ for ( int i = 0 ; i < updates . Count ; i ++ )
808+ {
809+ Assert . Equal ( "resp_0b949080ec8e4b8a006920e0661d00819383ed81438ab11299" , updates [ i ] . ResponseId ) ;
810+ Assert . Equal ( "resp_0b949080ec8e4b8a006920e0661d00819383ed81438ab11299" , updates [ i ] . ConversationId ) ;
811+ Assert . Equal ( DateTimeOffset . FromUnixTimeSeconds ( 1_763_762_278 ) , updates [ i ] . CreatedAt ) ;
812+ Assert . Equal ( "computer-use-preview-2025-03-11" , updates [ i ] . ModelId ) ;
813+ Assert . Null ( updates [ i ] . AdditionalProperties ) ;
814+ Assert . Equal ( i >= 3 ? 1 : 0 , updates [ i ] . Contents . Count ) ;
815+ Assert . Equal ( i >= 4 ? ChatFinishReason . Stop : null , updates [ i ] . FinishReason ) ;
816+ Assert . Null ( updates [ i ] . Role ) ;
817+ }
818+
819+ AIContent content = Assert . Single ( updates [ 3 ] . Contents ) ;
820+ var ccri = Assert . IsType < ComputerCallResponseItem > ( content . RawRepresentation ) ;
821+
822+ UsageContent usage = Assert . IsType < UsageContent > ( Assert . Single ( updates [ 4 ] . Contents ) ) ;
823+ Assert . Equal ( 18 , usage . Details . InputTokenCount ) ;
824+ Assert . Equal ( 53 , usage . Details . OutputTokenCount ) ;
825+ Assert . Equal ( 71 , usage . Details . TotalTokenCount ) ;
826+ }
827+
596828 [ Fact ]
597829 public async Task ChatOptions_StrictRespected ( )
598830 {
0 commit comments