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:
@@ -218,6 +218,39 @@ function ToolCallSheetContent({ data, onClose }: ToolCallSheetContentProps) {
|
|||||||
) : null}
|
) : null}
|
||||||
</View>
|
</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 {
|
} else {
|
||||||
// Generic tool: show input/output as key-value pairs
|
// Generic tool: show input/output as key-value pairs
|
||||||
if (toolCallDisplay.input.length > 0) {
|
if (toolCallDisplay.input.length > 0) {
|
||||||
@@ -414,6 +447,10 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
fontFamily: Fonts.mono,
|
fontFamily: Fonts.mono,
|
||||||
fontSize: theme.fontSize.xs,
|
fontSize: theme.fontSize.xs,
|
||||||
},
|
},
|
||||||
|
rangeText: {
|
||||||
|
color: theme.colors.mutedForeground,
|
||||||
|
fontSize: theme.fontSize.xs,
|
||||||
|
},
|
||||||
diffContainer: {
|
diffContainer: {
|
||||||
borderWidth: theme.borderWidth[1],
|
borderWidth: theme.borderWidth[1],
|
||||||
borderColor: theme.colors.border,
|
borderColor: theme.colors.border,
|
||||||
|
|||||||
@@ -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)
|
// Generic tool call display schema (fallback)
|
||||||
const GenericToolCallSchema = z
|
const GenericToolCallSchema = z
|
||||||
.object({
|
.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>;
|
export type ToolCallDisplay = z.infer<typeof ToolCallDisplaySchema>;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user