11use crate :: {
2- anthropic:: { AnthropicClient , AuthProvider , MessageConverter , RequestCustomizer } ,
2+ anthropic:: { AnthropicClient , AuthProvider , DefaultMessageConverter , RequestCustomizer } ,
33 types:: * ,
44 LLMProvider , StreamingCallback ,
55} ;
66use anyhow:: Result ;
77use async_trait:: async_trait;
8- use serde:: Serialize ;
98use serde_json:: Value ;
109use std:: sync:: Arc ;
1110
@@ -71,157 +70,6 @@ impl RequestCustomizer for AiCoreRequestCustomizer {
7170 }
7271}
7372
74- /// AiCore message converter - converts messages to AiCore format without caching
75- pub struct AiCoreMessageConverter ;
76-
77- /// AiCore message structure
78- #[ derive( Debug , Serialize ) ]
79- struct AiCoreMessage {
80- role : String ,
81- content : Vec < AiCoreContentBlock > ,
82- }
83-
84- /// AiCore content block structure
85- #[ derive( Debug , Serialize ) ]
86- struct AiCoreContentBlock {
87- #[ serde( rename = "type" ) ]
88- block_type : String ,
89- #[ serde( flatten) ]
90- content : AiCoreBlockContent ,
91- }
92-
93- /// Content variants for AiCore content blocks
94- #[ derive( Debug , Serialize ) ]
95- #[ serde( untagged) ]
96- enum AiCoreBlockContent {
97- Text {
98- text : String ,
99- } ,
100- Thinking {
101- thinking : String ,
102- signature : String ,
103- } ,
104- RedactedThinking {
105- data : String ,
106- } ,
107- ToolUse {
108- id : String ,
109- name : String ,
110- input : serde_json:: Value ,
111- } ,
112- ToolResult {
113- tool_use_id : String ,
114- #[ serde( skip_serializing_if = "Option::is_none" ) ]
115- content : Option < Vec < AiCoreToolResultContent > > ,
116- #[ serde( skip_serializing_if = "Option::is_none" ) ]
117- is_error : Option < bool > ,
118- } ,
119- }
120-
121- /// Tool result content for AiCore
122- #[ derive( Debug , Serialize ) ]
123- struct AiCoreToolResultContent {
124- #[ serde( rename = "type" ) ]
125- content_type : String ,
126- #[ serde( flatten) ]
127- data : AiCoreToolResultData ,
128- }
129-
130- #[ derive( Debug , Serialize ) ]
131- #[ serde( untagged) ]
132- enum AiCoreToolResultData {
133- Text { text : String } ,
134- }
135-
136- impl MessageConverter for AiCoreMessageConverter {
137- fn convert_messages ( & mut self , messages : Vec < Message > ) -> Result < Vec < serde_json:: Value > > {
138- let aicore_messages = self . convert_messages_to_aicore ( messages) ;
139- Ok ( vec ! [ serde_json:: to_value( aicore_messages) ?] )
140- }
141- }
142-
143- impl AiCoreMessageConverter {
144- pub fn new ( ) -> Self {
145- Self
146- }
147-
148- /// Convert LLM messages to AiCore format (removes internal fields like request_id)
149- fn convert_messages_to_aicore ( & self , messages : Vec < Message > ) -> Vec < AiCoreMessage > {
150- messages
151- . into_iter ( )
152- . map ( |msg| AiCoreMessage {
153- role : match msg. role {
154- MessageRole :: User => "user" . to_string ( ) ,
155- MessageRole :: Assistant => "assistant" . to_string ( ) ,
156- } ,
157- content : self . convert_content_to_aicore ( msg. content ) ,
158- } )
159- . collect ( )
160- }
161-
162- /// Convert LLM message content to AiCore format
163- fn convert_content_to_aicore ( & self , content : MessageContent ) -> Vec < AiCoreContentBlock > {
164- match content {
165- MessageContent :: Text ( text) => {
166- vec ! [ AiCoreContentBlock {
167- block_type: "text" . to_string( ) ,
168- content: AiCoreBlockContent :: Text { text } ,
169- } ]
170- }
171- MessageContent :: Structured ( blocks) => blocks
172- . into_iter ( )
173- . map ( |block| self . convert_content_block_to_aicore ( block) )
174- . collect ( ) ,
175- }
176- }
177-
178- /// Convert a single content block to AiCore format
179- fn convert_content_block_to_aicore ( & self , block : ContentBlock ) -> AiCoreContentBlock {
180- match block {
181- ContentBlock :: Text { text } => AiCoreContentBlock {
182- block_type : "text" . to_string ( ) ,
183- content : AiCoreBlockContent :: Text { text } ,
184- } ,
185- ContentBlock :: ToolUse { id, name, input } => AiCoreContentBlock {
186- block_type : "tool_use" . to_string ( ) ,
187- content : AiCoreBlockContent :: ToolUse { id, name, input } ,
188- } ,
189- ContentBlock :: ToolResult {
190- tool_use_id,
191- content,
192- is_error,
193- } => {
194- let tool_content = Some ( vec ! [ AiCoreToolResultContent {
195- content_type: "text" . to_string( ) ,
196- data: AiCoreToolResultData :: Text { text: content } ,
197- } ] ) ;
198- AiCoreContentBlock {
199- block_type : "tool_result" . to_string ( ) ,
200- content : AiCoreBlockContent :: ToolResult {
201- tool_use_id,
202- content : tool_content,
203- is_error,
204- } ,
205- }
206- }
207- ContentBlock :: Thinking {
208- thinking,
209- signature,
210- } => AiCoreContentBlock {
211- block_type : "thinking" . to_string ( ) ,
212- content : AiCoreBlockContent :: Thinking {
213- thinking,
214- signature,
215- } ,
216- } ,
217- ContentBlock :: RedactedThinking { data } => AiCoreContentBlock {
218- block_type : "redacted_thinking" . to_string ( ) ,
219- content : AiCoreBlockContent :: RedactedThinking { data } ,
220- } ,
221- }
222- }
223- }
224-
22573pub struct AiCoreClient {
22674 anthropic_client : AnthropicClient ,
22775}
@@ -233,7 +81,7 @@ impl AiCoreClient {
23381 ) -> AnthropicClient {
23482 let auth_provider = Box :: new ( AiCoreAuthProvider :: new ( token_manager) ) ;
23583 let request_customizer = Box :: new ( AiCoreRequestCustomizer ) ;
236- let message_converter = Box :: new ( AiCoreMessageConverter :: new ( ) ) ;
84+ let message_converter = Box :: new ( DefaultMessageConverter :: new ( ) ) ;
23785
23886 AnthropicClient :: with_customization (
23987 "ignored" . to_string ( ) , // Default model, can be overridden
0 commit comments