wip: tool call structure investigation and e2e tests

- Add debug logging for tool call payloads in agent-stream-view
- Add e2e tests to verify tool call structure for Claude and Codex agents
- Include sidebar toggle and horizontal scroll improvements from previous work

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Mohamed Boudra
2026-01-07 10:30:29 +07:00
co-authored by Claude Opus 4.5
parent 351735a71b
commit 4f3b2317ab
11 changed files with 398 additions and 80 deletions
+66 -29
View File
@@ -1,5 +1,13 @@
import { useState, useCallback } from "react";
import { View, Text, ActivityIndicator, Pressable, RefreshControl } from "react-native";
import { useState, useCallback, useEffect, useId } from "react";
import {
View,
Text,
ActivityIndicator,
Pressable,
RefreshControl,
type NativeSyntheticEvent,
type NativeScrollEvent,
} from "react-native";
import { ScrollView } from "react-native-gesture-handler";
import { StyleSheet, useUnistyles } from "react-native-unistyles";
import { ChevronRight } from "lucide-react-native";
@@ -10,6 +18,7 @@ import {
type DiffLine,
type HighlightToken,
} from "@/hooks/use-highlighted-diff-query";
import { useHorizontalScrollOptional } from "@/contexts/horizontal-scroll-context";
type HighlightStyle = NonNullable<HighlightToken["style"]>;
@@ -70,6 +79,7 @@ function HighlightedText({ tokens, lineType }: HighlightedTextProps) {
interface DiffFileSectionProps {
file: ParsedDiffFile;
defaultExpanded?: boolean;
testID?: string;
}
function DiffLineView({ line }: { line: DiffLine }) {
@@ -106,16 +116,37 @@ function DiffLineView({ line }: { line: DiffLine }) {
);
}
function DiffFileSection({ file, defaultExpanded = true }: DiffFileSectionProps) {
function DiffFileSection({ file, defaultExpanded = true, testID }: DiffFileSectionProps) {
const { theme } = useUnistyles();
const [isExpanded, setIsExpanded] = useState(defaultExpanded);
const horizontalScroll = useHorizontalScrollOptional();
const scrollId = useId();
const toggleExpanded = useCallback(() => {
setIsExpanded((prev) => !prev);
}, []);
// Register/unregister scroll offset tracking
useEffect(() => {
if (!horizontalScroll || !isExpanded) return;
// Start at 0 (not scrolled)
horizontalScroll.registerScrollOffset(scrollId, 0);
return () => {
horizontalScroll.unregisterScrollOffset(scrollId);
};
}, [horizontalScroll, isExpanded, scrollId]);
const handleScroll = useCallback(
(event: NativeSyntheticEvent<NativeScrollEvent>) => {
if (!horizontalScroll) return;
const offsetX = event.nativeEvent.contentOffset.x;
horizontalScroll.registerScrollOffset(scrollId, offsetX);
},
[horizontalScroll, scrollId]
);
return (
<View style={styles.fileSection}>
<View style={styles.fileSection} testID={testID}>
<Pressable
style={({ pressed }) => [
styles.fileHeader,
@@ -154,8 +185,11 @@ function DiffFileSection({ file, defaultExpanded = true }: DiffFileSectionProps)
horizontal
nestedScrollEnabled
showsHorizontalScrollIndicator
bounces={false}
style={styles.diffContent}
contentContainerStyle={styles.diffContentInner}
onScroll={handleScroll}
scrollEventThrottle={16}
>
<View style={styles.linesContainer}>
{file.hunks.map((hunk, hunkIndex) =>
@@ -200,7 +234,7 @@ export function GitDiffPane({ serverId, agentId }: GitDiffPaneProps) {
return (
<ScrollView
style={styles.scrollView}
contentContainerStyle={styles.contentContainer}
testID="git-diff-scroll"
refreshControl={
<RefreshControl
refreshing={isFetching && !isLoading}
@@ -210,24 +244,26 @@ export function GitDiffPane({ serverId, agentId }: GitDiffPaneProps) {
/>
}
>
{isLoading ? (
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" />
<Text style={styles.loadingText}>Loading changes...</Text>
</View>
) : isError ? (
<View style={styles.errorContainer}>
<Text style={styles.errorText}>{errorMessage ?? "Failed to load changes"}</Text>
</View>
) : !hasChanges ? (
<View style={styles.emptyContainer}>
<Text style={styles.emptyText}>No changes</Text>
</View>
) : (
files.map((file, fileIndex) => (
<DiffFileSection key={fileIndex} file={file} />
))
)}
<View style={styles.contentContainer} testID="git-diff-content">
{isLoading ? (
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" />
<Text style={styles.loadingText}>Loading changes...</Text>
</View>
) : isError ? (
<View style={styles.errorContainer}>
<Text style={styles.errorText}>{errorMessage ?? "Failed to load changes"}</Text>
</View>
) : !hasChanges ? (
<View style={styles.emptyContainer}>
<Text style={styles.emptyText}>No changes</Text>
</View>
) : (
files.map((file, fileIndex) => (
<DiffFileSection key={fileIndex} file={file} testID={`diff-file-${fileIndex}`} />
))
)}
</View>
</ScrollView>
);
}
@@ -238,7 +274,7 @@ const styles = StyleSheet.create((theme) => ({
},
contentContainer: {
paddingHorizontal: theme.spacing[2],
paddingTop: theme.spacing[2],
paddingTop: theme.spacing[3],
paddingBottom: theme.spacing[8],
},
loadingContainer: {
@@ -346,7 +382,7 @@ const styles = StyleSheet.create((theme) => ({
diffContent: {
borderTopWidth: theme.borderWidth[1],
borderTopColor: theme.colors.border,
backgroundColor: "#0d1117", // GitHub dark background
backgroundColor: "#0d1117",
},
diffContentInner: {
flexDirection: "column",
@@ -354,6 +390,7 @@ const styles = StyleSheet.create((theme) => ({
linesContainer: {
alignSelf: "flex-start",
minWidth: "100%",
backgroundColor: "#0d1117",
},
diffLineContainer: {
paddingHorizontal: theme.spacing[3],
@@ -365,25 +402,25 @@ const styles = StyleSheet.create((theme) => ({
color: theme.colors.foreground,
},
addLineContainer: {
backgroundColor: "rgba(46, 160, 67, 0.1)", // GitHub green with transparency
backgroundColor: "rgba(46, 160, 67, 0.15)", // GitHub green
},
addLineText: {
color: "#c9d1d9", // Same text color as all code
},
removeLineContainer: {
backgroundColor: "rgba(248, 81, 73, 0.1)", // GitHub red with transparency
backgroundColor: "rgba(248, 81, 73, 0.1)", // GitHub red
},
removeLineText: {
color: "#c9d1d9", // Same text color as all code
},
headerLineContainer: {
backgroundColor: "#161b22", // GitHub dark header
backgroundColor: theme.colors.muted,
},
headerLineText: {
color: theme.colors.mutedForeground,
},
contextLineContainer: {
backgroundColor: "#0d1117", // GitHub dark background
backgroundColor: "#0d1117",
},
contextLineText: {
color: theme.colors.mutedForeground,