@@ -11,7 +11,6 @@ import {
1111 DetailSection ,
1212 DetailLabel ,
1313 DetailContent ,
14- LoadingDots ,
1514 ToolIcon ,
1615 ErrorBox ,
1716 ExitCodeBadge ,
@@ -60,31 +59,24 @@ export const BashToolCall: React.FC<BashToolCallProps> = ({
6059
6160 const liveOutput = useBashToolLiveOutput ( workspaceId , toolCallId ) ;
6261
63- const stdoutRef = useRef < HTMLPreElement > ( null ) ;
64- const stderrRef = useRef < HTMLPreElement > ( null ) ;
65- const stdoutPinnedRef = useRef ( true ) ;
66- const stderrPinnedRef = useRef ( true ) ;
62+ const outputRef = useRef < HTMLPreElement > ( null ) ;
63+ const outputPinnedRef = useRef ( true ) ;
6764
68- const updatePinned = ( el : HTMLPreElement , pinnedRef : React . MutableRefObject < boolean > ) => {
65+ const updatePinned = ( el : HTMLPreElement ) => {
6966 const distanceToBottom = el . scrollHeight - el . scrollTop - el . clientHeight ;
70- pinnedRef . current = distanceToBottom < 40 ;
67+ outputPinnedRef . current = distanceToBottom < 40 ;
7168 } ;
7269
73- useEffect ( ( ) => {
74- const el = stdoutRef . current ;
75- if ( ! el ) return ;
76- if ( stdoutPinnedRef . current ) {
77- el . scrollTop = el . scrollHeight ;
78- }
79- } , [ liveOutput ?. stdout ] ) ;
70+ const liveOutputView = liveOutput ?? EMPTY_LIVE_OUTPUT ;
71+ const combinedLiveOutput = liveOutputView . stdout + liveOutputView . stderr ;
8072
8173 useEffect ( ( ) => {
82- const el = stderrRef . current ;
74+ const el = outputRef . current ;
8375 if ( ! el ) return ;
84- if ( stderrPinnedRef . current ) {
76+ if ( outputPinnedRef . current ) {
8577 el . scrollTop = el . scrollHeight ;
8678 }
87- } , [ liveOutput ?. stderr ] ) ;
79+ } , [ combinedLiveOutput ] ) ;
8880 const startTimeRef = useRef < number > ( startedAt ?? Date . now ( ) ) ;
8981
9082 // Track elapsed time for pending/executing status
@@ -115,13 +107,9 @@ export const BashToolCall: React.FC<BashToolCallProps> = ({
115107
116108 const resultHasOutput = typeof ( result as { output ?: unknown } | undefined ) ?. output === "string" ;
117109
118- const hasLiveOutputSource = Boolean ( workspaceId && toolCallId ) ;
119110 const showLiveOutput =
120- ! isBackground &&
121- hasLiveOutputSource &&
122- ( status === "executing" || ( Boolean ( liveOutput ) && ! resultHasOutput ) ) ;
111+ ! isBackground && ( status === "executing" || ( Boolean ( liveOutput ) && ! resultHasOutput ) ) ;
123112
124- const liveOutputView = liveOutput ?? EMPTY_LIVE_OUTPUT ;
125113 const liveLabelSuffix = status === "executing" ? " (live)" : " (tail)" ;
126114
127115 return (
@@ -187,6 +175,11 @@ export const BashToolCall: React.FC<BashToolCallProps> = ({
187175
188176 { expanded && (
189177 < ToolDetails >
178+ < DetailSection >
179+ < DetailLabel > Script</ DetailLabel >
180+ < DetailContent className = "px-2 py-1.5" > { args . script } </ DetailContent >
181+ </ DetailSection >
182+
190183 { showLiveOutput && (
191184 < >
192185 { liveOutputView . truncated && (
@@ -196,38 +189,20 @@ export const BashToolCall: React.FC<BashToolCallProps> = ({
196189 ) }
197190
198191 < DetailSection >
199- < DetailLabel > { `Stdout${ liveLabelSuffix } ` } </ DetailLabel >
200- < DetailContent
201- ref = { stdoutRef }
202- onScroll = { ( e ) => updatePinned ( e . currentTarget , stdoutPinnedRef ) }
203- className = { cn (
204- "px-2 py-1.5" ,
205- liveOutputView . stdout . length === 0 && "text-muted italic"
206- ) }
207- >
208- { liveOutputView . stdout . length > 0 ? liveOutputView . stdout : "No output yet" }
209- </ DetailContent >
210- </ DetailSection >
211-
212- < DetailSection >
213- < DetailLabel > { `Stderr${ liveLabelSuffix } ` } </ DetailLabel >
192+ < DetailLabel > { `Output${ liveLabelSuffix } ` } </ DetailLabel >
214193 < DetailContent
215- ref = { stderrRef }
216- onScroll = { ( e ) => updatePinned ( e . currentTarget , stderrPinnedRef ) }
194+ ref = { outputRef }
195+ onScroll = { ( e ) => updatePinned ( e . currentTarget ) }
217196 className = { cn (
218197 "px-2 py-1.5" ,
219- liveOutputView . stderr . length === 0 && "text-muted italic"
198+ combinedLiveOutput . length === 0 && "text-muted italic"
220199 ) }
221200 >
222- { liveOutputView . stderr . length > 0 ? liveOutputView . stderr : "No output yet" }
201+ { combinedLiveOutput . length > 0 ? combinedLiveOutput : "No output yet" }
223202 </ DetailContent >
224203 </ DetailSection >
225204 </ >
226205 ) }
227- < DetailSection >
228- < DetailLabel > Script</ DetailLabel >
229- < DetailContent className = "px-2 py-1.5" > { args . script } </ DetailContent >
230- </ DetailSection >
231206
232207 { result && (
233208 < >
@@ -258,15 +233,6 @@ export const BashToolCall: React.FC<BashToolCallProps> = ({
258233 ) }
259234 </ >
260235 ) }
261-
262- { status === "executing" && ! result && ! showLiveOutput && (
263- < DetailSection >
264- < DetailContent className = "px-2 py-1.5" >
265- Waiting for result
266- < LoadingDots />
267- </ DetailContent >
268- </ DetailSection >
269- ) }
270236 </ ToolDetails >
271237 ) }
272238 </ ToolContainer >
0 commit comments