Skip to content

Commit 79b4e53

Browse files
committed
tool parsing cleanup
1 parent 2ef9a7e commit 79b4e53

File tree

6 files changed

+97
-67
lines changed

6 files changed

+97
-67
lines changed

src/renderer/features/logs/tools/BashOutputToolView.tsx

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type {
1010
ShellStatus,
1111
} from "@features/logs/tools/types";
1212
import { Box } from "@radix-ui/themes";
13+
import { parseShellStatusResult } from "@utils/tool-results";
1314

1415
type BashOutputToolViewProps = BaseToolViewProps<
1516
BashOutputArgs,
@@ -19,20 +20,7 @@ type BashOutputToolViewProps = BaseToolViewProps<
1920
export function BashOutputToolView({ args, result }: BashOutputToolViewProps) {
2021
const { filter } = args;
2122

22-
// Parse result
23-
let stdout = "";
24-
let stderr = "";
25-
let status: string | undefined;
26-
27-
if (result) {
28-
if (typeof result === "string") {
29-
stdout = result;
30-
} else if (typeof result === "object") {
31-
stdout = result.stdout || "";
32-
stderr = result.stderr || "";
33-
status = result.status;
34-
}
35-
}
23+
const { stdout, stderr, status } = parseShellStatusResult(result);
3624

3725
return (
3826
<Box>

src/renderer/features/logs/tools/BashToolView.tsx

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,14 @@ import type {
1111
ShellResult,
1212
} from "@features/logs/tools/types";
1313
import { Box } from "@radix-ui/themes";
14+
import { parseShellResult } from "@utils/tool-results";
1415

1516
type BashToolViewProps = BaseToolViewProps<BashArgs, string | ShellResult>;
1617

1718
export function BashToolView({ args, result }: BashToolViewProps) {
1819
const { command, timeout, run_in_background } = args;
1920

20-
// Parse result
21-
let stdout = "";
22-
let stderr = "";
23-
let exitCode: number | undefined;
24-
25-
if (result) {
26-
if (typeof result === "string") {
27-
stdout = result;
28-
} else if (typeof result === "object") {
29-
stdout = result.stdout || "";
30-
stderr = result.stderr || "";
31-
exitCode = result.exitCode;
32-
}
33-
}
21+
const { stdout, stderr, exitCode } = parseShellResult(result);
3422

3523
return (
3624
<Box>

src/renderer/features/logs/tools/GrepToolView.tsx

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type {
1010
GrepResult,
1111
} from "@features/logs/tools/types";
1212
import { Box, Code } from "@radix-ui/themes";
13-
import { parseStringListResult, truncateList } from "@utils/tool-results";
13+
import { parseGrepResult, truncateList } from "@utils/tool-results";
1414

1515
type GrepToolViewProps = BaseToolViewProps<GrepArgs, string | GrepResult>;
1616

@@ -22,18 +22,7 @@ export function GrepToolView({ args, result }: GrepToolViewProps) {
2222
const contextBefore = args["-B"];
2323
const contextAround = args["-C"];
2424

25-
// Parse result
26-
let matches: string[] = [];
27-
let count: number | undefined;
28-
29-
if (result) {
30-
if (typeof result === "string") {
31-
matches = parseStringListResult(result);
32-
} else if (typeof result === "object") {
33-
matches = result.matches || [];
34-
count = result.count;
35-
}
36-
}
25+
const { matches, count } = parseGrepResult(result);
3726

3827
return (
3928
<Box>

src/renderer/features/logs/tools/KillShellToolView.tsx

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,15 @@ import type {
55
KillShellResult,
66
} from "@features/logs/tools/types";
77
import { Box } from "@radix-ui/themes";
8+
import { parseKillShellResult } from "@utils/tool-results";
89

910
type KillShellToolViewProps = BaseToolViewProps<
1011
KillShellArgs,
1112
string | KillShellResult
1213
>;
1314

1415
export function KillShellToolView({ result }: KillShellToolViewProps) {
15-
let success = false;
16-
let message = "";
17-
18-
if (result) {
19-
if (typeof result === "string") {
20-
message = result;
21-
success = result.includes("killed") || result.includes("terminated");
22-
} else if (typeof result === "object") {
23-
success = result.success || false;
24-
message = result.message || "";
25-
}
26-
}
16+
const { success, message } = parseKillShellResult(result);
2717

2818
return (
2919
<Box>

src/renderer/features/logs/tools/WebSearchToolView.tsx

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type {
77
WebSearchResultItem,
88
} from "@features/logs/tools/types";
99
import { Box, Code } from "@radix-ui/themes";
10+
import { parseWebSearchResult } from "@utils/tool-results";
1011

1112
type WebSearchToolViewProps = BaseToolViewProps<
1213
WebSearchArgs,
@@ -16,20 +17,7 @@ type WebSearchToolViewProps = BaseToolViewProps<
1617
export function WebSearchToolView({ args, result }: WebSearchToolViewProps) {
1718
const { allowed_domains, blocked_domains } = args;
1819

19-
// Parse result
20-
let results: WebSearchResultItem[] = [];
21-
if (result) {
22-
if (typeof result === "string") {
23-
try {
24-
const parsed = JSON.parse(result);
25-
results = parsed.results || [];
26-
} catch {
27-
// Result is just text
28-
}
29-
} else if (result && typeof result === "object" && "results" in result) {
30-
results = result.results || [];
31-
}
32-
}
20+
const results = parseWebSearchResult<WebSearchResultItem>(result);
3321

3422
return (
3523
<Box>

src/renderer/utils/tool-results.ts

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,90 @@ export function truncateList(
3232

3333
return truncated.join(separator);
3434
}
35+
36+
function parseToolResult<TResult>(
37+
result: string | Partial<TResult> | undefined,
38+
defaults: TResult,
39+
stringParser?: (str: string) => Partial<TResult>,
40+
): TResult {
41+
if (!result) {
42+
return defaults;
43+
}
44+
45+
if (typeof result === "string") {
46+
const stringResult =
47+
stringParser?.(result) ??
48+
({ stdout: result } as unknown as Partial<TResult>);
49+
return { ...defaults, ...stringResult };
50+
}
51+
52+
return { ...defaults, ...result };
53+
}
54+
55+
export interface ShellResult {
56+
stdout: string;
57+
stderr: string;
58+
exitCode?: number;
59+
}
60+
61+
export function parseShellResult(
62+
result: string | Partial<ShellResult> | undefined,
63+
): ShellResult {
64+
return parseToolResult(result, { stdout: "", stderr: "" });
65+
}
66+
67+
export interface ShellStatusResult {
68+
stdout: string;
69+
stderr: string;
70+
status?: string;
71+
}
72+
73+
export function parseShellStatusResult(
74+
result: string | Partial<ShellStatusResult> | undefined,
75+
): ShellStatusResult {
76+
return parseToolResult(result, { stdout: "", stderr: "" });
77+
}
78+
79+
export interface KillShellResult {
80+
success: boolean;
81+
message: string;
82+
}
83+
84+
export function parseKillShellResult(
85+
result: string | Partial<KillShellResult> | undefined,
86+
): KillShellResult {
87+
return parseToolResult(result, { success: false, message: "" }, (str) => ({
88+
success: str.includes("killed") || str.includes("terminated"),
89+
message: str,
90+
}));
91+
}
92+
93+
export interface GrepResultParsed {
94+
matches: string[];
95+
count?: number;
96+
}
97+
98+
export function parseGrepResult(
99+
result: string | Partial<GrepResultParsed> | undefined,
100+
): GrepResultParsed {
101+
return parseToolResult(result, { matches: [] }, (str) => ({
102+
matches: parseStringListResult(str),
103+
}));
104+
}
105+
106+
export function parseWebSearchResult<T>(
107+
result: string | { results?: T[] } | undefined,
108+
): T[] {
109+
if (!result) return [];
110+
111+
if (typeof result === "string") {
112+
try {
113+
const parsed = JSON.parse(result);
114+
return parsed.results || [];
115+
} catch {
116+
return [];
117+
}
118+
}
119+
120+
return result.results || [];
121+
}

0 commit comments

Comments
 (0)