@@ -122,10 +122,11 @@ func (m *OpenAIChatMessage) GetUsage() *uctypes.AIUsage {
122122 return nil
123123 }
124124 return & uctypes.AIUsage {
125- APIType : "openai" ,
126- Model : m .Usage .Model ,
127- InputTokens : m .Usage .InputTokens ,
128- OutputTokens : m .Usage .OutputTokens ,
125+ APIType : "openai" ,
126+ Model : m .Usage .Model ,
127+ InputTokens : m .Usage .InputTokens ,
128+ OutputTokens : m .Usage .OutputTokens ,
129+ NativeWebSearchCount : m .Usage .NativeWebSearchCount ,
129130 }
130131}
131132
@@ -281,12 +282,13 @@ type openaiTextFormat struct {
281282}
282283
283284type OpenAIUsage struct {
284- InputTokens int `json:"input_tokens,omitempty"`
285- OutputTokens int `json:"output_tokens,omitempty"`
286- TotalTokens int `json:"total_tokens,omitempty"`
287- InputTokensDetails * openaiInputTokensDetails `json:"input_tokens_details,omitempty"`
288- OutputTokensDetails * openaiOutputTokensDetails `json:"output_tokens_details,omitempty"`
289- Model string `json:"model,omitempty"` // internal field (not from OpenAI API)
285+ InputTokens int `json:"input_tokens,omitempty"`
286+ OutputTokens int `json:"output_tokens,omitempty"`
287+ TotalTokens int `json:"total_tokens,omitempty"`
288+ InputTokensDetails * openaiInputTokensDetails `json:"input_tokens_details,omitempty"`
289+ OutputTokensDetails * openaiOutputTokensDetails `json:"output_tokens_details,omitempty"`
290+ Model string `json:"model,omitempty"` // internal field (not from OpenAI API)
291+ NativeWebSearchCount int `json:"nativewebsearchcount,omitempty"` // internal field (not from OpenAI API)
290292}
291293
292294type openaiInputTokensDetails struct {
@@ -323,12 +325,13 @@ type openaiBlockState struct {
323325}
324326
325327type openaiStreamingState struct {
326- blockMap map [string ]* openaiBlockState // Use item_id as key for UI streaming
327- toolUseData map [string ]* uctypes.UIMessageDataToolUse // Use toolCallId as key
328- msgID string
329- model string
330- stepStarted bool
331- chatOpts uctypes.WaveChatOpts
328+ blockMap map [string ]* openaiBlockState // Use item_id as key for UI streaming
329+ toolUseData map [string ]* uctypes.UIMessageDataToolUse // Use toolCallId as key
330+ msgID string
331+ model string
332+ stepStarted bool
333+ chatOpts uctypes.WaveChatOpts
334+ webSearchCount int
332335}
333336
334337// ---------- Public entrypoint ----------
@@ -759,7 +762,7 @@ func handleOpenAIEvent(
759762 }
760763
761764 // Extract partial message if available
762- finalMessages , _ := extractMessageAndToolsFromResponse (ev .Response , state . toolUseData )
765+ finalMessages , _ := extractMessageAndToolsFromResponse (ev .Response , state )
763766
764767 _ = sse .AiMsgError (errorMsg )
765768 return & uctypes.WaveStopReason {
@@ -772,7 +775,7 @@ func handleOpenAIEvent(
772775 }
773776
774777 // Extract the final message and tool calls from the response output
775- finalMessages , toolCalls := extractMessageAndToolsFromResponse (ev .Response , state . toolUseData )
778+ finalMessages , toolCalls := extractMessageAndToolsFromResponse (ev .Response , state )
776779
777780 stopKind := uctypes .StopKindDone
778781 if len (toolCalls ) > 0 {
@@ -820,6 +823,19 @@ func handleOpenAIEvent(
820823 }
821824 return nil , nil
822825
826+ case "response.web_search_call.in_progress" :
827+ return nil , nil
828+
829+ case "response.web_search_call.searching" :
830+ return nil , nil
831+
832+ case "response.web_search_call.completed" :
833+ state .webSearchCount ++
834+ return nil , nil
835+
836+ case "response.output_text.annotation.added" :
837+ return nil , nil
838+
823839 default :
824840 // log unknown events for debugging
825841 log .Printf ("OpenAI: unknown event: %s, data: %s" , eventName , data )
@@ -857,9 +873,8 @@ func createToolUseData(toolCallID, toolName string, toolDef *uctypes.ToolDefinit
857873 return toolUseData
858874}
859875
860-
861876// extractMessageAndToolsFromResponse extracts the final OpenAI message and tool calls from the completed response
862- func extractMessageAndToolsFromResponse (resp openaiResponse , toolUseData map [ string ] * uctypes. UIMessageDataToolUse ) ([]* OpenAIChatMessage , []uctypes.WaveToolCall ) {
877+ func extractMessageAndToolsFromResponse (resp openaiResponse , state * openaiStreamingState ) ([]* OpenAIChatMessage , []uctypes.WaveToolCall ) {
863878 var messageContent []OpenAIMessageContent
864879 var toolCalls []uctypes.WaveToolCall
865880 var messages []* OpenAIChatMessage
@@ -893,7 +908,7 @@ func extractMessageAndToolsFromResponse(resp openaiResponse, toolUseData map[str
893908 }
894909
895910 // Attach UIToolUseData if available
896- if data , ok := toolUseData [outputItem .CallId ]; ok {
911+ if data , ok := state . toolUseData [outputItem .CallId ]; ok {
897912 toolCall .ToolUseData = data
898913 } else {
899914 log .Printf ("AI no data-tooluse for %s (callid: %s)\n " , outputItem .Id , outputItem .CallId )
@@ -907,7 +922,7 @@ func extractMessageAndToolsFromResponse(resp openaiResponse, toolUseData map[str
907922 argsStr = outputItem .Arguments
908923 }
909924 var toolUseDataPtr * uctypes.UIMessageDataToolUse
910- if data , ok := toolUseData [outputItem .CallId ]; ok {
925+ if data , ok := state . toolUseData [outputItem .CallId ]; ok {
911926 toolUseDataPtr = data
912927 }
913928 functionCallMsg := & OpenAIChatMessage {
@@ -925,17 +940,20 @@ func extractMessageAndToolsFromResponse(resp openaiResponse, toolUseData map[str
925940 }
926941
927942 // Create OpenAIChatMessage with assistant message (first in slice)
928- if resp .Usage != nil {
943+ usage := resp .Usage
944+ if usage != nil {
929945 resp .Usage .Model = resp .Model
946+ if state .webSearchCount > 0 {
947+ usage .NativeWebSearchCount = state .webSearchCount
948+ }
930949 }
931-
932950 assistantMessage := & OpenAIChatMessage {
933951 MessageId : uuid .New ().String (),
934952 Message : & OpenAIMessage {
935953 Role : "assistant" ,
936954 Content : messageContent ,
937955 },
938- Usage : resp . Usage ,
956+ Usage : usage ,
939957 }
940958
941959 // Return assistant message first, followed by function call messages
0 commit comments