History

fix(web): simplify expanded tool details (#9549)

maria committed 2 months ago

Commit 710f6dc1 parent f96a2201 file · +65 −27Browse files

Unified · Split

apps/web/src/components/chat/MessagesTimeline.tsx+65−27
@@ -2886,27 +2886,47 @@ function workEntryRawCommand( · 2885 unmodified lines
28862886 function buildToolCallExpandedBody(
28872887 workEntry: TimelineWorkEntry,
28882888 workspaceRoot: string | undefined,
2889+ visibleLabel: string,
2890+ viewedImagePath: string | null,
28892891 ): string | null {
28902892 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+ };
28912900 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)}`);
28932902 }
2903+ const command = workEntry.command?.trim();
28942904 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);
28992909 }
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);
29022913 }
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+ });
29042928 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"));
29102930 }
29112931 return blocks.length > 0 ? blocks.join("\n\n") : null;
29122932 }
@@ -3092,19 +3112,7 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: { · 179 unmodified lines
30923112 ? "circle-alert"
30933113 : workEntryIconName(workEntry);
30943114 const previewText = displayLabel ?? workEntryDisplayLabel(workEntry, workspaceRoot);
3095− const displayText =
3096− !toolPresentation && expanded && workEntry.command?.trim() ? "Command" : previewText;
30973115 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;
31083116 const viewedImage =
31093117 viewedImagePath && threadRef
31103118 ? resolveViewedImageAsset(viewedImagePath, {
@@ -3112,6 +3120,24 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: { · 1 unmodified line
31123120 workspaceRoot,
31133121 })
31143122 : 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;
31153141 const showDestructiveRowStyle =
31163142 showFailedIndicator &&
31173143 (workEntrySignalsSevereFailure(workEntry) || !workLogEntryIsToolLike(workEntry));
@@ -3183,7 +3209,19 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: { · 65 unmodified lines
31833209 <div className="flex min-w-0 flex-1 items-center gap-1.5">
31843210 <div className="min-w-0 flex-1 overflow-hidden">
31853211 <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>
31873225 </p>
31883226 </div>
31893227 {showFailedIndicator && hasSpecialToolIcon ? (
@@ -3224,7 +3262,7 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: { · 34 unmodified lines
32243262 ) : null}
32253263 {expanded && canExpand && expandedBody ? (
32263264 <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"
32283266 onClick={stopRowToggle}
32293267 onPointerDown={stopRowToggle}
32303268 >