Skip to content

Conversation

@qdaxb
Copy link
Contributor

@qdaxb qdaxb commented Nov 27, 2025

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

  • MessagesArea.tsx:
    • Added CollapsibleToolCalls component for displaying tool calls in a collapsible format
    • Implemented detectToolCalls helper function to extract and hide tool calls from content
    • Added removeMetaInfo helper function to filter out metadata lines (e.g., "Current working directory", "project url")
    • Updated renderAiMessage to handle tool calls with collapse/expand functionality
    • Imported ChevronDown and ChevronRight icons for the collapse UI

Internationalization (i18n)

  • English (en/chat.json):

    • Added tool_calls_summary: "Called {count} tool(s): {tools}"
    • Added tool_call: "Tool Call"
  • Chinese (zh-CN/chat.json):

    • Added tool_calls_summary: "调用了 {count} 个工具:{tools}"
    • Added tool_call: "工具调用"

User Experience Improvements

Before

Tool calls were displayed as raw XML in the chat bubble:

<tool_call>delegate_task_to_member 
<arg_key>member_id</arg_key> 
<arg_value>新闻搜索bot示例</arg_value>
...
</tool_call>

After

  • Default (collapsed): Shows a summary like "调用了 2 个工具:delegate_task_to_member, search_news"
  • Expanded: Users can click to view full tool call details with formatted display
  • Metadata lines like "Current working directory" and "project url" are automatically filtered out

Test Plan

  • Test with Agno Agent in chat mode - tool calls should be collapsed by default
  • Test expand/collapse functionality - clicking should toggle tool call details
  • Test metadata filtering - metadata lines should not appear in chat bubbles
  • Test internationalization - both English and Chinese labels should display correctly
  • Verify backward compatibility - existing messages without tool calls should render normally
  • Test with Claude Code Agent - should maintain consistent behavior

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

    • Tool calls in AI messages are now collapsible, displaying a summary of which tools were invoked.
    • Users can expand/collapse tool call details with a toggle button.
  • Localization

    • Added Chinese language support for tool call display messages.

✏️ Tip: You can customize this high-level summary in your review settings.

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.
@coderabbitai
Copy link

coderabbitai bot commented Nov 27, 2025

Walkthrough

The 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

Cohort / File(s) Change Summary
Tool Call Rendering Enhancement
frontend/src/features/tasks/components/MessagesArea.tsx
Added CollapsibleToolCalls component for rendering collapsible tool call blocks; introduced detectToolCalls() and removeMetaInfo() helper functions to parse and clean content; expanded MessagesArea interface with selectedBranch prop; enhanced AI, plain, and Markdown message rendering paths to detect and display tool calls; imported ChevronDown and ChevronRight icons from lucide-react
Localization for Tool Calls
frontend/src/i18n/locales/en/chat.json
frontend/src/i18n/locales/zh-CN/chat.json
Added tool_calls_summary and tool_call keys to messages object in both English and Chinese locale files with appropriate translations

Sequence Diagram

sequenceDiagram
    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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • MessagesArea.tsx: Requires careful review of the detectToolCalls() and removeMetaInfo() helper logic for correctness and edge cases; understand the multiple conditional rendering paths and their interactions; verify CollapsibleToolCalls component state management.
  • Localization files: Trivial additions; verify translation accuracy and formatting consistency.

Suggested reviewers

  • feifei325

Poem

🐰 A rabbit hops through messages with glee,
Tool calls now fold like origami, so neat!
Metadata stripped, and icons so bright,
Collapsible wisdom shines clear in the light! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a collapsible tool call display component in the chat interface to fix how tool calls are rendered.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch wegent/fix-tool-call-display

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a 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 opportunities

The new CollapsibleToolCalls component plus Chevron imports correctly delivers a collapsed-by-default summary with expandable details and uses the new messages.tool_calls_summary / messages.tool_call keys 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 optionally aria-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

detectToolCalls and removeMetaInfo correctly 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:

  • toolCallsCount is 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, removeMetaInfo will 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

📥 Commits

Reviewing files that changed from the base of the PR and between e2fcd49 and 94abe50.

📒 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.json
  • frontend/src/features/tasks/components/MessagesArea.tsx
  • frontend/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
Use const over let, never use var in 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_summary and tool_call align with how renderAiMessage/CollapsibleToolCalls use t('messages.tool_calls_summary') and t('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 correctly

The tool_calls_summary / tool_call keys mirror the English locale, keep {count} / {tools} placeholders intact, and will work with the current string .replace logic.

Comment on lines 708 to 713
const renderAiMessage = (msg: Message, messageIndex: number) => {
const content = msg.content ?? '';
let content = msg.content ?? '';

// Remove metadata first
content = removeMetaInfo(content);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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:

  1. 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);
  1. 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants