@@ -113,18 +113,10 @@ func renderAssistantMessage(
113 width int,
113 width int,
114 position int,
114 position int,
115) []uiMessage {
115) []uiMessage {
116− // find the user message that is before this assistant message
117− var userMsg message.Message
118− for i := msgIndex - 1; i >= 0; i-- {
119− msg := allMessages[i]
120− if msg.Role == message.User {
121− userMsg = allMessages[i]
126 messages := []uiMessage{}
116 messages := []uiMessage{}
127 content := msg.Content().String()
117 content := msg.Content().String()
118+ thinking := msg.IsThinking()
119+ thinkingContent := msg.ReasoningContent().Thinking
128 finished := msg.IsFinished()
120 finished := msg.IsFinished()
129 finishData := msg.FinishPart()
121 finishData := msg.FinishPart()
130 info := []string{}
122 info := []string{}
@@ -133,7 +125,7 @@ func renderAssistantMessage(
133 if finished {
125 if finished {
134 switch finishData.Reason {
126 switch finishData.Reason {
135 case message.FinishReasonEndTurn:
127 case message.FinishReasonEndTurn:
136− took := formatTimeDifference(userMsg.CreatedAt, finishData.Time)
128+ took := formatTimeDifference(msg.CreatedAt, finishData.Time)
137 info = append(info, styles.BaseStyle.Width(width-1).Foreground(styles.ForgroundDim).Render(
129 info = append(info, styles.BaseStyle.Width(width-1).Foreground(styles.ForgroundDim).Render(
138 fmt.Sprintf(" %s (%s)", models.SupportedModels[msg.Model].Name, took),
130 fmt.Sprintf(" %s (%s)", models.SupportedModels[msg.Model].Name, took),
@@ -166,6 +158,9 @@ func renderAssistantMessage(
167 position += messages[0].height
159 position += messages[0].height
168 position++ // for the space
160 position++ // for the space
161+ } else if thinking && thinkingContent != "" {
162+ // Render the thinking content
163+ content = renderMessage(thinkingContent, false, msg.ID == focusedUIMessageId, width)
171 for i, toolCall := range msg.ToolCalls() {
166 for i, toolCall := range msg.ToolCalls() {
@@ -218,10 +213,40 @@ func toolName(name string) string {
218 return "View"
213 return "View"
219 case tools.WriteToolName:
214 case tools.WriteToolName:
220 return "Write"
215 return "Write"
216+ case tools.PatchToolName:
222 return name
219 return name
222+func getToolAction(name string) string {
224+ case agent.AgentToolName:
225+ return "Preparing prompt..."
226+ case tools.BashToolName:
227+ return "Building command..."
228+ case tools.EditToolName:
229+ return "Preparing edit..."
230+ case tools.FetchToolName:
231+ return "Writing fetch..."
232+ case tools.GlobToolName:
233+ return "Finding files..."
234+ case tools.GrepToolName:
235+ return "Searching content..."
236+ case tools.LSToolName:
237+ return "Listing directory..."
238+ case tools.SourcegraphToolName:
239+ return "Searching code..."
240+ case tools.ViewToolName:
241+ return "Reading file..."
242+ case tools.WriteToolName:
243+ return "Preparing write..."
244+ case tools.PatchToolName:
245+ return "Preparing patch..."
225// renders params, params[0] (params[1]=params[2] ....)
250// renders params, params[0] (params[1]=params[2] ....)
226func renderParams(paramsWidth int, params ...string) string {
251func renderParams(paramsWidth int, params ...string) string {
227 if len(params) == 0 {
252 if len(params) == 0 {
@@ -490,8 +515,47 @@ func renderToolMessage(
490 if nested {
515 if nested {
491 width = width - 3
516 width = width - 3
518+ style := styles.BaseStyle.
521+ BorderStyle(lipgloss.ThickBorder()).
523+ BorderForeground(styles.ForgroundDim)
493 response := findToolResponse(toolCall.ID, allMessages)
525 response := findToolResponse(toolCall.ID, allMessages)
494 toolName := styles.BaseStyle.Foreground(styles.ForgroundDim).Render(fmt.Sprintf("%s: ", toolName(toolCall.Name)))
526 toolName := styles.BaseStyle.Foreground(styles.ForgroundDim).Render(fmt.Sprintf("%s: ", toolName(toolCall.Name)))
528+ if !toolCall.Finished {
529+ // Get a brief description of what the tool is doing
530+ toolAction := getToolAction(toolCall.Name)
532+ // toolInput := strings.ReplaceAll(toolCall.Input, "\n", " ")
533+ // truncatedInput := toolInput
534+ // if len(truncatedInput) > 10 {
535+ // truncatedInput = truncatedInput[len(truncatedInput)-10:]
538+ // truncatedInput = styles.BaseStyle.
540+ // Width(width - 2 - lipgloss.Width(toolName)).
541+ // Background(styles.BackgroundDim).
542+ // Foreground(styles.ForgroundMid).
543+ // Render(truncatedInput)
545+ progressText := styles.BaseStyle.
546+ Width(width - 2 - lipgloss.Width(toolName)).
547+ Foreground(styles.ForgroundDim).
548+ Render(fmt.Sprintf("%s", toolAction))
550+ content := style.Render(lipgloss.JoinHorizontal(lipgloss.Left, toolName, progressText))
551+ toolMsg := uiMessage{
552+ messageType: toolMessageType,
554+ height: lipgloss.Height(content),
495 params := renderToolParams(width-2-lipgloss.Width(toolName), toolCall)
559 params := renderToolParams(width-2-lipgloss.Width(toolName), toolCall)
496 responseContent := ""
560 responseContent := ""
497 if response != nil {
561 if response != nil {
@@ -504,12 +568,6 @@ func renderToolMessage(
504 Foreground(styles.ForgroundDim).
568 Foreground(styles.ForgroundDim).
505 Render("Waiting for response...")
569 Render("Waiting for response...")
507− style := styles.BaseStyle.
510− BorderStyle(lipgloss.ThickBorder()).
512− BorderForeground(styles.ForgroundDim)
514 parts := []string{}
572 parts := []string{}
515 if !nested {
573 if !nested {