@@ -39,6 +39,7 @@ import { RunInTerminalTool, type IRunInTerminalInputParams } from '../../browser
3939import { ShellIntegrationQuality } from '../../browser/toolTerminalCreator.js' ;
4040import { terminalChatAgentToolsConfiguration , TerminalChatAgentToolsSettingId } from '../../common/terminalChatAgentToolsConfiguration.js' ;
4141import { TerminalChatService } from '../../../chat/browser/terminalChatService.js' ;
42+ import type { IMarkdownString } from '../../../../../../base/common/htmlContent.js' ;
4243
4344class TestRunInTerminalTool extends RunInTerminalTool {
4445 protected override _osBackend : Promise < OperatingSystem > = Promise . resolve ( OperatingSystem . Windows ) ;
@@ -1213,4 +1214,97 @@ suite('RunInTerminalTool', () => {
12131214 } ) ;
12141215 } ) ;
12151216 } ) ;
1217+
1218+ suite ( 'denial info in disclaimers' , ( ) => {
1219+ function getDisclaimerValue ( disclaimer : string | IMarkdownString | undefined ) : string | undefined {
1220+ if ( ! disclaimer ) {
1221+ return undefined ;
1222+ }
1223+ return typeof disclaimer === 'string' ? disclaimer : disclaimer . value ;
1224+ }
1225+
1226+ test ( 'should include denial reason in disclaimer when command is denied by rule' , async ( ) => {
1227+ setAutoApprove ( {
1228+ npm : { approve : false }
1229+ } ) ;
1230+ const result = await executeToolTest ( {
1231+ command : 'npm run build' ,
1232+ explanation : 'Build the project'
1233+ } ) ;
1234+
1235+ assertConfirmationRequired ( result , 'Run `bash` command?' ) ;
1236+ const disclaimerValue = getDisclaimerValue ( result ?. confirmationMessages ?. disclaimer ) ;
1237+ ok ( disclaimerValue , 'Expected disclaimer to be defined' ) ;
1238+ ok ( disclaimerValue . includes ( 'denied' ) , 'Expected disclaimer to mention denial' ) ;
1239+ ok ( disclaimerValue . includes ( 'npm' ) , 'Expected disclaimer to mention the denied rule' ) ;
1240+ } ) ;
1241+
1242+ test ( 'should include link to settings in denial disclaimer' , async ( ) => {
1243+ setAutoApprove ( {
1244+ rm : { approve : false }
1245+ } ) ;
1246+ const result = await executeToolTest ( {
1247+ command : 'rm -rf temp' ,
1248+ explanation : 'Remove temp folder'
1249+ } ) ;
1250+
1251+ assertConfirmationRequired ( result , 'Run `bash` command?' ) ;
1252+ ok ( result ?. confirmationMessages ?. disclaimer , 'Expected disclaimer to be defined' ) ;
1253+ // The disclaimer should have trusted commands enabled for settings links
1254+ const disclaimer = result . confirmationMessages . disclaimer ;
1255+ ok ( typeof disclaimer !== 'string' && disclaimer . isTrusted , 'Expected disclaimer to be trusted for command links' ) ;
1256+ } ) ;
1257+
1258+ test ( 'should include denial reason for multiple denied sub-commands' , async ( ) => {
1259+ setAutoApprove ( {
1260+ rm : { approve : false } ,
1261+ sudo : { approve : false }
1262+ } ) ;
1263+ const result = await executeToolTest ( {
1264+ command : 'sudo rm -rf /' ,
1265+ explanation : 'Dangerous command'
1266+ } ) ;
1267+
1268+ assertConfirmationRequired ( result , 'Run `bash` command?' ) ;
1269+ const disclaimerValue = getDisclaimerValue ( result ?. confirmationMessages ?. disclaimer ) ;
1270+ ok ( disclaimerValue , 'Expected disclaimer to be defined' ) ;
1271+ ok ( disclaimerValue . includes ( 'denied' ) , 'Expected disclaimer to mention denial' ) ;
1272+ } ) ;
1273+
1274+ test ( 'should not include denial info when auto-approve is disabled' , async ( ) => {
1275+ setConfig ( TerminalChatAgentToolsSettingId . EnableAutoApprove , false ) ;
1276+ setAutoApprove ( {
1277+ npm : { approve : false }
1278+ } ) ;
1279+ const result = await executeToolTest ( {
1280+ command : 'npm run build' ,
1281+ explanation : 'Build the project'
1282+ } ) ;
1283+
1284+ assertConfirmationRequired ( result , 'Run `bash` command?' ) ;
1285+ // When auto-approve is disabled, there should be no denial-related disclaimer
1286+ const disclaimerValue = getDisclaimerValue ( result ?. confirmationMessages ?. disclaimer ) ;
1287+ if ( disclaimerValue ) {
1288+ ok ( ! disclaimerValue . includes ( 'denied' ) , 'Should not mention denial when auto-approve is disabled' ) ;
1289+ }
1290+ } ) ;
1291+
1292+ test ( 'should not include denial info for commands that are simply not approved' , async ( ) => {
1293+ // Command is not in auto-approve list, but not explicitly denied
1294+ setAutoApprove ( {
1295+ echo : true
1296+ } ) ;
1297+ const result = await executeToolTest ( {
1298+ command : 'npm run build' ,
1299+ explanation : 'Build the project'
1300+ } ) ;
1301+
1302+ assertConfirmationRequired ( result , 'Run `bash` command?' ) ;
1303+ // There should be no denial disclaimer since npm is not explicitly denied
1304+ const disclaimerValue = getDisclaimerValue ( result ?. confirmationMessages ?. disclaimer ) ;
1305+ if ( disclaimerValue ) {
1306+ ok ( ! disclaimerValue . includes ( 'denied' ) , 'Should not mention denial for non-denied commands' ) ;
1307+ }
1308+ } ) ;
1309+ } ) ;
12161310} ) ;
0 commit comments