Skip to content

fix: use appropriate icons for dynamic tool calls instead of hammer fallback#32

Closed
zortos293 wants to merge 1 commit intomainfrom
capy/fix-dynamic-tool-icons
Closed

fix: use appropriate icons for dynamic tool calls instead of hammer fallback#32
zortos293 wants to merge 1 commit intomainfrom
capy/fix-dynamic-tool-icons

Conversation

@zortos293
Copy link
Owner

@zortos293 zortos293 commented Mar 15, 2026

This PR fixes a bug where all tool activity icons were displaying as hammers because dynamic_tool_call and collab_agent_tool_call itemTypes had a hardcoded hammer fallback.

  • Centralized icon resolution logic into resolveWorkEntryIcon in apps/web/src/components/chat/MessagesTimeline.logic.ts
  • Changed dynamic_tool_call fallback from HammerIcon to WrenchIcon (generic tool icon)
  • Changed collab_agent_tool_call fallback from HammerIcon to BotIcon (agent/assistant connotation)
  • Kept HammerIcon specifically for task.progress activities where it makes semantic sense
  • Updated both ChatView.tsx and MessagesTimeline.tsx to use the shared resolver
  • Added focused test coverage for icon resolution in MessagesTimeline.logic.test.ts

Open in Capy TC-13 · 5.4

Summary by CodeRabbit

Release Notes

  • Refactor

    • Consolidated icon selection logic in the chat messaging component, centralizing icon resolution into a reusable helper function to reduce code complexity.
  • Tests

    • Added comprehensive test coverage for icon resolution functionality, validating icon selection across various work entry types and interaction scenarios.

@zortos293 zortos293 added the capy Generated by capy.ai label Mar 15, 2026 — with Capy AI
@coderabbitai
Copy link

coderabbitai bot commented Mar 15, 2026

📝 Walkthrough

Walkthrough

This pull request centralizes icon resolution logic for work entries by introducing a new public function resolveWorkEntryIcon() and interface WorkEntryIconInput in MessagesTimeline.logic.ts. The branching logic previously distributed across ChatView.tsx and MessagesTimeline.tsx is consolidated into this single helper function. Both components are updated to call the new function instead of maintaining their own icon selection logic, and unused icon imports are removed. Test coverage is added to validate icon mapping across various work entry types.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: fixing inappropriate hammer icons for dynamic tool calls by introducing proper icon selection.
Description check ✅ Passed The description provides clear context on the bug being fixed, explains the approach, and documents all changes made across multiple files with concrete before/after icon mappings.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

📝 Coding Plan
  • Generate coding plan for human review comments

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/components/chat/MessagesTimeline.logic.ts`:
- Around line 119-126: The generic haystack.includes("task") check is taking
precedence and can incorrectly return HammerIcon for entries that are actually
dynamic_tool_call or collab_agent_tool_call; update MessagesTimeline.logic by
moving the workEntry.itemType checks for "dynamic_tool_call" and
"collab_agent_tool_call" (WrenchIcon and BotIcon) so they run before the
haystack.includes("task") conditional, ensuring those specific itemType
fallbacks are matched first; keep the existing activityKind checks in place and
preserve return values for ListTodoIcon, HammerIcon, BotIcon, and CheckIcon.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e705b146-c860-4df0-9a11-61ea2c4fc582

📥 Commits

Reviewing files that changed from the base of the PR and between 32de82c and 6e029af.

📒 Files selected for processing (4)
  • apps/web/src/components/ChatView.tsx
  • apps/web/src/components/chat/MessagesTimeline.logic.test.ts
  • apps/web/src/components/chat/MessagesTimeline.logic.ts
  • apps/web/src/components/chat/MessagesTimeline.tsx

Comment on lines +119 to +126
if (haystack.includes("task")) return HammerIcon;

if (workEntry.activityKind === "turn.plan.updated") return ListTodoIcon;
if (workEntry.activityKind === "task.progress") return HammerIcon;
if (workEntry.activityKind === "approval.requested") return BotIcon;
if (workEntry.activityKind === "approval.resolved") return CheckIcon;
if (workEntry.itemType === "dynamic_tool_call") return WrenchIcon;
if (workEntry.itemType === "collab_agent_tool_call") return BotIcon;
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

Move dynamic/collab fallbacks ahead of generic haystack matches

On Line 119, the generic haystack.includes("task") check runs before Lines 125-126. That can still return HammerIcon for dynamic_tool_call / collab_agent_tool_call entries whose text contains “task”, undermining this PR’s icon-fallback fix.

Suggested reorder
   if (workEntry.itemType === "web_search") return GlobeIcon;
   if (workEntry.itemType === "image_view") return EyeIcon;
   if (workEntry.itemType === "mcp_tool_call") return WrenchIcon;
+  if (workEntry.itemType === "dynamic_tool_call") return WrenchIcon;
+  if (workEntry.itemType === "collab_agent_tool_call") return BotIcon;

   const haystack = [
     workEntry.label,
     workEntry.toolTitle,
@@
   if (haystack.includes("store_memory")) return FolderIcon;
   if (haystack.includes("edit") || haystack.includes("patch")) return WrenchIcon;
   if (haystack.includes("file")) return FileIcon;
   if (haystack.includes("task")) return HammerIcon;

   if (workEntry.activityKind === "turn.plan.updated") return ListTodoIcon;
   if (workEntry.activityKind === "task.progress") return HammerIcon;
   if (workEntry.activityKind === "approval.requested") return BotIcon;
   if (workEntry.activityKind === "approval.resolved") return CheckIcon;
-  if (workEntry.itemType === "dynamic_tool_call") return WrenchIcon;
-  if (workEntry.itemType === "collab_agent_tool_call") return BotIcon;

As per coding guidelines, "apps/web/**: Prioritize UI correctness, responsive layout behavior, and avoiding unnecessary rerenders or fragile client state transitions."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (haystack.includes("task")) return HammerIcon;
if (workEntry.activityKind === "turn.plan.updated") return ListTodoIcon;
if (workEntry.activityKind === "task.progress") return HammerIcon;
if (workEntry.activityKind === "approval.requested") return BotIcon;
if (workEntry.activityKind === "approval.resolved") return CheckIcon;
if (workEntry.itemType === "dynamic_tool_call") return WrenchIcon;
if (workEntry.itemType === "collab_agent_tool_call") return BotIcon;
if (workEntry.itemType === "web_search") return GlobeIcon;
if (workEntry.itemType === "image_view") return EyeIcon;
if (workEntry.itemType === "mcp_tool_call") return WrenchIcon;
if (workEntry.itemType === "dynamic_tool_call") return WrenchIcon;
if (workEntry.itemType === "collab_agent_tool_call") return BotIcon;
const haystack = [
workEntry.label,
workEntry.toolTitle,
workEntry.activityKind,
];
if (haystack.includes("store_memory")) return FolderIcon;
if (haystack.includes("edit") || haystack.includes("patch")) return WrenchIcon;
if (haystack.includes("file")) return FileIcon;
if (haystack.includes("task")) return HammerIcon;
if (workEntry.activityKind === "turn.plan.updated") return ListTodoIcon;
if (workEntry.activityKind === "task.progress") return HammerIcon;
if (workEntry.activityKind === "approval.requested") return BotIcon;
if (workEntry.activityKind === "approval.resolved") return CheckIcon;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/components/chat/MessagesTimeline.logic.ts` around lines 119 -
126, The generic haystack.includes("task") check is taking precedence and can
incorrectly return HammerIcon for entries that are actually dynamic_tool_call or
collab_agent_tool_call; update MessagesTimeline.logic by moving the
workEntry.itemType checks for "dynamic_tool_call" and "collab_agent_tool_call"
(WrenchIcon and BotIcon) so they run before the haystack.includes("task")
conditional, ensuring those specific itemType fallbacks are matched first; keep
the existing activityKind checks in place and preserve return values for
ListTodoIcon, HammerIcon, BotIcon, and CheckIcon.

@zortos293 zortos293 closed this Mar 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

capy Generated by capy.ai size:L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant