@@ -9,7 +9,11 @@ import { Box, Text } from 'ink';
99import { theme } from '../semantic-colors.js' ;
1010import { useConfig } from '../contexts/ConfigContext.js' ;
1111import { ToolConfirmationMessage } from './messages/ToolConfirmationMessage.js' ;
12- import { ToolStatusIndicator , ToolInfo } from './messages/ToolShared.js' ;
12+ import {
13+ isShellTool ,
14+ ToolStatusIndicator ,
15+ ToolInfo ,
16+ } from './messages/ToolShared.js' ;
1317import { useUIState } from '../contexts/UIStateContext.js' ;
1418import type { ConfirmingToolState } from '../hooks/useConfirmingTool.js' ;
1519import { StickyHeader } from './StickyHeader.js' ;
@@ -31,6 +35,16 @@ function getConfirmationHeader(
3135 return headers [ details . type ] ?? 'Action Required' ;
3236}
3337
38+ function getConfirmationLabel (
39+ toolName : string ,
40+ details : SerializableConfirmationDetails | undefined ,
41+ ) : string {
42+ if ( details ?. type === 'ask_user' ) return 'Questions' ;
43+ if ( details ?. type === 'exit_plan_mode' ) return 'Implementation' ;
44+ if ( isShellTool ( toolName ) ) return 'Shell' ;
45+ return toolName ;
46+ }
47+
3448interface ToolConfirmationQueueProps {
3549 confirmingTool : ConfirmingToolState ;
3650}
@@ -58,22 +72,78 @@ export const ToolConfirmationQueue: React.FC<ToolConfirmationQueueProps> = ({
5872 ? Math . max ( uiAvailableHeight , 4 )
5973 : Math . floor ( terminalHeight * 0.5 ) ;
6074
75+ const isShell = isShellTool ( tool . name ) ;
76+ const isEdit = tool . confirmationDetails ?. type === 'edit' ;
77+
78+ if ( isShell || isEdit ) {
79+ // Use the new simplified layout for Shell and Edit tools
80+ const borderColor = theme . border . default ;
81+ const availableContentHeight = constrainHeight
82+ ? Math . max ( maxHeight - 3 , 4 )
83+ : undefined ;
84+
85+ const toolLabel = getConfirmationLabel ( tool . name , tool . confirmationDetails ) ;
86+
87+ return (
88+ < Box
89+ flexDirection = "column"
90+ width = { mainAreaWidth }
91+ flexShrink = { 0 }
92+ borderStyle = "round"
93+ borderColor = { borderColor }
94+ paddingX = { 1 }
95+ >
96+ { /* Header Line */ }
97+ < Box justifyContent = "space-between" marginBottom = { 0 } >
98+ < Box flexDirection = "row" flexShrink = { 1 } overflow = "hidden" >
99+ < Text color = { theme . status . warning } bold >
100+ ? { toolLabel }
101+ { ! isEdit && ! ! tool . description && ' ' }
102+ </ Text >
103+ { ! isEdit && ! ! tool . description && (
104+ < Box flexShrink = { 1 } overflow = "hidden" >
105+ < Text color = { theme . text . primary } wrap = "truncate-end" >
106+ { tool . description }
107+ </ Text >
108+ </ Box >
109+ ) }
110+ </ Box >
111+ { total > 1 && (
112+ < Text color = { theme . text . secondary } >
113+ { index } of { total }
114+ </ Text >
115+ ) }
116+ </ Box >
117+
118+ { /* Interactive Area */ }
119+ < Box flexDirection = "column" >
120+ < ToolConfirmationMessage
121+ callId = { tool . callId }
122+ confirmationDetails = { tool . confirmationDetails }
123+ config = { config }
124+ getPreferredEditor = { getPreferredEditor }
125+ terminalWidth = { mainAreaWidth - 4 } // Adjust for parent border/padding
126+ availableTerminalHeight = { availableContentHeight }
127+ toolName = { tool . name }
128+ isFocused = { true }
129+ />
130+ </ Box >
131+ </ Box >
132+ ) ;
133+ }
134+
135+ // Restore original logic for other tools
61136 const isRoutine =
62137 tool . confirmationDetails ?. type === 'ask_user' ||
63138 tool . confirmationDetails ?. type === 'exit_plan_mode' ;
64139 const borderColor = isRoutine ? theme . status . success : theme . status . warning ;
65140 const hideToolIdentity = isRoutine ;
66141
67- // ToolConfirmationMessage needs to know the height available for its OWN content.
68- // We subtract the lines used by the Queue wrapper:
69- // - 2 lines for the rounded border
70- // - 2 lines for the Header (text + margin)
71- // - 2 lines for Tool Identity (text + margin)
72142 const availableContentHeight = constrainHeight
73143 ? Math . max ( maxHeight - ( hideToolIdentity ? 4 : 6 ) , 4 )
74144 : undefined ;
75145
76- const content = (
146+ return (
77147 < Box flexDirection = "column" width = { mainAreaWidth } flexShrink = { 0 } >
78148 < StickyHeader
79149 width = { mainAreaWidth }
@@ -122,18 +192,14 @@ export const ToolConfirmationQueue: React.FC<ToolConfirmationQueueProps> = ({
122192 paddingX = { 1 }
123193 flexDirection = "column"
124194 >
125- { /* Interactive Area */ }
126- { /*
127- Note: We force isFocused={true} because if this component is rendered,
128- it effectively acts as a modal over the shell/composer.
129- */ }
130195 < ToolConfirmationMessage
131196 callId = { tool . callId }
132197 confirmationDetails = { tool . confirmationDetails }
133198 config = { config }
134199 getPreferredEditor = { getPreferredEditor }
135200 terminalWidth = { mainAreaWidth - 4 } // Adjust for parent border/padding
136201 availableTerminalHeight = { availableContentHeight }
202+ toolName = { tool . name }
137203 isFocused = { true }
138204 />
139205 </ Box >
@@ -149,6 +215,4 @@ export const ToolConfirmationQueue: React.FC<ToolConfirmationQueueProps> = ({
149215 />
150216 </ Box >
151217 ) ;
152-
153- return content ;
154218} ;
0 commit comments