on main help sign in
Merge pull request #242 from charmbracelet/conditional-header
913b91eKujtim Hoxha
internal/llm/provider/anthropic.go+21−2
@@ -163,6 +163,15 @@ func (a *anthropicClient) finishReason(reason string) message.FinishReason {
163 }
163 }
164}
164}
165
165
166+func (a *anthropicClient) isThinkingEnabled() bool {
167+ cfg := config.Get()
168+ modelConfig := cfg.Models[config.SelectedModelTypeLarge]
169+ if a.providerOptions.modelType == config.SelectedModelTypeSmall {
170+ modelConfig = cfg.Models[config.SelectedModelTypeSmall]
171+ }
172+ return a.Model().CanReason && modelConfig.Think
173+}
174+
166func (a *anthropicClient) preparedMessages(messages []anthropic.MessageParam, tools []anthropic.ToolUnionParam) anthropic.MessageNewParams {
175func (a *anthropicClient) preparedMessages(messages []anthropic.MessageParam, tools []anthropic.ToolUnionParam) anthropic.MessageNewParams {
167 model := a.providerOptions.model(a.providerOptions.modelType)
176 model := a.providerOptions.model(a.providerOptions.modelType)
168 var thinkingParam anthropic.ThinkingConfigParamUnion
177 var thinkingParam anthropic.ThinkingConfigParamUnion
@@ -177,7 +186,7 @@ func (a *anthropicClient) preparedMessages(messages []anthropic.MessageParam, to
177 if modelConfig.MaxTokens > 0 {
186 if modelConfig.MaxTokens > 0 {
178 maxTokens = modelConfig.MaxTokens
187 maxTokens = modelConfig.MaxTokens
179 }
188 }
180− if a.Model().CanReason && modelConfig.Think {
189+ if a.isThinkingEnabled() {
181 thinkingParam = anthropic.ThinkingConfigParamOfEnabled(int64(float64(maxTokens) * 0.8))
190 thinkingParam = anthropic.ThinkingConfigParamOfEnabled(int64(float64(maxTokens) * 0.8))
182 temperature = anthropic.Float(1)
191 temperature = anthropic.Float(1)
183 }
192 }
@@ -222,9 +231,14 @@ func (a *anthropicClient) send(ctx context.Context, messages []message.Message,
222 slog.Debug("Prepared messages", "messages", string(jsonData))
231 slog.Debug("Prepared messages", "messages", string(jsonData))
223 }
232 }
224
233
234+ var opts []option.RequestOption
235+ if a.isThinkingEnabled() {
236+ opts = append(opts, option.WithHeaderAdd("anthropic-beta", "interleaved-thinking-2025-05-14"))
237+ }
225 anthropicResponse, err := a.client.Messages.New(
238 anthropicResponse, err := a.client.Messages.New(
226 ctx,
239 ctx,
227 preparedMessages,
240 preparedMessages,
241+ opts...,
228 )
242 )
229 // If there is an error we are going to see if we can retry the call
243 // If there is an error we are going to see if we can retry the call
230 if err != nil {
244 if err != nil {
@@ -274,10 +288,15 @@ func (a *anthropicClient) stream(ctx context.Context, messages []message.Message
274 slog.Debug("Prepared messages", "messages", string(jsonData))
288 slog.Debug("Prepared messages", "messages", string(jsonData))
275 }
289 }
276
290
291+ var opts []option.RequestOption
292+ if a.isThinkingEnabled() {
293+ opts = append(opts, option.WithHeaderAdd("anthropic-beta", "interleaved-thinking-2025-05-14"))
294+ }
295+
277 anthropicStream := a.client.Messages.NewStreaming(
296 anthropicStream := a.client.Messages.NewStreaming(
278 ctx,
297 ctx,
279 preparedMessages,
298 preparedMessages,
280− option.WithHeaderAdd("anthropic-beta", "interleaved-thinking-2025-05-14"),
299+ opts...,
281 )
300 )
282 accumulatedMessage := anthropic.Message{}
301 accumulatedMessage := anthropic.Message{}
283
302
internal/tui/components/chat/messages/messages.go+1−1
@@ -266,7 +266,7 @@ func (m *messageCmp) renderThinkingContent() string {
266 Description: duration.String(),
266 Description: duration.String(),
267 NoIcon: true,
267 NoIcon: true,
268 }
268 }
269− footer = t.S().Base.PaddingLeft(1).Render(core.Status(opts, m.textWidth()-1))
269+ return t.S().Base.PaddingLeft(1).Render(core.Status(opts, m.textWidth()-1))
270 } else if finishReason != nil && finishReason.Reason == message.FinishReasonCanceled {
270 } else if finishReason != nil && finishReason.Reason == message.FinishReasonCanceled {
271 footer = t.S().Base.PaddingLeft(1).Render(m.toMarkdown("*Canceled*"))
271 footer = t.S().Base.PaddingLeft(1).Render(m.toMarkdown("*Canceled*"))
272 } else {
272 } else {