1717package agenticopenai
1818
1919import (
20+ "encoding/json"
2021 "fmt"
2122 "strings"
2223 "sync"
2324
2425 "github.com/bytedance/sonic"
26+ "github.com/cloudwego/eino/components/model"
2527 "github.com/cloudwego/eino/schema"
2628 "github.com/cloudwego/eino/schema/openai"
2729 "github.com/eino-contrib/jsonschema"
@@ -554,6 +556,12 @@ func toUserRoleInputItems(msg *schema.AgenticMessage) (items []responses.Respons
554556 return nil , fmt .Errorf ("failed to convert function tool result to input item: %w" , err )
555557 }
556558
559+ case schema .ContentBlockTypeToolSearchResult :
560+ item , err = toolSearchToolResultToInputItem (block .ToolSearchFunctionToolResult )
561+ if err != nil {
562+ return nil , fmt .Errorf ("failed to convert tool search function tool result to input item: %w" , err )
563+ }
564+
557565 case schema .ContentBlockTypeMCPToolApprovalResponse :
558566 item , err = mcpToolApprovalResponseToInputItem (block .MCPToolApprovalResponse )
559567 if err != nil {
@@ -664,6 +672,25 @@ func userInputFileToInputItem(role responses.EasyInputMessageRole, block *schema
664672 return item , nil
665673}
666674
675+ func toolSearchToolResultToInputItem (block * schema.ToolSearchFunctionToolResult ) (item responses.ResponseInputItemUnionParam , err error ) {
676+ if block .Result == nil {
677+ return item , fmt .Errorf ("tool search result should not be nil" )
678+ }
679+ tools , err := toDeferredFunctionTools (block .Result .Tools )
680+ if err != nil {
681+ return item , err
682+ }
683+ item = responses.ResponseInputItemUnionParam {
684+ OfToolSearchOutput : & responses.ResponseToolSearchOutputItemParam {
685+ Tools : tools ,
686+ CallID : param .NewOpt (block .CallID ),
687+ Status : responses .ResponseToolSearchOutputItemParamStatusCompleted ,
688+ Execution : responses .ResponseToolSearchOutputItemParamExecutionClient ,
689+ },
690+ }
691+ return item , nil
692+ }
693+
667694func functionToolResultToInputItem (block * schema.FunctionToolResult ) (item responses.ResponseInputItemUnionParam , err error ) {
668695 item = responses.ResponseInputItemUnionParam {
669696 OfFunctionCallOutput : & responses.ResponseInputItemFunctionCallOutputParam {
@@ -788,6 +815,21 @@ func functionToolCallToInputItem(block *schema.ContentBlock) (item responses.Res
788815
789816 id , _ := getItemID (block )
790817 status , _ := GetItemStatus (block )
818+ namespace , _ := getNamespace (block )
819+
820+ if GetToolSearchToolCall (block ) {
821+ // client tool search call
822+ item = responses.ResponseInputItemUnionParam {
823+ OfToolSearchCall : & responses.ResponseInputItemToolSearchCallParam {
824+ Arguments : json .RawMessage (content .Arguments ),
825+ ID : newOpenaiStrOpt (id ),
826+ CallID : param .NewOpt (content .CallID ),
827+ Status : status ,
828+ Execution : "client" ,
829+ },
830+ }
831+ return item , nil
832+ }
791833
792834 item = responses.ResponseInputItemUnionParam {
793835 OfFunctionCall : & responses.ResponseFunctionToolCallParam {
@@ -796,6 +838,7 @@ func functionToolCallToInputItem(block *schema.ContentBlock) (item responses.Res
796838 CallID : content .CallID ,
797839 Name : content .Name ,
798840 Arguments : content .Arguments ,
841+ Namespace : newOpenaiStrOpt (namespace ),
799842 },
800843 }
801844
@@ -847,6 +890,20 @@ func serverToolCallToInputItem(block *schema.ContentBlock) (item responses.Respo
847890 return imageGenerationToolCallToInputItem (arguments .ImageGeneration , block )
848891 case arguments .Shell != nil :
849892 return shellToolCallToInputItem (arguments .Shell , block )
893+ case arguments .ToolSearch != nil :
894+ id , _ := getItemID (block )
895+ status , _ := GetItemStatus (block )
896+ var action * responses.ResponseInputItemToolSearchCallParam
897+ action , err = getToolSearchCallActionParam (arguments .ToolSearch )
898+ if err != nil {
899+ return item , err
900+ }
901+ action .CallID = newOpenaiStrOpt (content .CallID )
902+ action .ID = param .NewOpt (id )
903+ action .Status = status
904+ return responses.ResponseInputItemUnionParam {
905+ OfToolSearchCall : action ,
906+ }, nil
850907 default :
851908 return item , fmt .Errorf ("server tool call arguments are nil" )
852909 }
@@ -1000,6 +1057,13 @@ func shellToolCallToInputItem(args *ShellArguments, block *schema.ContentBlock)
10001057 return item , nil
10011058}
10021059
1060+ func getToolSearchCallActionParam (ts * ToolSearchCall ) (* responses.ResponseInputItemToolSearchCallParam , error ) {
1061+ return & responses.ResponseInputItemToolSearchCallParam {
1062+ Arguments : ts .Arguments ,
1063+ Execution : "server" ,
1064+ }, nil
1065+ }
1066+
10031067func serverToolResultToInputItem (block * schema.ContentBlock ) (item responses.ResponseInputItemUnionParam , err error ) {
10041068 content := block .ServerToolResult
10051069 if content == nil {
@@ -1022,6 +1086,21 @@ func serverToolResultToInputItem(block *schema.ContentBlock) (item responses.Res
10221086 return imageGenerationToolResultToInputItem (result .ImageGeneration , block )
10231087 case result .Shell != nil :
10241088 return shellToolResultToInputItem (result .Shell , block )
1089+ case result .ToolSearch != nil :
1090+ id , _ := getItemID (block )
1091+ status , _ := GetItemStatus (block )
1092+ var action * responses.ResponseToolSearchOutputItemParam
1093+ action , err = getToolSearchResultActionParam (result .ToolSearch )
1094+ if err != nil {
1095+ return item , err
1096+ }
1097+ action .CallID = newOpenaiStrOpt (content .CallID )
1098+ action .ID = param .NewOpt (id )
1099+ action .Status = responses .ResponseToolSearchOutputItemParamStatus (status )
1100+
1101+ return responses.ResponseInputItemUnionParam {
1102+ OfToolSearchOutput : action ,
1103+ }, nil
10251104 default :
10261105 return item , fmt .Errorf ("server tool result is nil" )
10271106 }
@@ -1209,6 +1288,17 @@ func shellToolResultToInputItem(result *ShellResult, block *schema.ContentBlock)
12091288 return item , nil
12101289}
12111290
1291+ func getToolSearchResultActionParam (ts * ToolSearchResult ) (* responses.ResponseToolSearchOutputItemParam , error ) {
1292+ tools , err := toDeferredFunctionTools (ts .Tools )
1293+ if err != nil {
1294+ return nil , err
1295+ }
1296+ return & responses.ResponseToolSearchOutputItemParam {
1297+ Tools : tools ,
1298+ Execution : "server" ,
1299+ }, nil
1300+ }
1301+
12121302func mcpToolApprovalRequestToInputItem (block * schema.ContentBlock ) (item responses.ResponseInputItemUnionParam , err error ) {
12131303 content := block .MCPToolApprovalRequest
12141304 if content == nil {
@@ -1323,7 +1413,7 @@ func mcpToolResultToInputItem(block *schema.ContentBlock) (item responses.Respon
13231413 return item , nil
13241414}
13251415
1326- func toOutputMessage (resp * responses.Response ) (msg * schema.AgenticMessage , err error ) {
1416+ func toOutputMessage (resp * responses.Response , options * model. Options ) (msg * schema.AgenticMessage , err error ) {
13271417 blocks := make ([]* schema.ContentBlock , 0 , len (resp .Output ))
13281418
13291419 for _ , item := range resp .Output {
@@ -1411,6 +1501,19 @@ func toOutputMessage(resp *responses.Response) (msg *schema.AgenticMessage, err
14111501 return nil , fmt .Errorf ("failed to convert function shell output to content block: %w" , err )
14121502 }
14131503 tmpBlocks = []* schema.ContentBlock {block }
1504+ case responses.ResponseToolSearchCall :
1505+ block , err := toolSearchToolCallToContentBlock (variant , options )
1506+ if err != nil {
1507+ return nil , fmt .Errorf ("failed to convert tool search call to content block: %w" , err )
1508+ }
1509+ tmpBlocks = append (tmpBlocks , block )
1510+
1511+ case responses.ResponseToolSearchOutputItem :
1512+ block , err := toolSearchToolResultToContentBlock (variant )
1513+ if err != nil {
1514+ return nil , fmt .Errorf ("failed to convert tool search output item to content block: %w" , err )
1515+ }
1516+ tmpBlocks = append (tmpBlocks , block )
14141517
14151518 default :
14161519 return nil , fmt .Errorf ("unknown output item type: %T" , variant )
@@ -1547,6 +1650,9 @@ func functionToolCallToContentBlock(item responses.ResponseFunctionToolCall) (bl
15471650 if s := string (item .Status ); s != "" {
15481651 setItemStatus (block , s )
15491652 }
1653+ if len (item .Namespace ) > 0 {
1654+ setNamespace (block , item .Namespace )
1655+ }
15501656
15511657 return block , nil
15521658}
@@ -1631,6 +1737,64 @@ func webSearchToContentBlocks(item responses.ResponseFunctionWebSearch) (blocks
16311737 return blocks , nil
16321738}
16331739
1740+ func toolSearchToolCallToContentBlock (item responses.ResponseToolSearchCall , options * model.Options ) (* schema.ContentBlock , error ) {
1741+ args , err := json .Marshal (item .Arguments )
1742+ if err != nil {
1743+ return nil , fmt .Errorf ("failed to marshal tool search arguments: %w" , err )
1744+ }
1745+
1746+ switch item .Execution {
1747+ case responses .ResponseToolSearchCallExecutionClient :
1748+ if options .ToolSearchTool == nil {
1749+ return nil , fmt .Errorf ("haven't set client tool search tool, but get a client tool search tool call" )
1750+ }
1751+ block := schema .NewContentBlock (& schema.FunctionToolCall {
1752+ CallID : item .CallID ,
1753+ Name : options .ToolSearchTool .Name ,
1754+ Arguments : string (args ),
1755+ })
1756+ setItemID (block , item .ID )
1757+ setItemStatus (block , string (item .Status ))
1758+ setToolSearchToolCall (block )
1759+ return block , nil
1760+
1761+ case responses .ResponseToolSearchCallExecutionServer :
1762+ // server tool call
1763+ block := schema .NewContentBlock (& schema.ServerToolCall {
1764+ CallID : item .CallID ,
1765+ Arguments : & ServerToolCallArguments {
1766+ ToolSearch : & ToolSearchCall {
1767+ Arguments : args ,
1768+ },
1769+ },
1770+ })
1771+ setItemID (block , item .ID )
1772+ setItemStatus (block , string (item .Status ))
1773+ return block , nil
1774+
1775+ default :
1776+ return nil , fmt .Errorf ("invalid tool search execution type: %s" , item .Execution )
1777+ }
1778+ }
1779+
1780+ func toolSearchToolResultToContentBlock (item responses.ResponseToolSearchOutputItem ) (blocks * schema.ContentBlock , err error ) {
1781+ tools , err := fromFunctionTools (item .Tools )
1782+ if err != nil {
1783+ return nil , err
1784+ }
1785+ block := schema .NewContentBlock (& schema.ServerToolResult {
1786+ CallID : item .CallID ,
1787+ Result : & ServerToolResult {
1788+ ToolSearch : & ToolSearchResult {
1789+ Tools : tools ,
1790+ },
1791+ },
1792+ })
1793+ setItemID (block , item .ID )
1794+ setItemStatus (block , string (item .Status ))
1795+ return block , nil
1796+ }
1797+
16341798func fileSearchToContentBlocks (item responses.ResponseFileSearchToolCall ) (blocks []* schema.ContentBlock , err error ) {
16351799 args := & ServerToolCallArguments {
16361800 FileSearch : & FileSearchArguments {
0 commit comments