fix(app): keep single tool calls in overview list

This commit is contained in:
Mohamed Boudra
2026-07-15 11:50:10 +02:00
parent abfe955867
commit 3673846433
2 changed files with 9 additions and 60 deletions

View File

@@ -775,10 +775,8 @@ const AgentStreamViewComponent = forwardRef<AgentStreamViewHandle, AgentStreamVi
<OverviewToolCallGroupView <OverviewToolCallGroupView
group={group} group={group}
expanded={expanded} expanded={expanded}
isCompact={isMobile}
isLastInSequence={layoutItem.isLastInToolSequence} isLastInSequence={layoutItem.isLastInToolSequence}
onExpandedChange={setToolCallGroupExpanded} onExpandedChange={setToolCallGroupExpanded}
cwd={context.cwd}
> >
{expanded {expanded
? group.run.calls.map((call, index) => ( ? group.run.calls.map((call, index) => (
@@ -796,9 +794,7 @@ const AgentStreamViewComponent = forwardRef<AgentStreamViewHandle, AgentStreamVi
}, },
[ [
projectedToolCalls.groupsByHostId, projectedToolCalls.groupsByHostId,
context.cwd,
expandedToolCallGroupIds, expandedToolCallGroupIds,
isMobile,
renderSingleToolCallItem, renderSingleToolCallItem,
setToolCallGroupExpanded, setToolCallGroupExpanded,
], ],

View File

@@ -4,20 +4,13 @@ import { useTranslation } from "react-i18next";
import { Wrench } from "lucide-react-native"; import { Wrench } from "lucide-react-native";
import { StyleSheet } from "react-native-unistyles"; import { StyleSheet } from "react-native-unistyles";
import { ExpandableBadge } from "@/components/message"; import { ExpandableBadge } from "@/components/message";
import { ToolCallDetailsContent } from "@/components/tool-call-details";
import { useToolCallSheet } from "@/components/tool-call-sheet";
import { buildToolCallPresentation } from "@/tool-calls/presentation";
import { resolveToolCallIcon } from "@/utils/tool-call-icon";
import { describeToolCall } from "../grouping";
import { type OverviewSummary, type OverviewToolCallGroup } from "./model"; import { type OverviewSummary, type OverviewToolCallGroup } from "./model";
interface OverviewGroupProps { interface OverviewGroupProps {
group: OverviewToolCallGroup; group: OverviewToolCallGroup;
expanded: boolean; expanded: boolean;
isCompact: boolean;
isLastInSequence: boolean; isLastInSequence: boolean;
onExpandedChange: (groupId: string, expanded: boolean) => void; onExpandedChange: (groupId: string, expanded: boolean) => void;
cwd?: string;
children: ReactNode; children: ReactNode;
} }
@@ -61,63 +54,23 @@ function useOverviewSummary(summary: OverviewSummary): string {
export const OverviewToolCallGroupView = memo(function OverviewToolCallGroupView({ export const OverviewToolCallGroupView = memo(function OverviewToolCallGroupView({
group, group,
expanded, expanded,
isCompact,
isLastInSequence, isLastInSequence,
onExpandedChange, onExpandedChange,
cwd,
children, children,
}: OverviewGroupProps) { }: OverviewGroupProps) {
const { t } = useTranslation(); const { t } = useTranslation();
const { openToolCall } = useToolCallSheet();
const scrollRef = useRef<ScrollView>(null); const scrollRef = useRef<ScrollView>(null);
const aggregateSummary = useOverviewSummary(group.summary); const aggregateSummary = useOverviewSummary(group.summary);
const latest = useMemo(() => {
const descriptor = describeToolCall(group.run.latest);
return {
detail: descriptor.detail,
presentation: buildToolCallPresentation({
toolName: descriptor.name,
status: descriptor.status,
error: descriptor.error,
detail: descriptor.detail,
metadata: descriptor.metadata,
cwd,
resolveIcon: resolveToolCallIcon,
}),
};
}, [cwd, group.run.latest]);
const opensSingleCallSheet = isCompact && group.run.calls.length === 1;
const failedSummary = const failedSummary =
group.failedCount > 0 ? t("toolCallGroup.failed", { count: group.failedCount }) : undefined; group.failedCount > 0 ? t("toolCallGroup.failed", { count: group.failedCount }) : undefined;
const scrollToLatest = useCallback(() => { const scrollToLatest = useCallback(() => {
scrollRef.current?.scrollToEnd({ animated: false }); scrollRef.current?.scrollToEnd({ animated: false });
}, []); }, []);
const toggle = useCallback(() => { const toggle = useCallback(() => {
if (opensSingleCallSheet) {
openToolCall({
displayName: latest.presentation.displayName,
summary: latest.presentation.summary,
detail: latest.detail,
errorText: latest.presentation.errorText,
icon: latest.presentation.icon,
showLoadingSkeleton: latest.presentation.isLoadingDetails,
});
return;
}
onExpandedChange(group.run.id, !expanded); onExpandedChange(group.run.id, !expanded);
}, [expanded, group.run.id, latest, onExpandedChange, openToolCall, opensSingleCallSheet]); }, [expanded, group.run.id, onExpandedChange]);
const renderDetails = useCallback(() => { const renderDetails = useCallback(
if (group.run.calls.length === 1) { () => (
return (
<ToolCallDetailsContent
detail={latest.detail}
errorText={latest.presentation.errorText}
maxHeight={TOOL_CALL_GROUP_MAX_HEIGHT}
showLoadingSkeleton={latest.presentation.isLoadingDetails}
/>
);
}
return (
<ScrollView <ScrollView
ref={scrollRef} ref={scrollRef}
style={styles.scroll} style={styles.scroll}
@@ -128,9 +81,9 @@ export const OverviewToolCallGroupView = memo(function OverviewToolCallGroupView
> >
{children} {children}
</ScrollView> </ScrollView>
); ),
}, [children, group.run.calls.length, latest, scrollToLatest]); [children, scrollToLatest],
const canExpand = group.run.calls.length > 1 || latest.presentation.canOpenDetails; );
return ( return (
<ExpandableBadge <ExpandableBadge
@@ -140,10 +93,10 @@ export const OverviewToolCallGroupView = memo(function OverviewToolCallGroupView
icon={Wrench} icon={Wrench}
isLoading={group.isLoading} isLoading={group.isLoading}
isError={group.failedCount > 0} isError={group.failedCount > 0}
isExpanded={opensSingleCallSheet ? false : expanded} isExpanded={expanded}
isLastInSequence={isLastInSequence} isLastInSequence={isLastInSequence}
onToggle={canExpand ? toggle : undefined} onToggle={toggle}
renderDetails={canExpand && !opensSingleCallSheet ? renderDetails : undefined} renderDetails={renderDetails}
borderlessWhenExpanded borderlessWhenExpanded
/> />
); );