@@ -143,8 +143,9 @@ func (br baseRenderer) makeHeader(v *toolCallCmp, tool string, width int, params
143143func (br baseRenderer) renderError(v *toolCallCmp, message string) string {
144144 t := styles.CurrentTheme()
145145 header := br.makeHeader(v, prettifyToolName(v.call.Name), v.textWidth(), "")
146− message = t.S().Error.Render(v.fit(message, v.textWidth()-2)) // -2 for padding
147− return joinHeaderBody(header, message)
146+ errorTag := t.S().Base.Padding(0, 1).Background(t.Red).Foreground(t.White).Render("ERROR")
147+ message = t.S().Base.Foreground(t.FgHalfMuted).Render(v.fit(message, v.textWidth()-3-lipgloss.Width(errorTag))) // -2 for padding and space
148+ return joinHeaderBody(header, errorTag+" "+message)
148149}
149150
150151// Register tool renderers
@@ -198,6 +199,9 @@ func (br bashRenderer) Render(v *toolCallCmp) string {
198199 args := newParamBuilder().addMain(cmd).build()
199200
200201 return br.renderWithParams(v, "Bash", args, func() string {
202+ if v.result.Content == tools.BashNoOutput {
203+ return ""
204+ }
201205 return renderPlainContent(v, v.result.Content)
202206 })
203207}
@@ -254,13 +258,12 @@ type editRenderer struct {
254258// Render displays the edited file with a formatted diff of changes
255259func (er editRenderer) Render(v *toolCallCmp) string {
256260 var params tools.EditParams
257− if err := er.unmarshalParams(v.call.Input, ¶ms); err != nil {
258− return er.renderError(v, "Invalid edit parameters")
261+ var args []string
262+ if err := er.unmarshalParams(v.call.Input, ¶ms); err == nil {
263+ file := fsext.PrettyPath(params.FilePath)
264+ args = newParamBuilder().addMain(file).build()
259265 }
260266
261− file := fsext.PrettyPath(params.FilePath)
262− args := newParamBuilder().addMain(file).build()
263−
264267 return er.renderWithParams(v, "Edit", args, func() string {
265268 var meta tools.EditResponseMetadata
266269 if err := er.unmarshalParams(v.result.Metadata, &meta); err != nil {
@@ -290,13 +293,13 @@ type writeRenderer struct {
290293// Render displays the file being written with syntax highlighting
291294func (wr writeRenderer) Render(v *toolCallCmp) string {
292295 var params tools.WriteParams
293− if err := wr.unmarshalParams(v.call.Input, ¶ms); err != nil {
294− return wr.renderError(v, "Invalid write parameters")
296+ var args []string
297+ var file string
298+ if err := wr.unmarshalParams(v.call.Input, ¶ms); err == nil {
299+ file = fsext.PrettyPath(params.FilePath)
300+ args = newParamBuilder().addMain(file).build()
295301 }
296302
297− file := fsext.PrettyPath(params.FilePath)
298− args := newParamBuilder().addMain(file).build()
299−
300303 return wr.renderWithParams(v, "Write", args, func() string {
301304 return renderCodeContent(v, file, params.Content, 0)
302305 })
@@ -314,16 +317,15 @@ type fetchRenderer struct {
314317// Render displays the fetched URL with format and timeout parameters
315318func (fr fetchRenderer) Render(v *toolCallCmp) string {
316319 var params tools.FetchParams
317− if err := fr.unmarshalParams(v.call.Input, ¶ms); err != nil {
318− return fr.renderError(v, "Invalid fetch parameters")
320+ var args []string
321+ if err := fr.unmarshalParams(v.call.Input, ¶ms); err == nil {
322+ args = newParamBuilder().
323+ addMain(params.URL).
324+ addKeyValue("format", params.Format).
325+ addKeyValue("timeout", formatTimeout(params.Timeout)).
326+ build()
319327 }
320328
321− args := newParamBuilder().
322− addMain(params.URL).
323− addKeyValue("format", params.Format).
324− addKeyValue("timeout", formatTimeout(params.Timeout)).
325− build()
326−
327329 return fr.renderWithParams(v, "Fetch", args, func() string {
328330 file := fr.getFileExtension(params.Format)
329331 return renderCodeContent(v, file, v.result.Content, 0)
@@ -362,15 +364,14 @@ type globRenderer struct {
362364// Render displays the glob pattern with optional path parameter
363365func (gr globRenderer) Render(v *toolCallCmp) string {
364366 var params tools.GlobParams
365− if err := gr.unmarshalParams(v.call.Input, ¶ms); err != nil {
366− return gr.renderError(v, "Invalid glob parameters")
367+ var args []string
368+ if err := gr.unmarshalParams(v.call.Input, ¶ms); err == nil {
369+ args = newParamBuilder().
370+ addMain(params.Pattern).
371+ addKeyValue("path", params.Path).
372+ build()
367373 }
368374
369− args := newParamBuilder().
370− addMain(params.Pattern).
371− addKeyValue("path", params.Path).
372− build()
373−
374375 return gr.renderWithParams(v, "Glob", args, func() string {
375376 return renderPlainContent(v, v.result.Content)
376377 })
@@ -388,17 +389,16 @@ type grepRenderer struct {
388389// Render displays the search pattern with path, include, and literal text options
389390func (gr grepRenderer) Render(v *toolCallCmp) string {
390391 var params tools.GrepParams
391− if err := gr.unmarshalParams(v.call.Input, ¶ms); err != nil {
392− return gr.renderError(v, "Invalid grep parameters")
392+ var args []string
393+ if err := gr.unmarshalParams(v.call.Input, ¶ms); err == nil {
394+ args = newParamBuilder().
395+ addMain(params.Pattern).
396+ addKeyValue("path", params.Path).
397+ addKeyValue("include", params.Include).
398+ addFlag("literal", params.LiteralText).
399+ build()
393400 }
394401
395− args := newParamBuilder().
396− addMain(params.Pattern).
397− addKeyValue("path", params.Path).
398− addKeyValue("include", params.Include).
399− addFlag("literal", params.LiteralText).
400− build()
401−
402402 return gr.renderWithParams(v, "Grep", args, func() string {
403403 return renderPlainContent(v, v.result.Content)
404404 })
@@ -416,17 +416,16 @@ type lsRenderer struct {
416416// Render displays the directory path, defaulting to current directory
417417func (lr lsRenderer) Render(v *toolCallCmp) string {
418418 var params tools.LSParams
419− if err := lr.unmarshalParams(v.call.Input, ¶ms); err != nil {
420− return lr.renderError(v, "Invalid ls parameters")
421− }
419+ var args []string
420+ if err := lr.unmarshalParams(v.call.Input, ¶ms); err == nil {
421+ path := params.Path
422+ if path == "" {
423+ path = "."
424+ }
425+ path = fsext.PrettyPath(path)
422426
423− path := params.Path
424− if path == "" {
425− path = "."
427+ args = newParamBuilder().addMain(path).build()
426428 }
427− path = fsext.PrettyPath(path)
428−
429− args := newParamBuilder().addMain(path).build()
430429
431430 return lr.renderWithParams(v, "List", args, func() string {
432431 return renderPlainContent(v, v.result.Content)
@@ -445,16 +444,15 @@ type sourcegraphRenderer struct {
445444// Render displays the search query with optional count and context window parameters
446445func (sr sourcegraphRenderer) Render(v *toolCallCmp) string {
447446 var params tools.SourcegraphParams
448− if err := sr.unmarshalParams(v.call.Input, ¶ms); err != nil {
449− return sr.renderError(v, "Invalid sourcegraph parameters")
447+ var args []string
448+ if err := sr.unmarshalParams(v.call.Input, ¶ms); err == nil {
449+ args = newParamBuilder().
450+ addMain(params.Query).
451+ addKeyValue("count", formatNonZero(params.Count)).
452+ addKeyValue("context", formatNonZero(params.ContextWindow)).
453+ build()
450454 }
451455
452− args := newParamBuilder().
453− addMain(params.Query).
454− addKeyValue("count", formatNonZero(params.Count)).
455− addKeyValue("context", formatNonZero(params.ContextWindow)).
456− build()
457−
458456 return sr.renderWithParams(v, "Sourcegraph", args, func() string {
459457 return renderPlainContent(v, v.result.Content)
460458 })
@@ -498,13 +496,15 @@ func RoundedEnumerator(children tree.Children, index int) string {
498496func (tr agentRenderer) Render(v *toolCallCmp) string {
499497 t := styles.CurrentTheme()
500498 var params agent.AgentParams
501− if err := tr.unmarshalParams(v.call.Input, ¶ms); err != nil {
502− return tr.renderError(v, "Invalid task parameters")
503− }
499+ tr.unmarshalParams(v.call.Input, ¶ms)
500+
504501 prompt := params.Prompt
505502 prompt = strings.ReplaceAll(prompt, "\n", " ")
506503
507504 header := tr.makeHeader(v, "Agent", v.textWidth())
505+ if res, done := earlyState(header, v); done {
506+ return res
507+ }
508508 taskTag := t.S().Base.Padding(0, 1).MarginLeft(1).Background(t.BlueLight).Foreground(t.White).Render("Task")
509509 remainingWidth := v.textWidth() - lipgloss.Width(header) - lipgloss.Width(taskTag) - 2 // -2 for padding
510510 prompt = t.S().Muted.Width(remainingWidth).Render(prompt)
@@ -608,15 +608,15 @@ func earlyState(header string, v *toolCallCmp) (string, bool) {
608608 case v.result.IsError:
609609 message = v.renderToolError()
610610 case v.cancelled:
611− message = "Cancelled"
611+ message = t.S().Base.Padding(0, 1).Background(t.Border).Render("Cancelled")
612612 case v.result.ToolCallID == "":
613− message = "Waiting for tool to start..."
613+ message = t.S().Base.Padding(0, 1).Background(t.Accent).Foreground(t.FgSubtle).Render("Waiting for tool to start...")
614614 default:
615615 return "", false
616616 }
617617
618618 message = t.S().Base.PaddingLeft(2).Render(message)
619− return lipgloss.JoinVertical(lipgloss.Left, header, message), true
619+ return lipgloss.JoinVertical(lipgloss.Left, header, "", message), true
620620}
621621
622622func joinHeaderBody(header, body string) string {
@@ -699,8 +699,9 @@ func renderCodeContent(v *toolCallCmp, path, content string, offset int) string
699699func (v *toolCallCmp) renderToolError() string {
700700 t := styles.CurrentTheme()
701701 err := strings.ReplaceAll(v.result.Content, "\n", " ")
702− err = fmt.Sprintf("Error: %s", err)
703− return t.S().Base.Foreground(t.Error).Render(v.fit(err, v.textWidth()-2))
702+ errTag := t.S().Base.Padding(0, 1).Background(t.Red).Foreground(t.White).Render("ERROR")
703+ err = fmt.Sprintf("%s %s", errTag, t.S().Base.Foreground(t.FgHalfMuted).Render(v.fit(err, v.textWidth()-2-lipgloss.Width(errTag))))
704+ return err
704705}
705706
706707func truncateHeight(s string, h int) string {