| ... | @@ -2886,27 +2886,47 @@ function workEntryRawCommand( | ... | @@ -2886,27 +2886,47 @@ function workEntryRawCommand( |
| 2886 | function buildToolCallExpandedBody( | 2886 | function buildToolCallExpandedBody( |
| 2887 | workEntry: TimelineWorkEntry, | 2887 | workEntry: TimelineWorkEntry, |
| 2888 | workspaceRoot: string | undefined, | 2888 | workspaceRoot: string | undefined, |
| | 2889 | visibleLabel: string, |
| | 2890 | viewedImagePath: string | null, |
| 2889 | ): string | null { | 2891 | ): string | null { |
| 2890 | const blocks: string[] = []; | 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 | if (workEntry.itemType === "mcp_tool_call" && workEntry.toolData !== undefined) { | 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 | const raw = workEntryRawCommand(workEntry); | 2904 | const raw = workEntryRawCommand(workEntry); |
| 2895 | if (raw?.trim()) { | 2905 | if (command === visibleLabel.trim()) { |
| 2896 | blocks.push(raw.trim()); | 2906 | seen.add(command); |
| 2897 | } else if (workEntry.command?.trim()) { | 2907 | } else { |
| 2898 | blocks.push(workEntry.command.trim()); | 2908 | addBlock(raw ?? command); |
| 2899 | } | 2909 | } |
| 2900 | if (workEntry.detail?.trim()) { | 2910 | const detail = workEntry.detail?.trim(); |
| 2901 | blocks.push(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 | if (changedFiles.length > 0) { | 2928 | if (changedFiles.length > 0) { |
| 2905 | blocks.push( | 2929 | addBlock([...new Set(changedFiles)].join("\n")); |
| 2906 | changedFiles | | |
| 2907 | .map((filePath) => formatWorkspaceRelativePath(filePath, workspaceRoot)) | | |
| 2908 | .join("\n"), | | |
| 2909 | ); | | |
| 2910 | } | 2930 | } |
| 2911 | return blocks.length > 0 ? blocks.join("\n\n") : null; | 2931 | return blocks.length > 0 ? blocks.join("\n\n") : null; |
| 2912 | } | 2932 | } |
| ... | @@ -3092,19 +3112,7 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: { | ... | @@ -3092,19 +3112,7 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: { |
| 3092 | ? "circle-alert" | 3112 | ? "circle-alert" |
| 3093 | : workEntryIconName(workEntry); | 3113 | : workEntryIconName(workEntry); |
| 3094 | const previewText = displayLabel ?? workEntryDisplayLabel(workEntry, workspaceRoot); | 3114 | const previewText = displayLabel ?? workEntryDisplayLabel(workEntry, workspaceRoot); |
| 3095 | const displayText = | | |
| 3096 | !toolPresentation && expanded && workEntry.command?.trim() ? "Command" : previewText; | | |
| 3097 | const viewedImagePath = workEntryViewedImagePath(workEntry); | 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 | const viewedImage = | 3116 | const viewedImage = |
| 3109 | viewedImagePath && threadRef | 3117 | viewedImagePath && threadRef |
| 3110 | ? resolveViewedImageAsset(viewedImagePath, { | 3118 | ? resolveViewedImageAsset(viewedImagePath, { |
| ... | @@ -3112,6 +3120,24 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: { | ... | @@ -3112,6 +3120,24 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: { |
| 3112 | workspaceRoot, | 3120 | workspaceRoot, |
| 3113 | }) | 3121 | }) |
| 3114 | : null; | 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 | const showDestructiveRowStyle = | 3141 | const showDestructiveRowStyle = |
| 3116 | showFailedIndicator && | 3142 | showFailedIndicator && |
| 3117 | (workEntrySignalsSevereFailure(workEntry) || !workLogEntryIsToolLike(workEntry)); | 3143 | (workEntrySignalsSevereFailure(workEntry) || !workLogEntryIsToolLike(workEntry)); |
| ... | @@ -3183,7 +3209,19 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: { | ... | @@ -3183,7 +3209,19 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: { |
| 3183 | <div className="flex min-w-0 flex-1 items-center gap-1.5"> | 3209 | <div className="flex min-w-0 flex-1 items-center gap-1.5"> |
| 3184 | <div className="min-w-0 flex-1 overflow-hidden"> | 3210 | <div className="min-w-0 flex-1 overflow-hidden"> |
| 3185 | <p className="flex min-w-0 w-full items-baseline gap-1.5 text-sm leading-relaxed"> | 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 | </p> | 3225 | </p> |
| 3188 | </div> | 3226 | </div> |
| 3189 | {showFailedIndicator && hasSpecialToolIcon ? ( | 3227 | {showFailedIndicator && hasSpecialToolIcon ? ( |
| ... | @@ -3224,7 +3262,7 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: { | ... | @@ -3224,7 +3262,7 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: { |
| 3224 | ) : null} | 3262 | ) : null} |
| 3225 | {expanded && canExpand && expandedBody ? ( | 3263 | {expanded && canExpand && expandedBody ? ( |
| 3226 | <div | 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 | onClick={stopRowToggle} | 3266 | onClick={stopRowToggle} |
| 3229 | onPointerDown={stopRowToggle} | 3267 | onPointerDown={stopRowToggle} |
| 3230 | > | 3268 | > |