@@ -993,15 +993,50 @@ fn maybe_enforce_permission_check(
993993
994994#[ allow( clippy:: needless_pass_by_value) ]
995995fn run_ask_user_question ( input : AskUserQuestionInput ) -> Result < String , String > {
996- let mut result = json ! ( {
997- "question" : input. question,
998- "status" : "pending" ,
999- "message" : "Waiting for user response"
1000- } ) ;
1001- if let Some ( options) = & input. options {
1002- result[ "options" ] = json ! ( options) ;
996+ use std:: io:: { self , BufRead , Write } ;
997+
998+ // Display the question to the user via stdout
999+ let stdout = io:: stdout ( ) ;
1000+ let stdin = io:: stdin ( ) ;
1001+ let mut out = stdout. lock ( ) ;
1002+
1003+ writeln ! ( out, "\n [Question] {}" , input. question) . map_err ( |e| e. to_string ( ) ) ?;
1004+
1005+ if let Some ( ref options) = input. options {
1006+ for ( i, option) in options. iter ( ) . enumerate ( ) {
1007+ writeln ! ( out, " {}. {}" , i + 1 , option) . map_err ( |e| e. to_string ( ) ) ?;
1008+ }
1009+ write ! ( out, "Enter choice (1-{}): " , options. len( ) ) . map_err ( |e| e. to_string ( ) ) ?;
1010+ } else {
1011+ write ! ( out, "Your answer: " ) . map_err ( |e| e. to_string ( ) ) ?;
10031012 }
1004- to_pretty_json ( result)
1013+ out. flush ( ) . map_err ( |e| e. to_string ( ) ) ?;
1014+
1015+ // Read user response from stdin
1016+ let mut response = String :: new ( ) ;
1017+ stdin. lock ( ) . read_line ( & mut response) . map_err ( |e| e. to_string ( ) ) ?;
1018+ let response = response. trim ( ) . to_string ( ) ;
1019+
1020+ // If options were provided, resolve the numeric choice
1021+ let answer = if let Some ( ref options) = input. options {
1022+ if let Ok ( idx) = response. parse :: < usize > ( ) {
1023+ if idx >= 1 && idx <= options. len ( ) {
1024+ options[ idx - 1 ] . clone ( )
1025+ } else {
1026+ response. clone ( )
1027+ }
1028+ } else {
1029+ response. clone ( )
1030+ }
1031+ } else {
1032+ response. clone ( )
1033+ } ;
1034+
1035+ to_pretty_json ( json ! ( {
1036+ "question" : input. question,
1037+ "answer" : answer,
1038+ "status" : "answered"
1039+ } ) )
10051040}
10061041
10071042#[ allow( clippy:: needless_pass_by_value) ]
@@ -1275,14 +1310,62 @@ fn run_mcp_auth(input: McpAuthInput) -> Result<String, String> {
12751310
12761311#[ allow( clippy:: needless_pass_by_value) ]
12771312fn run_remote_trigger ( input : RemoteTriggerInput ) -> Result < String , String > {
1278- to_pretty_json ( json ! ( {
1279- "url" : input. url,
1280- "method" : input. method. unwrap_or_else( || "GET" . to_string( ) ) ,
1281- "headers" : input. headers,
1282- "body" : input. body,
1283- "status" : "triggered" ,
1284- "message" : "Remote trigger stub response"
1285- } ) )
1313+ let method = input. method . unwrap_or_else ( || "GET" . to_string ( ) ) ;
1314+ let client = Client :: new ( ) ;
1315+
1316+ let mut request = match method. to_uppercase ( ) . as_str ( ) {
1317+ "GET" => client. get ( & input. url ) ,
1318+ "POST" => client. post ( & input. url ) ,
1319+ "PUT" => client. put ( & input. url ) ,
1320+ "DELETE" => client. delete ( & input. url ) ,
1321+ "PATCH" => client. patch ( & input. url ) ,
1322+ "HEAD" => client. head ( & input. url ) ,
1323+ other => return Err ( format ! ( "unsupported HTTP method: {other}" ) ) ,
1324+ } ;
1325+
1326+ // Apply custom headers
1327+ if let Some ( ref headers) = input. headers {
1328+ if let Some ( obj) = headers. as_object ( ) {
1329+ for ( key, value) in obj {
1330+ if let Some ( val) = value. as_str ( ) {
1331+ request = request. header ( key. as_str ( ) , val) ;
1332+ }
1333+ }
1334+ }
1335+ }
1336+
1337+ // Apply body
1338+ if let Some ( ref body) = input. body {
1339+ request = request. body ( body. clone ( ) ) ;
1340+ }
1341+
1342+ // Execute with a 30-second timeout
1343+ let request = request. timeout ( Duration :: from_secs ( 30 ) ) ;
1344+
1345+ match request. send ( ) {
1346+ Ok ( response) => {
1347+ let status = response. status ( ) . as_u16 ( ) ;
1348+ let body = response. text ( ) . unwrap_or_default ( ) ;
1349+ let truncated_body = if body. len ( ) > 8192 {
1350+ format ! ( "{}\n \n [response truncated — {} bytes total]" , & body[ ..8192 ] , body. len( ) )
1351+ } else {
1352+ body
1353+ } ;
1354+ to_pretty_json ( json ! ( {
1355+ "url" : input. url,
1356+ "method" : method,
1357+ "status_code" : status,
1358+ "body" : truncated_body,
1359+ "success" : status >= 200 && status < 300
1360+ } ) )
1361+ }
1362+ Err ( e) => to_pretty_json ( json ! ( {
1363+ "url" : input. url,
1364+ "method" : method,
1365+ "error" : e. to_string( ) ,
1366+ "success" : false
1367+ } ) ) ,
1368+ }
12861369}
12871370
12881371#[ allow( clippy:: needless_pass_by_value) ]
0 commit comments