-
Notifications
You must be signed in to change notification settings - Fork 32
fix(frontend): add collapsible tool call display in chat mode #191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Fix the issue where Agno Agent's XML-formatted tool call information (<tool_call>delegate_task_to_member</tool_call>) was directly displayed in the chat interface, affecting user experience. Changes: - Add CollapsibleToolCalls component for displaying tool calls - Implement detectToolCalls helper to extract and hide tool calls - Add removeMetaInfo helper to filter metadata lines - Update renderAiMessage to handle tool calls collapsibly - Add i18n translations for tool call messages (en/zh-CN) - Import ChevronDown and ChevronRight icons for collapse UI The tool calls are now hidden by default with a summary (e.g., "Called 2 tools"), and users can click to expand and view detailed information. This applies to chat mode while maintaining backward compatibility with code mode.
WalkthroughThe MessagesArea component is enhanced to detect and render tool calls in message content through a new CollapsibleToolCalls component. Helper functions strip metadata and parse tool_call blocks. Corresponding localization strings are added in English and Chinese to support UI text display. Changes
Sequence DiagramsequenceDiagram
participant UI as MessagesArea
participant Detect as detectToolCalls()
participant Clean as removeMetaInfo()
participant Render as CollapsibleToolCalls
participant Output as Message Display
UI->>Clean: Strip metadata from content
Clean-->>UI: Cleaned content
UI->>Detect: Parse for tool_call blocks
Detect-->>UI: Tool calls found + cleaned content
alt Tool Calls Detected
UI->>Render: Render collapsible list (count, names)
Render-->>Output: Collapsed tool calls UI
UI->>Output: Render cleaned markdown content
else No Tool Calls
UI->>Output: Render cleaned content as-is
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
frontend/src/features/tasks/components/MessagesArea.tsx (2)
10-10: CollapsibleToolCalls implementation matches intended UX with minor polish opportunitiesThe new
CollapsibleToolCallscomponent plus Chevron imports correctly delivers a collapsed-by-default summary with expandable details and uses the newmessages.tool_calls_summary/messages.tool_callkeys as expected. The simple<tool_call>\s*(\w+)regex is a reasonable first pass given the current format.If you want to refine this later, consider:
- Adding
aria-expanded={isExpanded}(and optionallyaria-controls) on the<button>for better accessibility.- Using the functional updater form
setIsExpanded(prev => !prev)to avoid any future stale-closure issues.- Localizing the
'Unknown'fallback via a dedicated i18n key instead of hardcoding English.Also applies to: 127-176
200-213: Tool call detection and metadata stripping behave as intended; minor cleanup possible
detectToolCallsandremoveMetaInfocorrectly isolate<tool_call>…</tool_call>blocks and strip the “Current working directory” / “project url” lines before rendering, which should clean up the chat bubbles as desired.Two small follow-ups you might consider:
toolCallsCountis never read by any caller; you can remove it from the return type to avoid dead data:- ): { hasToolCalls: boolean; toolCallsCount: number; toolCalls: string[]; cleanedContent: string } => { + ): { hasToolCalls: boolean; toolCalls: string[]; cleanedContent: string } => { @@ - return { - hasToolCalls: matches !== null && matches.length > 0, - toolCallsCount: matches?.length || 0, - toolCalls: matches || [], - cleanedContent: matches ? content.replace(toolCallRegex, '').trim() : content, - }; + return { + hasToolCalls: !!matches && matches.length > 0, + toolCalls: matches || [], + cleanedContent: matches ? content.replace(toolCallRegex, '').trim() : content, + };
- If upstream ever changes capitalization of the meta lines,
removeMetaInfowill stop matching them; using a case-insensitive flag (e.g.,/^current working directory:.*$/gim) would make this a bit more resilient without changing behavior now.Also applies to: 215-221
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
frontend/src/features/tasks/components/MessagesArea.tsx(5 hunks)frontend/src/i18n/locales/en/chat.json(1 hunks)frontend/src/i18n/locales/zh-CN/chat.json(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
frontend/**
📄 CodeRabbit inference engine (AGENTS.md)
Frontend: Only use
NEXT_PUBLIC_*for client-safe environment variables
Files:
frontend/src/i18n/locales/en/chat.jsonfrontend/src/features/tasks/components/MessagesArea.tsxfrontend/src/i18n/locales/zh-CN/chat.json
frontend/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
frontend/**/*.{ts,tsx}: TypeScript strict mode must be enabled in Frontend
Use functional components with hooks in React
Use Prettier formatter in Frontend with single quotes and no semicolons
Use ESLint with Next.js configuration in Frontend
Useconstoverlet, never usevarin TypeScript
Component names must use PascalCase; file names must use kebab-case in Frontend
Use mobile-first responsive design approach in Frontend components
Frontend design: Low saturation + low contrast for reduced eye strain with generous whitespace
Frontend design: Minimal shadows, subtle component differentiation (<10% background variance)
Frontend design: Use mint blue (#14B8A6) as primary accent sparingly
Use Tailwind CSS variables for colors: --color-bg-base, --color-text-primary, --color-border, etc.
Frontend spacing: Use standard units - p-2 (8px), p-4 (16px), p-6 (24px), gap-3 (12px)
Frontend border-radius: rounded-2xl (16px) for large containers, rounded-lg (12px) for cards, rounded-md (6px) for buttons
Frontend typography: H1 text-xl font-semibold, H2 text-lg font-semibold, H3 text-base font-medium, Body text-sm
Use shadcn/ui Button component with variants: default, secondary, ghost, outline, link
Use shadcn/ui Form component with react-hook-form + zod validation
Files:
frontend/src/features/tasks/components/MessagesArea.tsx
🧠 Learnings (1)
📚 Learning: 2025-11-26T07:34:32.573Z
Learnt from: CR
Repo: wecode-ai/Wegent PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-26T07:34:32.573Z
Learning: Applies to frontend/**/*.{ts,tsx} : Use functional components with hooks in React
Applied to files:
frontend/src/features/tasks/components/MessagesArea.tsx
🔇 Additional comments (2)
frontend/src/i18n/locales/en/chat.json (1)
38-40: New tool call message keys look correct
tool_calls_summaryandtool_callalign with howrenderAiMessage/CollapsibleToolCallsuset('messages.tool_calls_summary')andt('messages.tool_call'), and the{count}/{tools}placeholders match the replacement logic.frontend/src/i18n/locales/zh-CN/chat.json (1)
38-40: Chinese tool call translations wired correctlyThe
tool_calls_summary/tool_callkeys mirror the English locale, keep{count}/{tools}placeholders intact, and will work with the current string.replacelogic.
| const renderAiMessage = (msg: Message, messageIndex: number) => { | ||
| const content = msg.content ?? ''; | ||
| let content = msg.content ?? ''; | ||
|
|
||
| // Remove metadata first | ||
| content = removeMetaInfo(content); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AI message tool‑call rendering is on point; add a small guard for ${$$}$ edge cases
The new renderAiMessage flow correctly:
- Strips noisy meta via
removeMetaInfo, - Detects tool calls in both plain and
${$$}$-separated messages, - Renders a clean prompt/result with collapsible tool call details, which aligns well with the PR goal.
There is one defensive gap plus an optional UX tweak:
- Guard against missing result after the
${$$}$separator
If a future message ever contains the ${$$}$ delimiter without a second segment (e.g. due to a backend change), const [prompt, result] = content.split('${$$}$') will set result to undefined, and detectToolCalls(result) will throw at runtime.
You can harden this with a trivial default:
- const [prompt, result] = content.split('${$$}$');
-
- // Check for tool calls in result
- const { hasToolCalls, toolCalls, cleanedContent } = detectToolCalls(result);
+ const [prompt, resultRaw] = content.split('${$$}$');
+ const result = resultRaw ?? '';
+
+ // Check for tool calls in result
+ const { hasToolCalls, toolCalls, cleanedContent } = detectToolCalls(result);- Optional: keep the copy toolbar for plain messages that contain tool calls
In the !content.includes('${$$}$') branch, when hasToolCalls is true you render cleanedContent and CollapsibleToolCalls, but no BubbleTools. Previously, plain AI messages would always get the copy button via renderPlainMessage. If you want to preserve that UX, you could wrap the cleaned content in a group div and include BubbleTools just like renderPlainMessage does:
- if (hasToolCalls) {
- return (
- <>
- {cleanedContent && <div className="text-sm whitespace-pre-line mb-2">{cleanedContent}</div>}
- <CollapsibleToolCalls toolCalls={toolCalls} t={t} />
- </>
- );
- }
- return renderPlainMessage({ ...msg, content: cleanedContent });
+ if (hasToolCalls) {
+ return (
+ <>
+ {cleanedContent && (
+ <div className="group pb-4">
+ <BubbleTools contentToCopy={cleanedContent} tools={[]} />
+ <div className="text-sm whitespace-pre-line mb-2">{cleanedContent}</div>
+ </div>
+ )}
+ <CollapsibleToolCalls toolCalls={toolCalls} t={t} />
+ </>
+ );
+ }
+ return renderPlainMessage({ ...msg, content: cleanedContent });Based on learnings, this keeps everything in functional React components with hooks while improving resilience and preserving the existing copy behavior for AI messages.
Also applies to: 753-766, 769-778
🤖 Prompt for AI Agents
frontend/src/features/tasks/components/MessagesArea.tsx around lines 708-713
(also applies to 753-766 and 769-778): guard against content.split('${$$}$')
producing undefined for the result and optionally restore the copy toolbar for
plain messages with detected tool calls; specifically, after splitting do const
[prompt, result = ''] = content.split('${$$}$') (or otherwise default result to
an empty string) before calling detectToolCalls(result) to avoid runtime throws,
and in the branch where !content.includes('${$$}$') and hasToolCalls is true,
wrap the cleaned content in the same group that renders BubbleTools (or call
renderPlainMessage behavior) so the copy button is preserved for plain AI
messages with tool calls.
Summary
Fix the issue where Agno Agent's XML-formatted tool call information was directly displayed in the chat interface, affecting user experience.
Changes Made
Frontend Component Updates
CollapsibleToolCallscomponent for displaying tool calls in a collapsible formatdetectToolCallshelper function to extract and hide tool calls from contentremoveMetaInfohelper function to filter out metadata lines (e.g., "Current working directory", "project url")renderAiMessageto handle tool calls with collapse/expand functionalityChevronDownandChevronRighticons for the collapse UIInternationalization (i18n)
English (en/chat.json):
tool_calls_summary: "Called {count} tool(s): {tools}"tool_call: "Tool Call"Chinese (zh-CN/chat.json):
tool_calls_summary: "调用了 {count} 个工具:{tools}"tool_call: "工具调用"User Experience Improvements
Before
Tool calls were displayed as raw XML in the chat bubble:
After
Test Plan
Related Issues
Fixes the issue described in the requirements where XML-formatted tool call information was cluttering the chat interface.
Summary by CodeRabbit
New Features
Localization
✏️ Tip: You can customize this high-level summary in your review settings.