@@ -56,8 +56,8 @@ 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.Nested, toolParams...)
60− if opts.Nested {
59+ header := toolHeader(sty, opts.Status(), "View", cappedWidth, opts.Simple, toolParams...)
60+ if opts.Simple {
6161 return header
6262 }
6363
@@ -128,8 +128,8 @@ func (w *WriteToolRenderContext) RenderTool(sty *styles.Styles, width int, opts
128128 }
129129
130130 file := fsext.PrettyPath(params.FilePath)
131− header := toolHeader(sty, opts.Status(), "Write", cappedWidth, opts.Nested, file)
132− if opts.Nested {
131+ header := toolHeader(sty, opts.Status(), "Write", cappedWidth, opts.Simple, file)
132+ if opts.Simple {
133133 return header
134134 }
135135
@@ -183,8 +183,8 @@ func (e *EditToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *
183183 }
184184
185185 file := fsext.PrettyPath(params.FilePath)
186− header := toolHeader(sty, opts.Status(), "Edit", width, opts.Nested, file)
187− if opts.Nested {
186+ header := toolHeader(sty, opts.Status(), "Edit", width, opts.Simple, file)
187+ if opts.Simple {
188188 return header
189189 }
190190
@@ -251,8 +251,8 @@ func (m *MultiEditToolRenderContext) RenderTool(sty *styles.Styles, width int, o
251251 toolParams = append(toolParams, "edits", fmt.Sprintf("%d", len(params.Edits)))
252252 }
253253
254− header := toolHeader(sty, opts.Status(), "Multi-Edit", width, opts.Nested, toolParams...)
255− if opts.Nested {
254+ header := toolHeader(sty, opts.Status(), "Multi-Edit", width, opts.Simple, toolParams...)
255+ if opts.Simple {
256256 return header
257257 }
258258
@@ -276,3 +276,65 @@ func (m *MultiEditToolRenderContext) RenderTool(sty *styles.Styles, width int, o
276276 body := toolOutputMultiEditDiffContent(sty, file, meta, len(params.Edits), width, opts.Expanded)
277277 return joinToolParts(header, body)
278278}
279+
280+// -----------------------------------------------------------------------------
281+// Download Tool
282+// -----------------------------------------------------------------------------
283+
284+// DownloadToolMessageItem is a message item that represents a download tool call.
285+type DownloadToolMessageItem struct {
286+ *baseToolMessageItem
287+}
288+
289+var _ ToolMessageItem = (*DownloadToolMessageItem)(nil)
290+
291+// NewDownloadToolMessageItem creates a new [DownloadToolMessageItem].
292+func NewDownloadToolMessageItem(
293+ sty *styles.Styles,
294+ toolCall message.ToolCall,
295+ result *message.ToolResult,
296+ canceled bool,
297+) ToolMessageItem {
298+ return newBaseToolMessageItem(sty, toolCall, result, &DownloadToolRenderContext{}, canceled)
299+}
300+
301+// DownloadToolRenderContext renders download tool messages.
302+type DownloadToolRenderContext struct{}
303+
304+// RenderTool implements the [ToolRenderer] interface.
305+func (d *DownloadToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string {
306+ cappedWidth := cappedMessageWidth(width)
307+ if !opts.ToolCall.Finished && !opts.Canceled {
308+ return pendingTool(sty, "Download", opts.Anim)
309+ }
310+
311+ var params tools.DownloadParams
312+ if err := json.Unmarshal([]byte(opts.ToolCall.Input), ¶ms); err != nil {
313+ return toolErrorContent(sty, &message.ToolResult{Content: "Invalid parameters"}, cappedWidth)
314+ }
315+
316+ toolParams := []string{params.URL}
317+ if params.FilePath != "" {
318+ toolParams = append(toolParams, "file_path", fsext.PrettyPath(params.FilePath))
319+ }
320+ if params.Timeout != 0 {
321+ toolParams = append(toolParams, "timeout", formatTimeout(params.Timeout))
322+ }
323+
324+ header := toolHeader(sty, opts.Status(), "Download", cappedWidth, opts.Simple, toolParams...)
325+ if opts.Simple {
326+ return header
327+ }
328+
329+ if earlyState, ok := toolEarlyStateContent(sty, opts, cappedWidth); ok {
330+ return joinToolParts(header, earlyState)
331+ }
332+
333+ if opts.Result == nil || opts.Result.Content == "" {
334+ return header
335+ }
336+
337+ bodyWidth := cappedWidth - toolBodyLeftPaddingTotal
338+ body := sty.Tool.Body.Render(toolOutputPlainContent(sty, opts.Result.Content, bodyWidth, opts.Expanded))
339+ return joinToolParts(header, body)
340+}