From 8ebe91437c994ec0f88c005497b26feaad3e58c8 Mon Sep 17 00:00:00 2001 From: Kujtim Hoxha Date: Thu, 22 Jan 2026 16:01:43 +0100 Subject: [PATCH] refactor(ui): add references tool (#1940) --- internal/ui/chat/references.go | 63 ++++++++++++++++++++++++++++++++++ internal/ui/chat/tools.go | 2 ++ 2 files changed, 65 insertions(+) create mode 100644 internal/ui/chat/references.go diff --git a/internal/ui/chat/references.go b/internal/ui/chat/references.go new file mode 100644 index 0000000000000000000000000000000000000000..2d7efe8df3ed38bf3768d7ae13c433fc05c17418 --- /dev/null +++ b/internal/ui/chat/references.go @@ -0,0 +1,63 @@ +package chat + +import ( + "encoding/json" + + "github.com/charmbracelet/crush/internal/agent/tools" + "github.com/charmbracelet/crush/internal/fsext" + "github.com/charmbracelet/crush/internal/message" + "github.com/charmbracelet/crush/internal/ui/styles" +) + +// ReferencesToolMessageItem is a message item that represents a references tool call. +type ReferencesToolMessageItem struct { + *baseToolMessageItem +} + +var _ ToolMessageItem = (*ReferencesToolMessageItem)(nil) + +// NewReferencesToolMessageItem creates a new [ReferencesToolMessageItem]. +func NewReferencesToolMessageItem( + sty *styles.Styles, + toolCall message.ToolCall, + result *message.ToolResult, + canceled bool, +) ToolMessageItem { + return newBaseToolMessageItem(sty, toolCall, result, &ReferencesToolRenderContext{}, canceled) +} + +// ReferencesToolRenderContext renders references tool messages. +type ReferencesToolRenderContext struct{} + +// RenderTool implements the [ToolRenderer] interface. +func (r *ReferencesToolRenderContext) RenderTool(sty *styles.Styles, width int, opts *ToolRenderOpts) string { + cappedWidth := cappedMessageWidth(width) + if opts.IsPending() { + return pendingTool(sty, "Find References", opts.Anim) + } + + var params tools.ReferencesParams + _ = json.Unmarshal([]byte(opts.ToolCall.Input), ¶ms) + + toolParams := []string{params.Symbol} + if params.Path != "" { + toolParams = append(toolParams, "path", fsext.PrettyPath(params.Path)) + } + + header := toolHeader(sty, opts.Status, "Find References", cappedWidth, opts.Compact, toolParams...) + if opts.Compact { + return header + } + + if earlyState, ok := toolEarlyStateContent(sty, opts, cappedWidth); ok { + return joinToolParts(header, earlyState) + } + + if opts.HasEmptyResult() { + return header + } + + bodyWidth := cappedWidth - toolBodyLeftPaddingTotal + body := sty.Tool.Body.Render(toolOutputPlainContent(sty, opts.Result.Content, bodyWidth, opts.ExpandedContent)) + return joinToolParts(header, body) +} diff --git a/internal/ui/chat/tools.go b/internal/ui/chat/tools.go index e703cb1c096c0fa889438a446a8f042b892d9e31..1c9f71eb41168d913f4193af896ecb1b389136e7 100644 --- a/internal/ui/chat/tools.go +++ b/internal/ui/chat/tools.go @@ -242,6 +242,8 @@ func NewToolMessageItem( item = NewWebSearchToolMessageItem(sty, toolCall, result, canceled) case tools.TodosToolName: item = NewTodosToolMessageItem(sty, toolCall, result, canceled) + case tools.ReferencesToolName: + item = NewReferencesToolMessageItem(sty, toolCall, result, canceled) default: if strings.HasPrefix(toolCall.Name, "mcp_") { item = NewMCPToolMessageItem(sty, toolCall, result, canceled)