feat(app): add Read tool call display with file path and content

- Add ReadToolCallSchema to parse Read tool calls (file_path, offset, limit)
- Display file path immediately from input (before result arrives)
- Show offset/limit range when specified
- Display file content in scrollable area when result completes

🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
Mohamed Boudra
2026-01-10 23:55:44 +07:00
parent 9048198045
commit a0abf4a79f
2 changed files with 72 additions and 1 deletions

View File

@@ -218,6 +218,39 @@ function ToolCallSheetContent({ data, onClose }: ToolCallSheetContentProps) {
) : null}
</View>
);
} else if (toolCallDisplay.type === "read") {
// Read tool: show file path and content
sections.push(
<View key="read" style={styles.section}>
<Text style={styles.sectionTitle}>File</Text>
<View style={styles.fileBadge}>
<Text style={styles.fileBadgeText}>{toolCallDisplay.filePath}</Text>
</View>
{(toolCallDisplay.offset !== undefined || toolCallDisplay.limit !== undefined) ? (
<Text style={styles.rangeText}>
{toolCallDisplay.offset !== undefined ? `Offset: ${toolCallDisplay.offset}` : ""}
{toolCallDisplay.offset !== undefined && toolCallDisplay.limit !== undefined ? " • " : ""}
{toolCallDisplay.limit !== undefined ? `Limit: ${toolCallDisplay.limit}` : ""}
</Text>
) : null}
{toolCallDisplay.content ? (
<ScrollView
style={styles.scrollArea}
contentContainerStyle={styles.scrollContent}
nestedScrollEnabled
showsVerticalScrollIndicator={true}
>
<ScrollView
horizontal
nestedScrollEnabled
showsHorizontalScrollIndicator={true}
>
<Text style={styles.scrollText}>{toolCallDisplay.content}</Text>
</ScrollView>
</ScrollView>
) : null}
</View>
);
} else {
// Generic tool: show input/output as key-value pairs
if (toolCallDisplay.input.length > 0) {
@@ -414,6 +447,10 @@ const styles = StyleSheet.create((theme) => ({
fontFamily: Fonts.mono,
fontSize: theme.fontSize.xs,
},
rangeText: {
color: theme.colors.mutedForeground,
fontSize: theme.fontSize.xs,
},
diffContainer: {
borderWidth: theme.borderWidth[1],
borderColor: theme.colors.border,

View File

@@ -967,6 +967,40 @@ const EditToolCallSchema = z
};
});
// Read input: { file_path: string, offset?: number, limit?: number }
const ReadInputSchema = z.object({
file_path: z.string(),
offset: z.number().optional(),
limit: z.number().optional(),
}).passthrough();
// Read result: { type: "file_read", filePath: string, content: string }
const ReadResultSchema = z.object({
type: z.literal("file_read"),
filePath: z.string(),
content: z.string(),
}).passthrough();
// Read tool call display schema
const ReadToolCallSchema = z
.object({
input: ReadInputSchema,
result: z.unknown(),
})
.transform((data): { type: "read"; filePath: string; content: string; offset?: number; limit?: number } => {
const filePath = data.input.file_path;
const resultParsed = ReadResultSchema.safeParse(data.result);
const content = resultParsed.success ? resultParsed.data.content : "";
return {
type: "read",
filePath,
content,
offset: data.input.offset,
limit: data.input.limit,
};
});
// Generic tool call display schema (fallback)
const GenericToolCallSchema = z
.object({
@@ -984,7 +1018,7 @@ const GenericToolCallSchema = z
};
});
const ToolCallDisplaySchema = z.union([ShellToolCallSchema, EditToolCallSchema, GenericToolCallSchema]);
const ToolCallDisplaySchema = z.union([ShellToolCallSchema, EditToolCallSchema, ReadToolCallSchema, GenericToolCallSchema]);
export type ToolCallDisplay = z.infer<typeof ToolCallDisplaySchema>;