Skip to content

Commit 9e4c96a

Browse files
AaronZ345claude
andcommitted
feat(chat): add tool call visibility toggle
Add a persisted chat action toggle so users can hide noisy tool call cards while keeping normal message flow intact. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 2de79c1 commit 9e4c96a

11 files changed

Lines changed: 156 additions & 3 deletions

File tree

console/src/locales/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3198,6 +3198,8 @@
31983198
"newChatTooltip": "New chat",
31993199
"searchTooltip": "Search all chats",
32003200
"chatHistoryTooltip": "Chat history",
3201+
"hideToolCallsTooltip": "Hide tool calls",
3202+
"showToolCallsTooltip": "Show tool calls",
32013203
"wideModeTooltip": "Wide mode",
32023204
"normalModeTooltip": "Normal mode",
32033205
"allChats": "All Chats",

console/src/locales/id.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,8 @@
629629
"newChatTooltip": "Chat baru",
630630
"searchTooltip": "Cari semua chat",
631631
"chatHistoryTooltip": "Riwayat chat",
632+
"hideToolCallsTooltip": "Sembunyikan panggilan alat",
633+
"showToolCallsTooltip": "Tampilkan panggilan alat",
632634
"wideModeTooltip": "Mode lebar",
633635
"normalModeTooltip": "Mode normal",
634636
"allChats": "Semua Chat",

console/src/locales/ja.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2612,6 +2612,8 @@
26122612
"newChatTooltip": "新しいチャット",
26132613
"searchTooltip": "すべてのチャットを検索",
26142614
"chatHistoryTooltip": "チャット履歴",
2615+
"hideToolCallsTooltip": "ツール呼び出しを非表示",
2616+
"showToolCallsTooltip": "ツール呼び出しを表示",
26152617
"wideModeTooltip": "ワイドモード",
26162618
"normalModeTooltip": "標準モード",
26172619
"allChats": "すべてのチャット",

console/src/locales/pt-BR.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2856,6 +2856,8 @@
28562856
"newChatTooltip": "Novo Chat",
28572857
"searchTooltip": "Pesquisar Todos chats",
28582858
"chatHistoryTooltip": "Chat history",
2859+
"hideToolCallsTooltip": "Hide tool calls",
2860+
"showToolCallsTooltip": "Show tool calls",
28592861
"wideModeTooltip": "Modo amplo",
28602862
"normalModeTooltip": "Modo normal",
28612863
"allChats": "Todos Chats",

console/src/locales/ru.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2627,6 +2627,8 @@
26272627
"newChatTooltip": "Новый чат",
26282628
"searchTooltip": "Поиск во всех чатах",
26292629
"chatHistoryTooltip": "История чатов",
2630+
"hideToolCallsTooltip": "Скрыть вызовы инструментов",
2631+
"showToolCallsTooltip": "Показать вызовы инструментов",
26302632
"wideModeTooltip": "Широкий режим",
26312633
"normalModeTooltip": "Обычный режим",
26322634
"allChats": "Все чаты",

console/src/locales/vi.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,8 @@
645645
"newChatTooltip": "Cuộc trò chuyện mới",
646646
"searchTooltip": "Tìm kiếm tất cả cuộc trò chuyện",
647647
"chatHistoryTooltip": "Lịch sử trò chuyện",
648+
"hideToolCallsTooltip": "Ẩn lệnh gọi công cụ",
649+
"showToolCallsTooltip": "Hiện lệnh gọi công cụ",
648650
"allChats": "Tất cả cuộc trò chuyện",
649651
"createNewChat": "Tạo cuộc trò chuyện mới",
650652
"pinDrawer": "Ghim",

console/src/locales/zh.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3055,6 +3055,8 @@
30553055
"newChatTooltip": "新建聊天",
30563056
"searchTooltip": "搜索所有聊天",
30573057
"chatHistoryTooltip": "聊天历史",
3058+
"hideToolCallsTooltip": "隐藏工具调用",
3059+
"showToolCallsTooltip": "显示工具调用",
30583060
"wideModeTooltip": "宽屏模式",
30593061
"normalModeTooltip": "正常模式",
30603062
"allChats": "全部聊天",

console/src/pages/Chat/ChatPage.coverage.test.tsx

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,15 @@ vi.mock("./ModelSelector", () => ({
192192
}));
193193

194194
vi.mock("./components/ChatActionGroup", () => ({
195-
default: () => <div data-testid="action-group" />,
195+
default: (props: any) => (
196+
<div data-testid="action-group">
197+
<button
198+
data-testid="toggle-tool-calls"
199+
data-show-tool-calls={String(props.showToolCalls)}
200+
onClick={props.onToggleToolCalls}
201+
/>
202+
</div>
203+
),
196204
}));
197205

198206
vi.mock("./components/ChatHeaderTitle", () => ({
@@ -501,6 +509,7 @@ vi.mock("./utils", async () => {
501509
describe("ChatPage coverage", () => {
502510
beforeEach(() => {
503511
chatExtensions.__resetForTests();
512+
localStorage.clear();
504513
capturedOptions = null;
505514
mockListProviders.mockResolvedValue([
506515
{
@@ -1417,6 +1426,35 @@ describe("ChatPage coverage", () => {
14171426
expect(typeof capturedOptions.customToolRenderConfig).toBe("object");
14181427
});
14191428

1429+
it("disables tool call rendering from the chat action toggle", async () => {
1430+
renderWithProviders(<ChatPage />, {
1431+
initialEntries: ["/chat/test-session"],
1432+
});
1433+
await screen.findByTestId("chat-ui");
1434+
1435+
expect(screen.getByTestId("toggle-tool-calls")).toHaveAttribute(
1436+
"data-show-tool-calls",
1437+
"true",
1438+
);
1439+
1440+
await act(async () => {
1441+
screen
1442+
.getByTestId("toggle-tool-calls")
1443+
.dispatchEvent(new MouseEvent("click", { bubbles: true }));
1444+
});
1445+
1446+
expect(screen.getByTestId("toggle-tool-calls")).toHaveAttribute(
1447+
"data-show-tool-calls",
1448+
"false",
1449+
);
1450+
expect(
1451+
capturedOptions.customToolRenderConfig.any_tool_name({
1452+
data: { content: [] },
1453+
}),
1454+
).toBeNull();
1455+
expect(localStorage.getItem("qwenpaw_show_tool_calls")).toBe("false");
1456+
});
1457+
14201458
// ── cards config ───────────────────────────────────────────────────────
14211459
it("cards config has host wrappers", async () => {
14221460
renderWithProviders(<ChatPage />, {

console/src/pages/Chat/components/ChatActionGroup/ChatActionGroup.test.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,23 @@ describe("ChatActionGroup", () => {
7777
button?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
7878
expect(onToggleWorkspace).toHaveBeenCalledOnce();
7979
});
80+
81+
it("renders and toggles the tool call visibility button", () => {
82+
const onToggleToolCalls = vi.fn();
83+
renderWithProviders(
84+
<ChatActionGroup
85+
showToolCalls={false}
86+
onToggleToolCalls={onToggleToolCalls}
87+
/>,
88+
);
89+
90+
const button = document.querySelector(
91+
'button[aria-label="chat.showToolCallsTooltip"]',
92+
) as HTMLButtonElement | null;
93+
expect(button).toBeInTheDocument();
94+
expect(button).toHaveAttribute("aria-pressed", "false");
95+
96+
button?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
97+
expect(onToggleToolCalls).toHaveBeenCalledOnce();
98+
});
8099
});

console/src/pages/Chat/components/ChatActionGroup/index.tsx

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
} from "@ant-design/icons";
1010
import { useTranslation } from "react-i18next";
1111
import { Dropdown, Flex, Tooltip } from "antd";
12-
import { Files } from "lucide-react";
12+
import { Eye, EyeOff, Files } from "lucide-react";
1313
import type { MenuProps } from "antd";
1414
import { useCreateNewSession } from "../../hooks/useCreateNewSession";
1515
import { useIsMobile } from "../../../../hooks/useIsMobile";
@@ -24,6 +24,8 @@ interface ChatActionGroupProps {
2424
workspaceOpen?: boolean;
2525
isWideMode?: boolean;
2626
onToggleWideMode?: () => void;
27+
showToolCalls?: boolean;
28+
onToggleToolCalls?: () => void;
2729
}
2830

2931
const ChatActionGroup: React.FC<ChatActionGroupProps> = ({
@@ -33,6 +35,8 @@ const ChatActionGroup: React.FC<ChatActionGroupProps> = ({
3335
workspaceOpen = false,
3436
isWideMode = false,
3537
onToggleWideMode,
38+
showToolCalls = true,
39+
onToggleToolCalls,
3640
}) => {
3741
const { t } = useTranslation();
3842

@@ -112,6 +116,50 @@ const ChatActionGroup: React.FC<ChatActionGroupProps> = ({
112116
/>
113117
</Tooltip>
114118
)}
119+
{onToggleToolCalls && (
120+
<Tooltip
121+
title={t(
122+
showToolCalls
123+
? "chat.hideToolCallsTooltip"
124+
: "chat.showToolCallsTooltip",
125+
)}
126+
mouseEnterDelay={0.5}
127+
>
128+
<IconButton
129+
bordered={false}
130+
aria-label={t(
131+
showToolCalls
132+
? "chat.hideToolCallsTooltip"
133+
: "chat.showToolCallsTooltip",
134+
)}
135+
aria-pressed={showToolCalls}
136+
icon={
137+
showToolCalls ? (
138+
<Eye
139+
size={16}
140+
strokeWidth={2}
141+
style={{ width: 16, height: 16 }}
142+
/>
143+
) : (
144+
<EyeOff
145+
size={16}
146+
strokeWidth={2}
147+
style={{ width: 16, height: 16 }}
148+
/>
149+
)
150+
}
151+
style={{
152+
width: 32,
153+
height: 32,
154+
padding: 0,
155+
...(showToolCalls
156+
? undefined
157+
: { color: "var(--color-primary, #ff9d4d)" }),
158+
}}
159+
onClick={onToggleToolCalls}
160+
/>
161+
</Tooltip>
162+
)}
115163

116164
{/* History + WideMode: inline when NOT compact */}
117165
{!isCompact && onToggleHistory && (

0 commit comments

Comments
 (0)