diff --git a/internal/tui/components/chat/messages/messages.go b/internal/tui/components/chat/messages/messages.go index 078caf7dcd941eebab7d1a2989b25539c41989e4..bff149c72807f637a58a6d14878b3ac209f05541 100644 --- a/internal/tui/components/chat/messages/messages.go +++ b/internal/tui/components/chat/messages/messages.go @@ -252,6 +252,7 @@ func (m *messageCmp) renderThinkingContent() string { m.thinkingViewport.SetWidth(m.textWidth()) m.thinkingViewport.SetContent(fullContent) m.thinkingViewport.GotoBottom() + finishReason := m.message.FinishPart() var footer string if reasoningContent.StartedAt > 0 { duration := m.message.ThinkingDuration() @@ -263,6 +264,8 @@ func (m *messageCmp) renderThinkingContent() string { NoIcon: true, } footer = t.S().Base.PaddingLeft(1).Render(core.Status(opts, m.textWidth()-1)) + } else if finishReason != nil && finishReason.Reason == message.FinishReasonCanceled { + footer = t.S().Base.PaddingLeft(1).Render(m.toMarkdown("*Canceled*")) } else { footer = m.anim.View() } diff --git a/internal/tui/components/chat/sidebar/sidebar.go b/internal/tui/components/chat/sidebar/sidebar.go index cf1fd12dff512475fa77f0cd9fb657646c0cc2fd..ecb88e7d60dbaf09dfc2e88f789ed0057ee756fc 100644 --- a/internal/tui/components/chat/sidebar/sidebar.go +++ b/internal/tui/components/chat/sidebar/sidebar.go @@ -12,6 +12,7 @@ import ( "github.com/charmbracelet/crush/internal/config" "github.com/charmbracelet/crush/internal/diff" "github.com/charmbracelet/crush/internal/fsext" + "github.com/charmbracelet/crush/internal/fur/provider" "github.com/charmbracelet/crush/internal/history" "github.com/charmbracelet/crush/internal/lsp" "github.com/charmbracelet/crush/internal/lsp/protocol" @@ -26,6 +27,8 @@ import ( "github.com/charmbracelet/crush/internal/version" "github.com/charmbracelet/lipgloss/v2" "github.com/charmbracelet/x/ansi" + "golang.org/x/text/cases" + "golang.org/x/text/language" ) type FileHistory struct { @@ -880,8 +883,13 @@ func formatTokensAndCost(tokens, contextWindow int64, cost float64) string { } func (s *sidebarCmp) currentModelBlock() string { - agentCfg := config.Get().Agents["coder"] + cfg := config.Get() + agentCfg := cfg.Agents["coder"] + + selectedModel := cfg.Models[agentCfg.Model] + model := config.Get().GetModelByType(agentCfg.Model) + modelProvider := config.Get().GetProviderForModel(agentCfg.Model) t := styles.CurrentTheme() @@ -891,6 +899,25 @@ func (s *sidebarCmp) currentModelBlock() string { parts := []string{ modelInfo, } + if model.CanReason { + reasoningInfoStyle := t.S().Subtle.PaddingLeft(2) + switch modelProvider.Type { + case provider.TypeOpenAI: + reasoningEffort := model.DefaultReasoningEffort + if selectedModel.ReasoningEffort != "" { + reasoningEffort = selectedModel.ReasoningEffort + } + formatter := cases.Title(language.English, cases.NoLower) + parts = append(parts, reasoningInfoStyle.Render(formatter.String(fmt.Sprintf("Reasoning %s", reasoningEffort)))) + case provider.TypeAnthropic: + formatter := cases.Title(language.English, cases.NoLower) + if selectedModel.Think { + parts = append(parts, reasoningInfoStyle.Render(formatter.String("Thinking on"))) + } else { + parts = append(parts, reasoningInfoStyle.Render(formatter.String("Thinking off"))) + } + } + } if s.session.ID != "" { parts = append( parts,