-
Notifications
You must be signed in to change notification settings - Fork 108
Expand file tree
/
Copy pathBashBackgroundListToolCall.tsx
More file actions
125 lines (117 loc) · 3.89 KB
/
BashBackgroundListToolCall.tsx
File metadata and controls
125 lines (117 loc) · 3.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import React from "react";
import type {
BashBackgroundListArgs,
BashBackgroundListResult,
BashBackgroundListProcess,
} from "@/common/types/tools";
import {
ToolContainer,
ToolHeader,
ExpandIcon,
StatusIndicator,
ToolDetails,
DetailSection,
LoadingDots,
ToolIcon,
ErrorBox,
OutputPaths,
} from "./shared/ToolPrimitives";
import {
useToolExpansion,
getStatusDisplay,
formatDuration,
type ToolStatus,
} from "./shared/toolUtils";
import { cn } from "@/common/lib/utils";
interface BashBackgroundListToolCallProps {
args: BashBackgroundListArgs;
result?: BashBackgroundListResult;
status?: ToolStatus;
}
function getProcessStatusStyle(status: BashBackgroundListProcess["status"]) {
switch (status) {
case "running":
return "bg-success text-on-success";
case "exited":
return "bg-[hsl(0,0%,40%)] text-white";
case "killed":
case "failed":
return "bg-danger text-on-danger";
}
}
export const BashBackgroundListToolCall: React.FC<BashBackgroundListToolCallProps> = ({
args: _args,
result,
status = "pending",
}) => {
const { expanded, toggleExpanded } = useToolExpansion(false);
const processes = result?.success ? result.processes : [];
const runningCount = processes.filter((p) => p.status === "running").length;
return (
<ToolContainer expanded={expanded}>
<ToolHeader onClick={toggleExpanded}>
<ExpandIcon expanded={expanded}>▶</ExpandIcon>
<ToolIcon emoji="📋" toolName="bash_background_list" />
<span className="text-text-secondary">
{result?.success
? runningCount === 0
? "No background processes"
: `${runningCount} background process${runningCount !== 1 ? "es" : ""}`
: "Listing background processes"}
</span>
<StatusIndicator status={status}>{getStatusDisplay(status)}</StatusIndicator>
</ToolHeader>
{expanded && (
<ToolDetails>
{result?.success === false && (
<DetailSection>
<ErrorBox>{result.error}</ErrorBox>
</DetailSection>
)}
{result?.success && processes.length > 0 && (
<DetailSection>
<div className="space-y-2">
{processes.map((proc) => (
<div
key={proc.display_name ?? proc.process_id}
className="bg-code-bg rounded px-2 py-1.5 text-[11px]"
>
<div className="mb-1 flex items-center gap-2">
<span className="text-text font-mono">
{proc.display_name ?? proc.process_id}
</span>
<span
className={cn(
"inline-block rounded px-1.5 py-0.5 text-[9px] font-medium uppercase",
getProcessStatusStyle(proc.status)
)}
>
{proc.status}
{proc.exitCode !== undefined && ` (${proc.exitCode})`}
</span>
<span className="text-text-secondary ml-auto">
{formatDuration(proc.uptime_ms)}
</span>
</div>
<div className="text-text-secondary truncate font-mono" title={proc.script}>
{proc.script}
</div>
<OutputPaths stdout={proc.stdout_path} stderr={proc.stderr_path} compact />
</div>
))}
</div>
</DetailSection>
)}
{status === "executing" && !result && (
<DetailSection>
<div className="text-[11px]">
Listing processes
<LoadingDots />
</div>
</DetailSection>
)}
</ToolDetails>
)}
</ToolContainer>
);
};