on main help sign in
fix(ui): render nested tools consistently across states
b05a4adChristian Rocha
internal/ui/chat/agent.go+2−2
@@ -101,7 +101,7 @@ type AgentToolRenderContext struct {
101func (r *AgentToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
101func (r *AgentToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
102 cappedWidth := cappedMessageWidth(width)
102 cappedWidth := cappedMessageWidth(width)
103 if !opts.ToolCall.Finished && !opts.IsCanceled() && len(r.agent.nestedTools) == 0 {
103 if !opts.ToolCall.Finished && !opts.IsCanceled() && len(r.agent.nestedTools) == 0 {
104− return pendingTool(sty, "Agent", opts.Anim)
104+ return pendingTool(sty, "Agent", opts.Anim, opts.Compact)
105 }
105 }
106
106
107 var params agent.AgentParams
107 var params agent.AgentParams
@@ -232,7 +232,7 @@ type agenticFetchParams struct {
232func (r *AgenticFetchToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
232func (r *AgenticFetchToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
233 cappedWidth := cappedMessageWidth(width)
233 cappedWidth := cappedMessageWidth(width)
234 if !opts.ToolCall.Finished && !opts.IsCanceled() && len(r.fetch.nestedTools) == 0 {
234 if !opts.ToolCall.Finished && !opts.IsCanceled() && len(r.fetch.nestedTools) == 0 {
235− return pendingTool(sty, "Agentic Fetch", opts.Anim)
235+ return pendingTool(sty, "Agentic Fetch", opts.Anim, opts.Compact)
236 }
236 }
237
237
238 var params agenticFetchParams
238 var params agenticFetchParams
internal/ui/chat/bash.go+3−3
@@ -41,7 +41,7 @@ type BashToolRenderContext struct{}
41func (b *BashToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
41func (b *BashToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
42 cappedWidth := cappedMessageWidth(width)
42 cappedWidth := cappedMessageWidth(width)
43 if opts.IsPending() {
43 if opts.IsPending() {
44− return pendingTool(sty, "Bash", opts.Anim)
44+ return pendingTool(sty, "Bash", opts.Anim, opts.Compact)
45 }
45 }
46
46
47 var params tools.BashParams
47 var params tools.BashParams
@@ -123,7 +123,7 @@ type JobOutputToolRenderContext struct{}
123func (j *JobOutputToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
123func (j *JobOutputToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
124 cappedWidth := cappedMessageWidth(width)
124 cappedWidth := cappedMessageWidth(width)
125 if opts.IsPending() {
125 if opts.IsPending() {
126− return pendingTool(sty, "Job", opts.Anim)
126+ return pendingTool(sty, "Job", opts.Anim, opts.Compact)
127 }
127 }
128
128
129 var params tools.JobOutputParams
129 var params tools.JobOutputParams
@@ -174,7 +174,7 @@ type JobKillToolRenderContext struct{}
174func (j *JobKillToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
174func (j *JobKillToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
175 cappedWidth := cappedMessageWidth(width)
175 cappedWidth := cappedMessageWidth(width)
176 if opts.IsPending() {
176 if opts.IsPending() {
177− return pendingTool(sty, "Job", opts.Anim)
177+ return pendingTool(sty, "Job", opts.Anim, opts.Compact)
178 }
178 }
179
179
180 var params tools.JobKillParams
180 var params tools.JobKillParams
internal/ui/chat/diagnostics.go+1−1
@@ -37,7 +37,7 @@ type DiagnosticsToolRenderContext struct{}
37func (d *DiagnosticsToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
37func (d *DiagnosticsToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
38 cappedWidth := cappedMessageWidth(width)
38 cappedWidth := cappedMessageWidth(width)
39 if opts.IsPending() {
39 if opts.IsPending() {
40− return pendingTool(sty, "Diagnostics", opts.Anim)
40+ return pendingTool(sty, "Diagnostics", opts.Anim, opts.Compact)
41 }
41 }
42
42
43 var params tools.DiagnosticsParams
43 var params tools.DiagnosticsParams
internal/ui/chat/fetch.go+3−3
@@ -36,7 +36,7 @@ type FetchToolRenderContext struct{}
36func (f *FetchToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
36func (f *FetchToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
37 cappedWidth := cappedMessageWidth(width)
37 cappedWidth := cappedMessageWidth(width)
38 if opts.IsPending() {
38 if opts.IsPending() {
39− return pendingTool(sty, "Fetch", opts.Anim)
39+ return pendingTool(sty, "Fetch", opts.Anim, opts.Compact)
40 }
40 }
41
41
42 var params tools.FetchParams
42 var params tools.FetchParams
@@ -111,7 +111,7 @@ type WebFetchToolRenderContext struct{}
111func (w *WebFetchToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
111func (w *WebFetchToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
112 cappedWidth := cappedMessageWidth(width)
112 cappedWidth := cappedMessageWidth(width)
113 if opts.IsPending() {
113 if opts.IsPending() {
114− return pendingTool(sty, "Fetch", opts.Anim)
114+ return pendingTool(sty, "Fetch", opts.Anim, opts.Compact)
115 }
115 }
116
116
117 var params tools.WebFetchParams
117 var params tools.WebFetchParams
@@ -165,7 +165,7 @@ type WebSearchToolRenderContext struct{}
165func (w *WebSearchToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
165func (w *WebSearchToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
166 cappedWidth := cappedMessageWidth(width)
166 cappedWidth := cappedMessageWidth(width)
167 if opts.IsPending() {
167 if opts.IsPending() {
168− return pendingTool(sty, "Search", opts.Anim)
168+ return pendingTool(sty, "Search", opts.Anim, opts.Compact)
169 }
169 }
170
170
171 var params tools.WebSearchParams
171 var params tools.WebSearchParams
internal/ui/chat/file.go+5−5
@@ -39,7 +39,7 @@ type ViewToolRenderContext struct{}
39func (v *ViewToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
39func (v *ViewToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
40 cappedWidth := cappedMessageWidth(width)
40 cappedWidth := cappedMessageWidth(width)
41 if opts.IsPending() {
41 if opts.IsPending() {
42− return pendingTool(sty, "View", opts.Anim)
42+ return pendingTool(sty, "View", opts.Anim, opts.Compact)
43 }
43 }
44
44
45 var params tools.ViewParams
45 var params tools.ViewParams
@@ -125,7 +125,7 @@ type WriteToolRenderContext struct{}
125func (w *WriteToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
125func (w *WriteToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
126 cappedWidth := cappedMessageWidth(width)
126 cappedWidth := cappedMessageWidth(width)
127 if opts.IsPending() {
127 if opts.IsPending() {
128− return pendingTool(sty, "Write", opts.Anim)
128+ return pendingTool(sty, "Write", opts.Anim, opts.Compact)
129 }
129 }
130
130
131 var params tools.WriteParams
131 var params tools.WriteParams
@@ -180,7 +180,7 @@ type EditToolRenderContext struct{}
180func (e *EditToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
180func (e *EditToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
181 // Edit tool uses full width for diffs.
181 // Edit tool uses full width for diffs.
182 if opts.IsPending() {
182 if opts.IsPending() {
183− return pendingTool(sty, "Edit", opts.Anim)
183+ return pendingTool(sty, "Edit", opts.Anim, opts.Compact)
184 }
184 }
185
185
186 var params tools.EditParams
186 var params tools.EditParams
@@ -243,7 +243,7 @@ type MultiEditToolRenderContext struct{}
243func (m *MultiEditToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
243func (m *MultiEditToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
244 // MultiEdit tool uses full width for diffs.
244 // MultiEdit tool uses full width for diffs.
245 if opts.IsPending() {
245 if opts.IsPending() {
246− return pendingTool(sty, "Multi-Edit", opts.Anim)
246+ return pendingTool(sty, "Multi-Edit", opts.Anim, opts.Compact)
247 }
247 }
248
248
249 var params tools.MultiEditParams
249 var params tools.MultiEditParams
@@ -311,7 +311,7 @@ type DownloadToolRenderContext struct{}
311func (d *DownloadToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
311func (d *DownloadToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
312 cappedWidth := cappedMessageWidth(width)
312 cappedWidth := cappedMessageWidth(width)
313 if opts.IsPending() {
313 if opts.IsPending() {
314− return pendingTool(sty, "Download", opts.Anim)
314+ return pendingTool(sty, "Download", opts.Anim, opts.Compact)
315 }
315 }
316
316
317 var params tools.DownloadParams
317 var params tools.DownloadParams
internal/ui/chat/generic.go+1−1
@@ -35,7 +35,7 @@ func (g *GenericToolRenderContext) RenderTool(sty *styles.Styles, width int, opt
35 name := genericPrettyName(opts.ToolCall.Name)
35 name := genericPrettyName(opts.ToolCall.Name)
36
36
37 if opts.IsPending() {
37 if opts.IsPending() {
38− return pendingTool(sty, name, opts.Anim)
38+ return pendingTool(sty, name, opts.Anim, opts.Compact)
39 }
39 }
40
40
41 var params map[string]any
41 var params map[string]any
internal/ui/chat/lsp_restart.go+1−1
@@ -32,7 +32,7 @@ type LSPRestartToolRenderContext struct{}
32func (r *LSPRestartToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
32func (r *LSPRestartToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
33 cappedWidth := cappedMessageWidth(width)
33 cappedWidth := cappedMessageWidth(width)
34 if opts.IsPending() {
34 if opts.IsPending() {
35− return pendingTool(sty, "Restart LSP", opts.Anim)
35+ return pendingTool(sty, "Restart LSP", opts.Anim, opts.Compact)
36 }
36 }
37
37
38 var params tools.LSPRestartParams
38 var params tools.LSPRestartParams
internal/ui/chat/mcp.go+1−1
@@ -46,7 +46,7 @@ func (b *MCPToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *T
46 name := fmt.Sprintf("%s %s %s", mcpName, sty.Tool.MCPArrow.String(), toolName)
46 name := fmt.Sprintf("%s %s %s", mcpName, sty.Tool.MCPArrow.String(), toolName)
47
47
48 if opts.IsPending() {
48 if opts.IsPending() {
49− return pendingTool(sty, name, opts.Anim)
49+ return pendingTool(sty, name, opts.Anim, opts.Compact)
50 }
50 }
51
51
52 var params map[string]any
52 var params map[string]any
internal/ui/chat/references.go+1−1
@@ -33,7 +33,7 @@ type ReferencesToolRenderContext struct{}
33func (r *ReferencesToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
33func (r *ReferencesToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
34 cappedWidth := cappedMessageWidth(width)
34 cappedWidth := cappedMessageWidth(width)
35 if opts.IsPending() {
35 if opts.IsPending() {
36− return pendingTool(sty, "Find References", opts.Anim)
36+ return pendingTool(sty, "Find References", opts.Anim, opts.Compact)
37 }
37 }
38
38
39 var params tools.ReferencesParams
39 var params tools.ReferencesParams
internal/ui/chat/search.go+4−4
@@ -37,7 +37,7 @@ type GlobToolRenderContext struct{}
37func (g *GlobToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
37func (g *GlobToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
38 cappedWidth := cappedMessageWidth(width)
38 cappedWidth := cappedMessageWidth(width)
39 if opts.IsPending() {
39 if opts.IsPending() {
40− return pendingTool(sty, "Glob", opts.Anim)
40+ return pendingTool(sty, "Glob", opts.Anim, opts.Compact)
41 }
41 }
42
42
43 var params tools.GlobParams
43 var params tools.GlobParams
@@ -96,7 +96,7 @@ type GrepToolRenderContext struct{}
96func (g *GrepToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
96func (g *GrepToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
97 cappedWidth := cappedMessageWidth(width)
97 cappedWidth := cappedMessageWidth(width)
98 if opts.IsPending() {
98 if opts.IsPending() {
99− return pendingTool(sty, "Grep", opts.Anim)
99+ return pendingTool(sty, "Grep", opts.Anim, opts.Compact)
100 }
100 }
101
101
102 var params tools.GrepParams
102 var params tools.GrepParams
@@ -161,7 +161,7 @@ type LSToolRenderContext struct{}
161func (l *LSToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
161func (l *LSToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
162 cappedWidth := cappedMessageWidth(width)
162 cappedWidth := cappedMessageWidth(width)
163 if opts.IsPending() {
163 if opts.IsPending() {
164− return pendingTool(sty, "List", opts.Anim)
164+ return pendingTool(sty, "List", opts.Anim, opts.Compact)
165 }
165 }
166
166
167 var params tools.LSParams
167 var params tools.LSParams
@@ -221,7 +221,7 @@ type SourcegraphToolRenderContext struct{}
221func (s *SourcegraphToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
221func (s *SourcegraphToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
222 cappedWidth := cappedMessageWidth(width)
222 cappedWidth := cappedMessageWidth(width)
223 if opts.IsPending() {
223 if opts.IsPending() {
224− return pendingTool(sty, "Sourcegraph", opts.Anim)
224+ return pendingTool(sty, "Sourcegraph", opts.Anim, opts.Compact)
225 }
225 }
226
226
227 var params tools.SourcegraphParams
227 var params tools.SourcegraphParams
internal/ui/chat/todos.go+1−1
@@ -41,7 +41,7 @@ type TodosToolRenderContext struct{}
41func (t *TodosToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
41func (t *TodosToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
42 cappedWidth := cappedMessageWidth(width)
42 cappedWidth := cappedMessageWidth(width)
43 if opts.IsPending() {
43 if opts.IsPending() {
44− return pendingTool(sty, "To-Do", opts.Anim)
44+ return pendingTool(sty, "To-Do", opts.Anim, opts.Compact)
45 }
45 }
46
46
47 var params tools.TodosParams
47 var params tools.TodosParams
internal/ui/chat/tools.go+6−2
@@ -424,9 +424,13 @@ func (t *baseToolMessageItem) HandleKeyEvent(key tea.KeyMsg) (bool, tea.Cmd) {
424}
424}
425
425
426// pendingTool renders a tool that is still in progress with an animation.
426// pendingTool renders a tool that is still in progress with an animation.
427−func pendingTool(sty *styles.Styles, name string, anim *anim.Anim) string {
427+func pendingTool(sty *styles.Styles, name string, anim *anim.Anim, nested bool) string {
428 icon := sty.Tool.IconPending.Render()
428 icon := sty.Tool.IconPending.Render()
429− toolName := sty.Tool.NameNormal.Render(name)
429+ nameStyle := sty.Tool.NameNormal
430+ if nested {
431+ nameStyle = sty.Tool.NameNested
432+ }
433+ toolName := nameStyle.Render(name)
430
434
431 var animView string
435 var animView string
432 if anim != nil {
436 if anim != nil {
internal/ui/styles/styles.go+9−9
@@ -254,18 +254,18 @@ type Styles struct {
254 // Tool - styles for tool call rendering
254 // Tool - styles for tool call rendering
255 Tool struct {
255 Tool struct {
256 // Icon styles with tool status
256 // Icon styles with tool status
257− IconPending lipgloss.Style // Pending operation icon
257+ IconPending lipgloss.Style
258− IconSuccess lipgloss.Style // Successful operation icon
258+ IconSuccess lipgloss.Style
259− IconError lipgloss.Style // Error operation icon
259+ IconError lipgloss.Style
260− IconCancelled lipgloss.Style // Cancelled operation icon
260+ IconCancelled lipgloss.Style
261
261
262 // Tool name styles
262 // Tool name styles
263− NameNormal lipgloss.Style // Normal tool name
263+ NameNormal lipgloss.Style // Top-level tool name
264− NameNested lipgloss.Style // Nested tool name
264+ NameNested lipgloss.Style // Nested child tool name (inside Agent/Agentic Fetch)
265
265
266 // Parameter list styles
266 // Parameter list styles
267− ParamMain lipgloss.Style // Main parameter
267+ ParamMain lipgloss.Style
268− ParamKey lipgloss.Style // Parameter keys
268+ ParamKey lipgloss.Style
269
269
270 // Content rendering styles
270 // Content rendering styles
271 ContentLine lipgloss.Style // Individual content line with background and width
271 ContentLine lipgloss.Style // Individual content line with background and width
@@ -1119,7 +1119,7 @@ func DefaultStyles() Styles {
1119 s.Tool.IconCancelled = s.Muted.SetString(ToolPending)
1119 s.Tool.IconCancelled = s.Muted.SetString(ToolPending)
1120
1120
1121 s.Tool.NameNormal = base.Foreground(blue)
1121 s.Tool.NameNormal = base.Foreground(blue)
1122− s.Tool.NameNested = base.Foreground(fgHalfMuted)
1122+ s.Tool.NameNested = base.Foreground(blue)
1123
1123
1124 s.Tool.ParamMain = s.Subtle
1124 s.Tool.ParamMain = s.Subtle
1125 s.Tool.ParamKey = s.Subtle
1125 s.Tool.ParamKey = s.Subtle