@@ -40,6 +40,12 @@ type ToolMessageItem interface {
40 SetResult(res *message.ToolResult)
40 SetResult(res *message.ToolResult)
43+// Simplifiable is an interface for tool items that can render in a simplified mode.
44+// When simple mode is enabled, tools render as a compact single-line header.
45+type Simplifiable interface {
46+ SetSimple(simple bool)
43// DefaultToolRenderContext implements the default [ToolRenderer] interface.
49// DefaultToolRenderContext implements the default [ToolRenderer] interface.
44type DefaultToolRenderContext struct{}
50type DefaultToolRenderContext struct{}
@@ -55,7 +61,7 @@ type ToolRenderOpts struct {
55 Canceled bool
61 Canceled bool
56 Anim *anim.Anim
62 Anim *anim.Anim
57 Expanded bool
63 Expanded bool
58− Nested bool
64+ Simple bool
59 IsSpinning bool
65 IsSpinning bool
60 PermissionRequested bool
66 PermissionRequested bool
61 PermissionGranted bool
67 PermissionGranted bool
@@ -106,6 +112,8 @@ type baseToolMessageItem struct {
106 // we use this so we can efficiently cache
112 // we use this so we can efficiently cache
107 // tools that have a capped width (e.x bash.. and others)
113 // tools that have a capped width (e.x bash.. and others)
108 hasCappedWidth bool
114 hasCappedWidth bool
115+ // isSimple indicates this tool should render in simplified/compact mode.
110 sty *styles.Styles
118 sty *styles.Styles
111 anim *anim.Anim
119 anim *anim.Anim
@@ -177,6 +185,14 @@ func NewToolMessageItem(
177 return NewGrepToolMessageItem(sty, toolCall, result, canceled)
185 return NewGrepToolMessageItem(sty, toolCall, result, canceled)
178 case tools.LSToolName:
186 case tools.LSToolName:
179 return NewLSToolMessageItem(sty, toolCall, result, canceled)
187 return NewLSToolMessageItem(sty, toolCall, result, canceled)
188+ case tools.DownloadToolName:
189+ return NewDownloadToolMessageItem(sty, toolCall, result, canceled)
190+ case tools.FetchToolName:
191+ return NewFetchToolMessageItem(sty, toolCall, result, canceled)
192+ case tools.SourcegraphToolName:
193+ return NewSourcegraphToolMessageItem(sty, toolCall, result, canceled)
194+ case tools.DiagnosticsToolName:
195+ return NewDiagnosticsToolMessageItem(sty, toolCall, result, canceled)
181 // TODO: Implement other tool items
197 // TODO: Implement other tool items
182 return newBaseToolMessageItem(
198 return newBaseToolMessageItem(
@@ -189,6 +205,12 @@ func NewToolMessageItem(
208+// SetSimple implements the Simplifiable interface.
209+func (t *baseToolMessageItem) SetSimple(simple bool) {
192// ID returns the unique identifier for this tool message item.
214// ID returns the unique identifier for this tool message item.
193func (t *baseToolMessageItem) ID() string {
215func (t *baseToolMessageItem) ID() string {
194 return t.toolCall.ID
216 return t.toolCall.ID
@@ -230,6 +252,7 @@ func (t *baseToolMessageItem) Render(width int) string {
230 Canceled: t.canceled,
252 Canceled: t.canceled,
231 Anim: t.anim,
253 Anim: t.anim,
232 Expanded: t.expanded,
254 Expanded: t.expanded,
233 PermissionRequested: t.permissionRequested,
256 PermissionRequested: t.permissionRequested,
234 PermissionGranted: t.permissionGranted,
257 PermissionGranted: t.permissionGranted,
235 IsSpinning: t.isSpinning(),
258 IsSpinning: t.isSpinning(),
@@ -487,10 +510,10 @@ func toolOutputCodeContent(sty *styles.Styles, path, content string, offset, wid
488 // Add truncation message if needed.
511 // Add truncation message if needed.
489 if len(lines) > maxLines && !expanded {
512 if len(lines) > maxLines && !expanded {
490− truncMsg := sty.Tool.ContentCodeTruncation.
513+ out = append(out, sty.Tool.ContentCodeTruncation.
491 Width(bodyWidth).
514 Width(bodyWidth).
492− Render(fmt.Sprintf(assistantMessageTruncateFormat, len(lines)-maxLines))
515+ Render(fmt.Sprintf(assistantMessageTruncateFormat, len(lines)-maxLines)),
493− out = append([]string{truncMsg}, out...)
516+ )
496 return sty.Tool.Body.Render(strings.Join(out, "\n"))
519 return sty.Tool.Body.Render(strings.Join(out, "\n"))
@@ -574,6 +597,23 @@ func toolOutputDiffContent(sty *styles.Styles, file, oldContent, newContent stri
574 return sty.Tool.Body.Render(formatted)
597 return sty.Tool.Body.Render(formatted)
600+// formatTimeout converts timeout seconds to a duration string (e.g., "30s").
601+// Returns empty string if timeout is 0.
602+func formatTimeout(timeout int) string {
606+ return fmt.Sprintf("%ds", timeout)
609+// formatNonZero returns string representation of non-zero integers, empty string for zero.
610+func formatNonZero(value int) string {
614+ return fmt.Sprintf("%d", value)
577// toolOutputMultiEditDiffContent renders a diff with optional failed edits note.
617// toolOutputMultiEditDiffContent renders a diff with optional failed edits note.
578func toolOutputMultiEditDiffContent(sty *styles.Styles, file string, meta tools.MultiEditResponseMetadata, totalEdits, width int, expanded bool) string {
618func toolOutputMultiEditDiffContent(sty *styles.Styles, file string, meta tools.MultiEditResponseMetadata, totalEdits, width int, expanded bool) string {
579 bodyWidth := width - toolBodyLeftPaddingTotal
619 bodyWidth := width - toolBodyLeftPaddingTotal