on main help sign in
feat(ui): allow expanding toolcall names
commitdb8add714e294401ce2e716459376f3803fac3ce authorKieran Klukas <kieran@dunkirk.sh> dateFri 26 Jun 2026, 11:07 (4 months ago) parenta9e3a57
13 files changed+43−28
internal/ui/chat/agent.go+2−2 internal/ui/chat/bash.go+1−1 internal/ui/chat/diagnostics.go+1−1 internal/ui/chat/docker_mcp.go+2−2 internal/ui/chat/fetch.go+3−3 internal/ui/chat/file.go+5−5 internal/ui/chat/generic.go+1−1 internal/ui/chat/lsp_restart.go+1−1 internal/ui/chat/mcp.go+1−1 internal/ui/chat/references.go+1−1 internal/ui/chat/search.go+4−4 internal/ui/chat/todos.go+1−1 internal/ui/chat/tools.go+20−5
internal/ui/chat/agent.go+2−2
@@ -136,7 +136,7 @@ func (r *AgentToolRenderContext) RenderTool(sty *styles.Styles, width int, opts
136136 prompt := params.Prompt
137137 prompt = strings.ReplaceAll(prompt, "\n", " ")
138138
139− header := toolHeader(sty, opts.Status, "Agent", cappedWidth, opts.Compact)
139+ header := toolHeader(sty, opts.Status, "Agent", cappedWidth, opts)
140140 if opts.Compact {
141141 return header
142142 }
@@ -303,7 +303,7 @@ func (r *AgenticFetchToolRenderContext) RenderTool(sty *styles.Styles, width int
303303 toolParams = append(toolParams, params.URL)
304304 }
305305
306− header := toolHeader(sty, opts.Status, "Agentic Fetch", cappedWidth, opts.Compact, toolParams...)
306+ header := toolHeader(sty, opts.Status, "Agentic Fetch", cappedWidth, opts, toolParams...)
307307 if opts.Compact {
308308 return header
309309 }
internal/ui/chat/bash.go+1−1
@@ -69,7 +69,7 @@ func (b *BashToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *
6969 toolParams = append(toolParams, "background", "true")
7070 }
7171
72− header := toolHeader(sty, opts.Status, "Bash", cappedWidth, opts.Compact, toolParams...)
72+ header := toolHeader(sty, opts.Status, "Bash", cappedWidth, opts, toolParams...)
7373 if opts.Compact {
7474 return header
7575 }
internal/ui/chat/diagnostics.go+1−1
@@ -49,7 +49,7 @@ func (d *DiagnosticsToolRenderContext) RenderTool(sty *styles.Styles, width int,
4949 mainParam = fsext.PrettyPath(params.FilePath)
5050 }
5151
52− header := toolHeader(sty, opts.Status, "Diagnostics", cappedWidth, opts.Compact, mainParam)
52+ header := toolHeader(sty, opts.Status, "Diagnostics", cappedWidth, opts, mainParam)
5353 if opts.Compact {
5454 return header
5555 }
internal/ui/chat/docker_mcp.go+2−2
@@ -220,7 +220,7 @@ func (d *DockerMCPToolRenderContext) makeHeader(sty *styles.Styles, tool string,
220220 icon = sty.Tool.IconPending.Render()
221221 }
222222 prefix := fmt.Sprintf("%s %s ", icon, d.formatToolName(sty, tool))
223− return prefix + toolParamList(sty, params, width-lipgloss.Width(prefix))
223+ return prefix + toolParamList(sty, params, width-lipgloss.Width(prefix), opts)
224224}
225225
226226func (d *DockerMCPToolRenderContext) formatToolName(sty *styles.Styles, tool string) string {
@@ -274,7 +274,7 @@ func (d *DockerMCPToolRenderContext) makeCompactHeader(sty *styles.Styles, tool
274274 }
275275
276276 name := fmt.Sprintf("Docker MCP: %s", action)
277− return toolHeader(sty, ToolStatusSuccess, name, width, true, params...)
277+ return toolHeader(sty, ToolStatusSuccess, name, width, &ToolRenderOpts{Compact: true}, params...)
278278}
279279
280280// IsDockerMCPTool returns true if the tool name is a Docker MCP tool.
internal/ui/chat/fetch.go+3−3
@@ -52,7 +52,7 @@ func (f *FetchToolRenderContext) RenderTool(sty *styles.Styles, width int, opts
5252 toolParams = append(toolParams, "timeout", formatTimeout(params.Timeout))
5353 }
5454
55− header := toolHeader(sty, opts.Status, "Fetch", cappedWidth, opts.Compact, toolParams...)
55+ header := toolHeader(sty, opts.Status, "Fetch", cappedWidth, opts, toolParams...)
5656 if opts.Compact {
5757 return header
5858 }
@@ -120,7 +120,7 @@ func (w *WebFetchToolRenderContext) RenderTool(sty *styles.Styles, width int, op
120120 }
121121
122122 toolParams := []string{params.URL}
123− header := toolHeader(sty, opts.Status, "Fetch", cappedWidth, opts.Compact, toolParams...)
123+ header := toolHeader(sty, opts.Status, "Fetch", cappedWidth, opts, toolParams...)
124124 if opts.Compact {
125125 return header
126126 }
@@ -174,7 +174,7 @@ func (w *WebSearchToolRenderContext) RenderTool(sty *styles.Styles, width int, o
174174 }
175175
176176 toolParams := []string{params.Query}
177− header := toolHeader(sty, opts.Status, "Search", cappedWidth, opts.Compact, toolParams...)
177+ header := toolHeader(sty, opts.Status, "Search", cappedWidth, opts, toolParams...)
178178 if opts.Compact {
179179 return header
180180 }
internal/ui/chat/file.go+5−5
@@ -56,7 +56,7 @@ func (v *ViewToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *
5656 toolParams = append(toolParams, "offset", fmt.Sprintf("%d", params.Offset))
5757 }
5858
59− header := toolHeader(sty, opts.Status, "View", cappedWidth, opts.Compact, toolParams...)
59+ header := toolHeader(sty, opts.Status, "View", cappedWidth, opts, toolParams...)
6060 if opts.Compact {
6161 return header
6262 }
@@ -134,7 +134,7 @@ func (w *WriteToolRenderContext) RenderTool(sty *styles.Styles, width int, opts
134134 }
135135
136136 file := fsext.PrettyPath(params.FilePath)
137− header := toolHeader(sty, opts.Status, "Write", cappedWidth, opts.Compact, file)
137+ header := toolHeader(sty, opts.Status, "Write", cappedWidth, opts, file)
138138 if opts.Compact {
139139 return header
140140 }
@@ -203,7 +203,7 @@ func (e *EditToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *
203203 }
204204
205205 file := fsext.PrettyPath(params.FilePath)
206− header := toolHeader(sty, opts.Status, "Edit", width, opts.Compact, file)
206+ header := toolHeader(sty, opts.Status, "Edit", width, opts, file)
207207 if opts.Compact {
208208 return header
209209 }
@@ -276,7 +276,7 @@ func (m *MultiEditToolRenderContext) RenderTool(sty *styles.Styles, width int, o
276276 toolParams = append(toolParams, "edits", fmt.Sprintf("%d", len(params.Edits)))
277277 }
278278
279− header := toolHeader(sty, opts.Status, "Multi-Edit", width, opts.Compact, toolParams...)
279+ header := toolHeader(sty, opts.Status, "Multi-Edit", width, opts, toolParams...)
280280 if opts.Compact {
281281 return header
282282 }
@@ -352,7 +352,7 @@ func (d *DownloadToolRenderContext) RenderTool(sty *styles.Styles, width int, op
352352 toolParams = append(toolParams, "timeout", formatTimeout(params.Timeout))
353353 }
354354
355− header := toolHeader(sty, opts.Status, "Download", cappedWidth, opts.Compact, toolParams...)
355+ header := toolHeader(sty, opts.Status, "Download", cappedWidth, opts, toolParams...)
356356 if opts.Compact {
357357 return header
358358 }
internal/ui/chat/generic.go+1−1
@@ -48,7 +48,7 @@ func (g *GenericToolRenderContext) RenderTool(sty *styles.Styles, width int, opt
4848 toolParams = append(toolParams, string(parsed))
4949 }
5050
51− header := toolHeader(sty, opts.Status, name, cappedWidth, opts.Compact, toolParams...)
51+ header := toolHeader(sty, opts.Status, name, cappedWidth, opts, toolParams...)
5252 if opts.Compact {
5353 return header
5454 }
internal/ui/chat/lsp_restart.go+1−1
@@ -43,7 +43,7 @@ func (r *LSPRestartToolRenderContext) RenderTool(sty *styles.Styles, width int,
4343 toolParams = append(toolParams, params.Name)
4444 }
4545
46− header := toolHeader(sty, opts.Status, "Restart LSP", cappedWidth, opts.Compact, toolParams...)
46+ header := toolHeader(sty, opts.Status, "Restart LSP", cappedWidth, opts, toolParams...)
4747 if opts.Compact {
4848 return header
4949 }
internal/ui/chat/mcp.go+1−1
@@ -59,7 +59,7 @@ func (b *MCPToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *T
5959 toolParams = append(toolParams, string(parsed))
6060 }
6161
62− header := toolHeader(sty, opts.Status, name, cappedWidth, opts.Compact, toolParams...)
62+ header := toolHeader(sty, opts.Status, name, cappedWidth, opts, toolParams...)
6363 if opts.Compact {
6464 return header
6565 }
internal/ui/chat/references.go+1−1
@@ -44,7 +44,7 @@ func (r *ReferencesToolRenderContext) RenderTool(sty *styles.Styles, width int,
4444 toolParams = append(toolParams, "path", fsext.PrettyPath(params.Path))
4545 }
4646
47− header := toolHeader(sty, opts.Status, "Find References", cappedWidth, opts.Compact, toolParams...)
47+ header := toolHeader(sty, opts.Status, "Find References", cappedWidth, opts, toolParams...)
4848 if opts.Compact {
4949 return header
5050 }
internal/ui/chat/search.go+4−4
@@ -50,7 +50,7 @@ func (g *GlobToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *
5050 toolParams = append(toolParams, "path", params.Path)
5151 }
5252
53− header := toolHeader(sty, opts.Status, "Glob", cappedWidth, opts.Compact, toolParams...)
53+ header := toolHeader(sty, opts.Status, "Glob", cappedWidth, opts, toolParams...)
5454 if opts.Compact {
5555 return header
5656 }
@@ -115,7 +115,7 @@ func (g *GrepToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *
115115 toolParams = append(toolParams, "literal", "true")
116116 }
117117
118− header := toolHeader(sty, opts.Status, "Grep", cappedWidth, opts.Compact, toolParams...)
118+ header := toolHeader(sty, opts.Status, "Grep", cappedWidth, opts, toolParams...)
119119 if opts.Compact {
120120 return header
121121 }
@@ -175,7 +175,7 @@ func (l *LSToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *To
175175 }
176176 path = fsext.PrettyPath(path)
177177
178− header := toolHeader(sty, opts.Status, "List", cappedWidth, opts.Compact, path)
178+ header := toolHeader(sty, opts.Status, "List", cappedWidth, opts, path)
179179 if opts.Compact {
180180 return header
181181 }
@@ -237,7 +237,7 @@ func (s *SourcegraphToolRenderContext) RenderTool(sty *styles.Styles, width int,
237237 toolParams = append(toolParams, "context", formatNonZero(params.ContextWindow))
238238 }
239239
240− header := toolHeader(sty, opts.Status, "Sourcegraph", cappedWidth, opts.Compact, toolParams...)
240+ header := toolHeader(sty, opts.Status, "Sourcegraph", cappedWidth, opts, toolParams...)
241241 if opts.Compact {
242242 return header
243243 }
internal/ui/chat/todos.go+1−1
@@ -119,7 +119,7 @@ func (t *TodosToolRenderContext) RenderTool(sty *styles.Styles, width int, opts
119119 }
120120
121121 toolParams := []string{headerText}
122− header := toolHeader(sty, opts.Status, "To-Do", cappedWidth, opts.Compact, toolParams...)
122+ header := toolHeader(sty, opts.Status, "To-Do", cappedWidth, opts, toolParams...)
123123 if opts.Compact {
124124 return header
125125 }
internal/ui/chat/tools.go+20−5
@@ -569,9 +569,9 @@ func toolIcon(sty *styles.Styles, status ToolStatus) string {
569569 }
570570}
571571
572−// toolParamList formats parameters as "main (key=value, ...)" with truncation.
573572// toolParamList formats tool parameters as "main (key=value, ...)" with truncation.
574−func toolParamList(sty *styles.Styles, params []string, width int) string {
573+// When opts.ExpandedContent is true, the output wraps instead of truncating.
574+func toolParamList(sty *styles.Styles, params []string, width int, opts *ToolRenderOpts) string {
575575 // minSpaceForMainParam is the min space required for the main param
576576 // if this is less that the value set we will only show the main param nothing else
577577 const minSpaceForMainParam = 30
@@ -598,14 +598,18 @@ func toolParamList(sty *styles.Styles, params []string, width int) string {
598598 }
599599 }
600600
601− if width >= 0 {
601+ if width >= 0 && (opts == nil || !opts.ExpandedContent) {
602602 output = ansi.Truncate(output, width, "…")
603+ } else if opts != nil && opts.ExpandedContent && width > 0 && lipgloss.Width(output) > width {
604+ output = ansi.Hardwrap(output, width, false)
603605 }
604606 return sty.Tool.ParamMain.Render(output)
605607}
606608
607609// toolHeader builds the tool header line: "● ToolName params..."
608−func toolHeader(sty *styles.Styles, status ToolStatus, name string, width int, nested bool, params ...string) string {
610+// When opts.ExpandedContent is true, long parameters wrap instead of truncating.
611+func toolHeader(sty *styles.Styles, status ToolStatus, name string, width int, opts *ToolRenderOpts, params ...string) string {
612+ nested := opts != nil && opts.Compact
609613 icon := toolIcon(sty, status)
610614 nameStyle := sty.Tool.NameNormal
611615 if nested {
@@ -615,7 +619,18 @@ func toolHeader(sty *styles.Styles, status ToolStatus, name string, width int, n
615619 prefix := fmt.Sprintf("%s %s ", icon, toolName)
616620 prefixWidth := lipgloss.Width(prefix)
617621 remainingWidth := width - prefixWidth
618− paramsStr := toolParamList(sty, params, remainingWidth)
622+ paramsStr := toolParamList(sty, params, remainingWidth, opts)
623+
624+ // When expanded, toolParamList may return multiple lines. Indent
625+ // continuation lines to align with the first line's param text.
626+ if strings.Contains(paramsStr, "\n") {
627+ lines := strings.Split(paramsStr, "\n")
628+ indent := strings.Repeat(" ", prefixWidth)
629+ for i := 1; i < len(lines); i++ {
630+ lines[i] = indent + lines[i]
631+ }
632+ return prefix + strings.Join(lines, "\n")
633+ }
619634 return prefix + paramsStr
620635}
621636