feat(app): add text selection and fix shell error display
- Add selectable prop to all Text components in tool call content areas - Add ShellErrorResultSchema to parse tool_result error format - Update ShellToolCallSchema to extract content from error results - Also handle tool_result extraction in formatValue as fallback
This commit is contained in:
@@ -27,6 +27,19 @@ function formatValue(value: unknown): string {
|
|||||||
if (typeof value === "string") {
|
if (typeof value === "string") {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
// Extract content from tool_result objects
|
||||||
|
if (
|
||||||
|
typeof value === "object" &&
|
||||||
|
value !== null &&
|
||||||
|
"type" in value &&
|
||||||
|
(value as { type: string }).type === "tool_result" &&
|
||||||
|
"content" in value
|
||||||
|
) {
|
||||||
|
const content = (value as { content: unknown }).content;
|
||||||
|
if (typeof content === "string") {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return JSON.stringify(value, null, 2);
|
return JSON.stringify(value, null, 2);
|
||||||
} catch {
|
} catch {
|
||||||
@@ -66,7 +79,7 @@ export function ToolCallDetailsContent({
|
|||||||
contentContainerStyle={styles.jsonContent}
|
contentContainerStyle={styles.jsonContent}
|
||||||
showsHorizontalScrollIndicator={true}
|
showsHorizontalScrollIndicator={true}
|
||||||
>
|
>
|
||||||
<Text style={styles.scrollText}>{display.command}</Text>
|
<Text selectable style={styles.scrollText}>{display.command}</Text>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
{display.output ? (
|
{display.output ? (
|
||||||
<ScrollView
|
<ScrollView
|
||||||
@@ -80,7 +93,7 @@ export function ToolCallDetailsContent({
|
|||||||
nestedScrollEnabled
|
nestedScrollEnabled
|
||||||
showsHorizontalScrollIndicator={true}
|
showsHorizontalScrollIndicator={true}
|
||||||
>
|
>
|
||||||
<Text style={styles.scrollText}>{display.output}</Text>
|
<Text selectable style={styles.scrollText}>{display.output}</Text>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
) : null}
|
) : null}
|
||||||
@@ -126,7 +139,7 @@ export function ToolCallDetailsContent({
|
|||||||
nestedScrollEnabled
|
nestedScrollEnabled
|
||||||
showsHorizontalScrollIndicator={true}
|
showsHorizontalScrollIndicator={true}
|
||||||
>
|
>
|
||||||
<Text style={styles.scrollText}>{display.content}</Text>
|
<Text selectable style={styles.scrollText}>{display.content}</Text>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
) : null}
|
) : null}
|
||||||
@@ -151,7 +164,7 @@ export function ToolCallDetailsContent({
|
|||||||
contentContainerStyle={styles.jsonContent}
|
contentContainerStyle={styles.jsonContent}
|
||||||
showsHorizontalScrollIndicator={true}
|
showsHorizontalScrollIndicator={true}
|
||||||
>
|
>
|
||||||
<Text style={styles.scrollText}>{pair.value}</Text>
|
<Text selectable style={styles.scrollText}>{pair.value}</Text>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
@@ -175,7 +188,7 @@ export function ToolCallDetailsContent({
|
|||||||
contentContainerStyle={styles.jsonContent}
|
contentContainerStyle={styles.jsonContent}
|
||||||
showsHorizontalScrollIndicator={true}
|
showsHorizontalScrollIndicator={true}
|
||||||
>
|
>
|
||||||
<Text style={styles.scrollText}>{pair.value}</Text>
|
<Text selectable style={styles.scrollText}>{pair.value}</Text>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
@@ -195,7 +208,7 @@ export function ToolCallDetailsContent({
|
|||||||
contentContainerStyle={styles.jsonContent}
|
contentContainerStyle={styles.jsonContent}
|
||||||
showsHorizontalScrollIndicator={true}
|
showsHorizontalScrollIndicator={true}
|
||||||
>
|
>
|
||||||
<Text style={[styles.scrollText, styles.errorText]}>
|
<Text selectable style={[styles.scrollText, styles.errorText]}>
|
||||||
{errorText}
|
{errorText}
|
||||||
</Text>
|
</Text>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|||||||
@@ -900,6 +900,13 @@ const ShellResultSchema = z.object({
|
|||||||
output: z.string(),
|
output: z.string(),
|
||||||
}).passthrough();
|
}).passthrough();
|
||||||
|
|
||||||
|
// Shell error result: { type: "tool_result", content: "Exit code 128\n...", is_error: true }
|
||||||
|
const ShellErrorResultSchema = z.object({
|
||||||
|
type: z.literal("tool_result"),
|
||||||
|
content: z.string(),
|
||||||
|
is_error: z.literal(true),
|
||||||
|
}).passthrough();
|
||||||
|
|
||||||
// Shell tool call display schema
|
// Shell tool call display schema
|
||||||
const ShellToolCallSchema = z
|
const ShellToolCallSchema = z
|
||||||
.object({
|
.object({
|
||||||
@@ -911,13 +918,30 @@ const ShellToolCallSchema = z
|
|||||||
? data.input.command.join(" ")
|
? data.input.command.join(" ")
|
||||||
: data.input.command;
|
: data.input.command;
|
||||||
|
|
||||||
|
// Try parsing as success result first
|
||||||
const resultParsed = ShellResultSchema.safeParse(data.result);
|
const resultParsed = ShellResultSchema.safeParse(data.result);
|
||||||
const output = resultParsed.success ? resultParsed.data.output : "";
|
if (resultParsed.success) {
|
||||||
|
return {
|
||||||
|
type: "shell" as const,
|
||||||
|
command,
|
||||||
|
output: resultParsed.data.output,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try parsing as error result
|
||||||
|
const errorParsed = ShellErrorResultSchema.safeParse(data.result);
|
||||||
|
if (errorParsed.success) {
|
||||||
|
return {
|
||||||
|
type: "shell" as const,
|
||||||
|
command,
|
||||||
|
output: errorParsed.data.content,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: "shell" as const,
|
type: "shell" as const,
|
||||||
command,
|
command,
|
||||||
output,
|
output: "",
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user