11import { useMemo } from 'react'
22import { ShimmerText } from '@/components/ui'
3- import { WorkspaceFile } from '@/lib/copilot/generated/tool-catalog-v1'
3+ import { Read as ReadTool , WorkspaceFile } from '@/lib/copilot/generated/tool-catalog-v1'
4+ import { getReadTargetBlock } from '@/lib/copilot/tools/client/read-block'
45import { getToolCompletedTitle } from '@/lib/copilot/tools/tool-display'
6+ import { getBareIconStyle } from '@/blocks/icon-color'
57import type { ToolCallStatus } from '../../../../types'
68import { resolveToolDisplayState } from '../../utils'
79
@@ -25,6 +27,7 @@ interface ToolCallItemProps {
2527 toolName : string
2628 displayTitle : string
2729 status : ToolCallStatus
30+ params ?: Record < string , unknown >
2831 streamingArgs ?: string
2932}
3033
@@ -33,8 +36,22 @@ interface ToolCallItemProps {
3336 * static label once terminal. For `workspace_file` the title is derived live
3437 * from the streaming args; because that path bypasses the completed-title
3538 * rewrite in `toToolData`, the past-tense flip is applied here on success.
39+ * A `read` of a block or integration schema shows the block's brand icon
40+ * inline next to its display name (e.g. the Gmail logo before "Read Gmail").
3641 */
37- export function ToolCallItem ( { toolName, displayTitle, status, streamingArgs } : ToolCallItemProps ) {
42+ export function ToolCallItem ( {
43+ toolName,
44+ displayTitle,
45+ status,
46+ params,
47+ streamingArgs,
48+ } : ToolCallItemProps ) {
49+ const readBlock = useMemo ( ( ) => {
50+ if ( toolName !== ReadTool . id ) return undefined
51+ const path = params ?. path
52+ return typeof path === 'string' ? getReadTargetBlock ( path ) : undefined
53+ } , [ toolName , params ] )
54+
3855 const liveWorkspaceFileTitle = useMemo ( ( ) => {
3956 if ( toolName !== WorkspaceFile . id || ! streamingArgs ) return null
4057 const titleMatch = streamingArgs . match ( / " t i t l e " \s * : \s * " ( [ ^ " ] + ) " / )
@@ -71,8 +88,13 @@ export function ToolCallItem({ toolName, displayTitle, status, streamingArgs }:
7188 ? ( getToolCompletedTitle ( liveTitle ) ?? liveTitle )
7289 : liveTitle
7390
91+ const BlockIcon = readBlock ?. icon
92+
7493 return (
75- < div className = 'flex items-center pl-6' >
94+ < div className = 'flex items-center gap-[6px] pl-6' >
95+ { BlockIcon && (
96+ < BlockIcon className = 'size-[14px] flex-shrink-0' style = { getBareIconStyle ( BlockIcon ) } />
97+ ) }
7698 { isExecuting ? (
7799 < ShimmerText className = 'text-[13px] [--shimmer-rest:var(--text-secondary)]' >
78100 { title }
0 commit comments