@@ -119,68 +119,12 @@ func (p *Anthropic) ChatCompletion(ctx context.Context, adapter internal.Adapter
119119
120120 opts := internal.CastProviderOptions [RequestOptions ](requester .ProviderRequestOptions (p ))
121121
122- messages , params , err := p .adaptRequest (adapter , requester , opts )
122+ params , err := p .adaptRequest (adapter , requester , * model , opts )
123123 if err != nil {
124124 return nil , errors .Wrap (err , "could not adapt request" )
125125 }
126126
127- messageParams := anthropic.MessageNewParams {
128- Model : * model ,
129- Messages : messages ,
130- }
131-
132- // Add max tokens only if explicitly provided (Vertex AI requires > 0)
133- if r .MaxTokens != nil {
134- messageParams .MaxTokens = int64 (* r .MaxTokens )
135- } else if p .backend == BackendVertexAI {
136- messageParams .MaxTokens = BackendVertexAiDefaultMaxTokens // Set a default max tokens for Vertex AI if not provided
137- }
138-
139- // Add system message
140- if params .System .Text != "" {
141- messageParams .System = []anthropic.TextBlockParam {params .System }
142- }
143-
144- // Add tools
145- if len (params .Tools ) > 0 {
146- toolUnions := make ([]anthropic.ToolUnionParam , len (params .Tools ))
147- for i , tool := range params .Tools {
148- toolUnions [i ] = anthropic .ToolUnionParamOfTool (
149- tool .InputSchema ,
150- tool .Name ,
151- )
152- // Description is already set in tool if provided
153- toolUnions [i ].OfTool .Description = tool .Description
154- }
155- messageParams .Tools = toolUnions
156- }
157-
158- // Add tool choice
159- if params .ToolChoice != nil {
160- messageParams .ToolChoice = * params .ToolChoice
161- }
162-
163- // Add temperature
164- if r .Temperature != nil {
165- messageParams .Temperature = anthropic .Float (* r .Temperature )
166- }
167-
168- // Add top_p
169- if r .TopP != nil {
170- messageParams .TopP = anthropic .Float (* r .TopP )
171- }
172-
173- // Add top_k
174- if params .TopK != nil {
175- messageParams .TopK = anthropic .Int (int64 (* params .TopK ))
176- }
177-
178- // Add thinking
179- if params .Thinking != nil && * params .Thinking > 0 {
180- messageParams .Thinking = anthropic .ThinkingConfigParamOfEnabled (int64 (* params .Thinking ))
181- }
182-
183- response , err := p .client .Messages .New (ctx , messageParams )
127+ response , err := p .client .Messages .New (ctx , * params )
184128 if err != nil {
185129 return nil , errors .Wrap (err , "LLM provider failed to generate content" )
186130 }
@@ -193,36 +137,25 @@ func (p *Anthropic) ChatCompletion(ctx context.Context, adapter internal.Adapter
193137 return responseAdapter , nil
194138}
195139
196- type requestParams struct {
197- System anthropic.TextBlockParam
198- Tools []anthropic.ToolParam
199- ToolChoice * anthropic.ToolChoiceUnionParam
200- TopK * int
201- Thinking * int
202- }
203-
204- func (p * Anthropic ) adaptRequest (_ internal.Adapter , requester llmberjack.Requester , opts RequestOptions ) ([]anthropic.MessageParam , * requestParams , error ) {
140+ func (p * Anthropic ) adaptRequest (_ internal.Adapter , requester llmberjack.Requester , model string , opts RequestOptions ) (* anthropic.MessageNewParams , error ) {
205141 r := requester .ToRequest ()
206142 messages := make ([]anthropic.MessageParam , 0 , len (r .Messages ))
207143
208144 if r .ThreadId != nil {
209145 messages = append (messages , p .history .Load (r .ThreadId )... )
210146 }
211147
212- params := & requestParams {
213- Tools : make ([]anthropic.ToolParam , 0 , len (r .Tools )),
214- }
215-
216- // Add tools
148+ // Build tools
149+ tools := make ([]anthropic.ToolParam , 0 , len (r .Tools ))
217150 for _ , tool := range r .Tools {
218151 paramsJson , err := json .Marshal (tool .Parameters )
219152 if err != nil {
220- return nil , nil , errors .Wrap (err , "failed to encode tool parameters" )
153+ return nil , errors .Wrap (err , "failed to encode tool parameters" )
221154 }
222155
223156 var toolParams map [string ]any
224157 if err := json .Unmarshal (paramsJson , & toolParams ); err != nil {
225- return nil , nil , errors .Wrap (err , "failed to decode tool parameters" )
158+ return nil , errors .Wrap (err , "failed to decode tool parameters" )
226159 }
227160
228161 toolParam := anthropic.ToolParam {
@@ -235,37 +168,44 @@ func (p *Anthropic) adaptRequest(_ internal.Adapter, requester llmberjack.Reques
235168 if tool .Description != "" {
236169 toolParam .Description = anthropic .String (tool .Description )
237170 }
238- params . Tools = append (params . Tools , toolParam )
171+ tools = append (tools , toolParam )
239172 }
240173
241- // System messages are handled as separate messages with RoleSystem
242-
243- // Resolve thinking configuration:
244- // - WithThinking(false) explicitly disables thinking
245- // - WithThinking(true) enables with BudgetTokens if set, otherwise default
246- // - BudgetTokens alone (without WithThinking) enables thinking
247- if r .Thinking != nil && ! * r .Thinking {
248- // Explicitly disabled, do not set thinking
249- } else if opts .BudgetTokens != nil && * opts .BudgetTokens > 0 {
250- params .Thinking = opts .BudgetTokens
251- } else if r .Thinking != nil && * r .Thinking {
252- params .Thinking = lo .ToPtr (DefaultThinkingBudgetTokens )
174+ // Handle system messages
175+ var systemText string
176+ for _ , msg := range r .Messages {
177+ if msg .Role == llmberjack .RoleSystem {
178+ for _ , part := range msg .Parts {
179+ if seeker , ok := part .(io.ReadSeeker ); ok {
180+ seeker .Seek (0 , io .SeekStart )
181+ }
182+ buf , _ := io .ReadAll (part )
183+ if systemText != "" {
184+ systemText += "\n "
185+ }
186+ systemText += string (buf )
187+ }
188+ }
253189 }
254190
255191 // Process messages
256192 for _ , msg := range r .Messages {
193+ if msg .Role == llmberjack .RoleSystem {
194+ continue // Already handled above
195+ }
196+
257197 parts := make ([]anthropic.ContentBlockParamUnion , 0 , len (msg .Parts ))
258198
259199 for _ , part := range msg .Parts {
260200 if seeker , ok := part .(io.ReadSeeker ); ok {
261201 if _ , err := seeker .Seek (0 , io .SeekStart ); err != nil {
262- return nil , nil , err
202+ return nil , err
263203 }
264204 }
265205
266206 buf , err := io .ReadAll (part )
267207 if err != nil {
268- return nil , nil , errors .Wrap (err , "could not read content part" )
208+ return nil , errors .Wrap (err , "could not read content part" )
269209 }
270210
271211 switch msg .Type {
@@ -289,26 +229,22 @@ func (p *Anthropic) adaptRequest(_ internal.Adapter, requester llmberjack.Reques
289229 Content : parts ,
290230 }
291231
292- case llmberjack .RoleSystem :
293- // System messages are handled separately in Anthropic SDK
294- continue
295-
296232 case llmberjack .RoleTool :
297233 if msg .Tool == nil {
298- return nil , nil , errors .New ("sent a tool response when no tool was invoked" )
234+ return nil , errors .New ("sent a tool response when no tool was invoked" )
299235 }
300236
301237 var toolContent string
302238 for _ , part := range msg .Parts {
303239 if seeker , ok := part .(io.ReadSeeker ); ok {
304240 _ , err := seeker .Seek (0 , io .SeekStart )
305241 if err != nil {
306- return nil , nil , errors .Wrap (err , "could not seek content part" )
242+ return nil , errors .Wrap (err , "could not seek content part" )
307243 }
308244 }
309245 buf , err := io .ReadAll (part )
310246 if err != nil {
311- return nil , nil , errors .Wrap (err , "could not read content part" )
247+ return nil , errors .Wrap (err , "could not read content part" )
312248 }
313249 toolContent = string (buf )
314250 }
@@ -328,7 +264,62 @@ func (p *Anthropic) adaptRequest(_ internal.Adapter, requester llmberjack.Reques
328264 messages = append (messages , msgParam )
329265 }
330266
331- return messages , params , nil
267+ // Build the complete MessageNewParams
268+ params := & anthropic.MessageNewParams {
269+ Model : model ,
270+ Messages : messages ,
271+ }
272+
273+ // Add system message if present
274+ if systemText != "" {
275+ params .System = []anthropic.TextBlockParam {
276+ {Text : systemText },
277+ }
278+ }
279+
280+ // Add tools if present
281+ if len (tools ) > 0 {
282+ toolUnions := make ([]anthropic.ToolUnionParam , len (tools ))
283+ for i , tool := range tools {
284+ toolUnions [i ] = anthropic .ToolUnionParamOfTool (
285+ tool .InputSchema ,
286+ tool .Name ,
287+ )
288+ toolUnions [i ].OfTool .Description = tool .Description
289+ }
290+ params .Tools = toolUnions
291+ }
292+
293+ // Add max tokens only if explicitly provided (Vertex AI requires > 0)
294+ if r .MaxTokens != nil {
295+ params .MaxTokens = int64 (* r .MaxTokens )
296+ } else if p .backend == BackendVertexAI {
297+ params .MaxTokens = BackendVertexAiDefaultMaxTokens
298+ }
299+
300+ // Add temperature
301+ if r .Temperature != nil {
302+ params .Temperature = anthropic .Float (* r .Temperature )
303+ }
304+
305+ // Add top_p
306+ if r .TopP != nil {
307+ params .TopP = anthropic .Float (* r .TopP )
308+ }
309+
310+ // Resolve thinking configuration
311+ if r .Thinking != nil && ! * r .Thinking {
312+ // Explicitly disabled, do not set thinking
313+ disabled := anthropic .NewThinkingConfigDisabledParam ()
314+ params .Thinking = anthropic.ThinkingConfigParamUnion {OfDisabled : & disabled }
315+ } else if opts .BudgetTokens != nil && * opts .BudgetTokens > 0 {
316+ params .Thinking = anthropic .ThinkingConfigParamOfEnabled (int64 (* opts .BudgetTokens ))
317+ } else if r .Thinking != nil && * r .Thinking {
318+ adaptative := anthropic.ThinkingConfigAdaptiveParam {Display : "summarized" , Type : "adaptive" }
319+ params .Thinking = anthropic.ThinkingConfigParamUnion {OfAdaptive : & adaptative }
320+ }
321+
322+ return params , nil
332323}
333324
334325func (p * Anthropic ) adaptResponse (_ internal.Adapter , response * anthropic.Message , requester llmberjack.Requester ) (* llmberjack.InnerResponse , error ) {
0 commit comments