| ... | ... | @@ -2886,27 +2886,47 @@ function workEntryRawCommand( |
| 2886 | 2886 | function buildToolCallExpandedBody( |
| 2887 | 2887 | workEntry: TimelineWorkEntry, |
| 2888 | 2888 | workspaceRoot: string | undefined, |
| 2889 | visibleLabel: string, |
| 2890 | viewedImagePath: string | null, |
| 2889 | 2891 | ): string | null { |
| 2890 | 2892 | const blocks: string[] = []; |
| 2893 | const seen = new Set<string>(); |
| 2894 | const addBlock = (value: string | null | undefined) => { |
| 2895 | const text = value?.trim(); |
| 2896 | if (!text || seen.has(text)) return; |
| 2897 | seen.add(text); |
| 2898 | blocks.push(text); |
| 2899 | }; |
| 2891 | 2900 | if (workEntry.itemType === "mcp_tool_call" && workEntry.toolData !== undefined) { |
| 2892 | | blocks.push(`MCP call\n${JSON.stringify(workEntry.toolData, null, 2)}`); |
| 2901 | addBlock(`MCP call\n${JSON.stringify(workEntry.toolData, null, 2)}`); |
| 2893 | 2902 | } |
| 2903 | const command = workEntry.command?.trim(); |
| 2894 | 2904 | const raw = workEntryRawCommand(workEntry); |
| 2895 | | if (raw?.trim()) { |
| 2896 | | blocks.push(raw.trim()); |
| 2897 | | } else if (workEntry.command?.trim()) { |
| 2898 | | blocks.push(workEntry.command.trim()); |
| 2905 | if (command === visibleLabel.trim()) { |
| 2906 | seen.add(command); |
| 2907 | } else { |
| 2908 | addBlock(raw ?? command); |
| 2899 | 2909 | } |
| 2900 | | if (workEntry.detail?.trim()) { |
| 2901 | | blocks.push(workEntry.detail.trim()); |
| 2910 | const detail = workEntry.detail?.trim(); |
| 2911 | if (detail !== viewedImagePath?.trim()) { |
| 2912 | addBlock(detail); |
| 2902 | 2913 | } |
| 2903 | | const changedFiles = workEntry.changedFiles ?? []; |
| 2914 | const viewedImagePaths = new Set( |
| 2915 | viewedImagePath |
| 2916 | ? [viewedImagePath.trim(), formatWorkspaceRelativePath(viewedImagePath, workspaceRoot)] |
| 2917 | : [], |
| 2918 | ); |
| 2919 | const changedFiles = (workEntry.changedFiles ?? []).flatMap((filePath) => { |
| 2920 | const formattedPath = formatWorkspaceRelativePath(filePath, workspaceRoot); |
| 2921 | return viewedImagePaths.has(filePath) || |
| 2922 | viewedImagePaths.has(formattedPath) || |
| 2923 | filePath.trim() === detail || |
| 2924 | formattedPath === detail |
| 2925 | ? [] |
| 2926 | : [formattedPath]; |
| 2927 | }); |
| 2904 | 2928 | if (changedFiles.length > 0) { |
| 2905 | | blocks.push( |
| 2906 | | changedFiles |
| 2907 | | .map((filePath) => formatWorkspaceRelativePath(filePath, workspaceRoot)) |
| 2908 | | .join("\n"), |
| 2909 | | ); |
| 2929 | addBlock([...new Set(changedFiles)].join("\n")); |
| 2910 | 2930 | } |
| 2911 | 2931 | return blocks.length > 0 ? blocks.join("\n\n") : null; |
| 2912 | 2932 | } |
| ... | ... | @@ -3092,19 +3112,7 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: { |
| 3092 | 3112 | ? "circle-alert" |
| 3093 | 3113 | : workEntryIconName(workEntry); |
| 3094 | 3114 | const previewText = displayLabel ?? workEntryDisplayLabel(workEntry, workspaceRoot); |
| 3095 | | const displayText = |
| 3096 | | !toolPresentation && expanded && workEntry.command?.trim() ? "Command" : previewText; |
| 3097 | 3115 | const viewedImagePath = workEntryViewedImagePath(workEntry); |
| 3098 | | const canExpand = |
| 3099 | | (workEntry.itemType === "mcp_tool_call" && workEntry.toolData !== undefined) || |
| 3100 | | Boolean( |
| 3101 | | workEntryRawCommand(workEntry) || |
| 3102 | | workEntry.command?.trim() || |
| 3103 | | workEntry.detail?.trim() || |
| 3104 | | workEntry.changedFiles?.length || |
| 3105 | | viewedImagePath, |
| 3106 | | ); |
| 3107 | | const expandedBody = expanded ? buildToolCallExpandedBody(workEntry, workspaceRoot) : null; |
| 3108 | 3116 | const viewedImage = |
| 3109 | 3117 | viewedImagePath && threadRef |
| 3110 | 3118 | ? resolveViewedImageAsset(viewedImagePath, { |
| ... | ... | @@ -3112,6 +3120,24 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: { |
| 3112 | 3120 | workspaceRoot, |
| 3113 | 3121 | }) |
| 3114 | 3122 | : null; |
| 3123 | const commandMatchesVisibleLabel = workEntry.command?.trim() === previewText.trim(); |
| 3124 | const canExpand = |
| 3125 | (workEntry.itemType === "mcp_tool_call" && workEntry.toolData !== undefined) || |
| 3126 | Boolean( |
| 3127 | (!commandMatchesVisibleLabel && |
| 3128 | (workEntryRawCommand(workEntry) || workEntry.command?.trim())) || |
| 3129 | workEntry.detail?.trim() || |
| 3130 | workEntry.changedFiles?.length || |
| 3131 | viewedImage, |
| 3132 | ); |
| 3133 | const expandedBody = expanded |
| 3134 | ? buildToolCallExpandedBody( |
| 3135 | workEntry, |
| 3136 | workspaceRoot, |
| 3137 | previewText, |
| 3138 | viewedImage ? viewedImagePath : null, |
| 3139 | ) |
| 3140 | : null; |
| 3115 | 3141 | const showDestructiveRowStyle = |
| 3116 | 3142 | showFailedIndicator && |
| 3117 | 3143 | (workEntrySignalsSevereFailure(workEntry) || !workLogEntryIsToolLike(workEntry)); |
| ... | ... | @@ -3183,7 +3209,19 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: { |
| 3183 | 3209 | <div className="flex min-w-0 flex-1 items-center gap-1.5"> |
| 3184 | 3210 | <div className="min-w-0 flex-1 overflow-hidden"> |
| 3185 | 3211 | <p className="flex min-w-0 w-full items-baseline gap-1.5 text-sm leading-relaxed"> |
| 3186 | | <span className={cn("min-w-0 flex-1 truncate", headingClass)}>{displayText}</span> |
| 3212 | <span |
| 3213 | className={cn( |
| 3214 | "min-w-0 flex-1", |
| 3215 | expanded || (commandMatchesVisibleLabel && !canExpand) |
| 3216 | ? "whitespace-pre-wrap break-words select-text" |
| 3217 | : "truncate", |
| 3218 | headingClass, |
| 3219 | )} |
| 3220 | onClick={expanded ? stopRowToggle : undefined} |
| 3221 | onPointerDown={expanded ? stopRowToggle : undefined} |
| 3222 | > |
| 3223 | {previewText} |
| 3224 | </span> |
| 3187 | 3225 | </p> |
| 3188 | 3226 | </div> |
| 3189 | 3227 | {showFailedIndicator && hasSpecialToolIcon ? ( |
| ... | ... | @@ -3224,7 +3262,7 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: { |
| 3224 | 3262 | ) : null} |
| 3225 | 3263 | {expanded && canExpand && expandedBody ? ( |
| 3226 | 3264 | <div |
| 3227 | | className="mt-1 ms-7 cursor-default border-s border-border/45 ps-3 pt-0.5" |
| 3265 | className="mt-1 ms-7 cursor-default rounded-md bg-muted/40 px-3 py-2" |
| 3228 | 3266 | onClick={stopRowToggle} |
| 3229 | 3267 | onPointerDown={stopRowToggle} |
| 3230 | 3268 | > |