@@ -377,9 +377,6 @@ const pendingAskUser = new Map();
377377const ASK_USER_TIMEOUT_MS = 5 * 60 * 1000 ; // 5 minutes
378378const ASK_USER_SECRET = require ( 'crypto' ) . randomBytes ( 16 ) . toString ( 'hex' ) ;
379379
380- // ─── CLI Ask Tool ──────────────────────────────────────────────────────────
381- // Pending CLI Ask tool questions: requestId → { sessionId, ws, resolved }
382- let pendingCliAsks = new Map ( ) ;
383380
384381// ─── Notify User (Internal MCP) ──────────────────────────────────────────
385382const NOTIFY_SECRET = require ( 'crypto' ) . randomBytes ( 16 ) . toString ( 'hex' ) ;
@@ -802,35 +799,13 @@ function runCliSingle(p) {
802799 try { stmts . addMsg . run ( sessionId , 'assistant' , 'tool' , ( inp || '' ) . substring ( 0 , 10000 ) , name , null , null , null ) ; } catch { }
803800 return ;
804801 }
805- // Debug: log all tool names to find Ask tool
806- if ( name . toLowerCase ( ) . includes ( 'ask' ) || name . toLowerCase ( ) . includes ( 'question' ) ) {
807- log . info ( 'Ask-like tool detected' , { name, inputPreview : ( inp || '' ) . substring ( 0 , 200 ) } ) ;
808- }
809- // Handle Ask tool from Claude Code CLI - render as interactive question card
810- // Match: "Ask", "mcp__Ask", or tools with "ask" in name (but not ask_user/notify_user which are already filtered)
811- if ( name === 'Ask' || name === 'mcp__Ask' || ( name . toLowerCase ( ) . includes ( 'ask' ) && ! name . includes ( 'ask_user' ) ) ) {
812- try {
813- const askData = typeof inp === 'string' ? JSON . parse ( inp ) : inp ;
814- // Generate a unique request ID for this ask
815- const askRequestId = `ask-${ Date . now ( ) } -${ Math . random ( ) . toString ( 36 ) . slice ( 2 , 8 ) } ` ;
816- // Store pending ask for response handling
817- if ( ! pendingCliAsks ) pendingCliAsks = new Map ( ) ;
818- pendingCliAsks . set ( askRequestId , { sessionId, ws, resolved : false } ) ;
819- // Send to client for rendering
820- ws . send ( JSON . stringify ( {
821- type : 'ask_tool' ,
822- requestId : askRequestId ,
823- question : askData . question || askData . prompt || '' ,
824- options : askData . options || [ ] ,
825- tabId
826- } ) ) ;
827- } catch ( e ) {
828- // If parsing fails, show as regular tool
829- ws . send ( JSON . stringify ( { type :'tool' , tool :name , input :( inp || '' ) . substring ( 0 , 600 ) , ...( tabId ? { tabId } : { } ) } ) ) ;
830- }
831- } else {
832- ws . send ( JSON . stringify ( { type :'tool' , tool :name , input :( inp || '' ) . substring ( 0 , 600 ) , ...( tabId ? { tabId } : { } ) } ) ) ;
802+ // AskUserQuestion is Claude CLI's internal tool — handled by the CLI itself
803+ // (auto-resolved with --dangerously-skip-permissions). Don't show to web UI user.
804+ if ( name === 'AskUserQuestion' ) {
805+ try { stmts . addMsg . run ( sessionId , 'assistant' , 'tool' , ( inp || '' ) . substring ( 0 , 10000 ) , name , null , null , null ) ; } catch { }
806+ return ;
833807 }
808+ ws . send ( JSON . stringify ( { type :'tool' , tool :name , input :( inp || '' ) . substring ( 0 , 600 ) , ...( tabId ? { tabId } : { } ) } ) ) ;
834809 try { stmts . addMsg . run ( sessionId , 'assistant' , 'tool' , ( inp || '' ) . substring ( 0 , 10000 ) , name , null , null , null ) ; } catch { }
835810 } )
836811 . onSessionId ( sid => { newCid = sid ; try { stmts . updateClaudeId . run ( sid , sessionId ) ; } catch { } } ) // persist early so open-terminal works during active chat
@@ -1108,70 +1083,6 @@ app.get('/api/health', (_, res) => {
11081083} ) ;
11091084
11101085// Test endpoint to simulate Ask tool (for UI testing)
1111- app . post ( '/api/test/ask-tool' , express . json ( ) , ( req , res ) => {
1112- const { sessionId, question, options } = req . body ;
1113- if ( ! sessionId ) return res . status ( 400 ) . json ( { error : 'sessionId required' } ) ;
1114-
1115- // Find active WebSocket for this session
1116- const task = activeTasks . get ( sessionId ) ;
1117- const ws = task ?. proxy ;
1118- if ( ! ws ) return res . status ( 404 ) . json ( { error : 'No active session' } ) ;
1119-
1120- const askRequestId = `ask-${ Date . now ( ) } -${ Math . random ( ) . toString ( 36 ) . slice ( 2 , 8 ) } ` ;
1121-
1122- ws . send ( JSON . stringify ( {
1123- type : 'ask_tool' ,
1124- requestId : askRequestId ,
1125- question : question || 'Which option do you prefer?' ,
1126- options : options || [ 'Option A' , 'Option B' , 'Option C' ] ,
1127- tabId : sessionId
1128- } ) ) ;
1129-
1130- res . json ( { ok : true , requestId : askRequestId } ) ;
1131- } ) ;
1132-
1133- // Test endpoint to simulate MCP ask_user (for UI testing)
1134- app . post ( '/api/test/ask-user' , express . json ( ) , ( req , res ) => {
1135- const { sessionId, question, questions, options, inputType } = req . body ;
1136- if ( ! sessionId ) return res . status ( 400 ) . json ( { error : 'sessionId required' } ) ;
1137-
1138- // Find active WebSocket for this session
1139- const task = activeTasks . get ( sessionId ) ;
1140- const ws = task ?. proxy ;
1141- if ( ! ws ) return res . status ( 404 ) . json ( { error : 'No active session' } ) ;
1142-
1143- const requestId = crypto . randomUUID ( ) ;
1144-
1145- // Build payload matching MCP ask_user format
1146- const payload = {
1147- type : 'ask_user' ,
1148- requestId,
1149- tabId : sessionId
1150- } ;
1151-
1152- // Single question format
1153- if ( question ) {
1154- payload . question = question ;
1155- if ( options ) payload . options = options ;
1156- if ( inputType ) payload . inputType = inputType ;
1157- }
1158-
1159- // Multiple questions format (paginated)
1160- if ( questions && Array . isArray ( questions ) ) {
1161- payload . questions = questions ;
1162- }
1163-
1164- // Default if nothing specified
1165- if ( ! question && ! questions ) {
1166- payload . question = 'What would you like to do?' ;
1167- payload . options = [ 'Option A' , 'Option B' , 'Option C' ] ;
1168- payload . inputType = 'single_choice' ;
1169- }
1170-
1171- ws . send ( JSON . stringify ( payload ) ) ;
1172- res . json ( { ok : true , requestId, payload } ) ;
1173- } ) ;
1174-
11751086// Stats
11761087app . get ( '/api/stats' , ( req , res ) => {
11771088 const sessionId = req . query . session_id || null ;
@@ -2245,18 +2156,6 @@ wss.on('connection', (ws) => {
22452156 return ;
22462157 }
22472158
2248- // ─── CLI Ask Tool responses ───────────────────────────────────────────────
2249- if ( msg . type === 'ask_tool_response' ) {
2250- const entry = pendingCliAsks . get ( msg . requestId ) ;
2251- if ( entry && ! entry . resolved ) {
2252- entry . resolved = true ;
2253- pendingCliAsks . delete ( msg . requestId ) ;
2254- // The answer will be sent as the next user message in the chat
2255- // This is handled client-side by adding the answer to the input
2256- }
2257- return ;
2258- }
2259-
22602159 if ( msg . type === 'new_session' ) {
22612160 ws . _queue = [ ] ;
22622161 if ( ws . _abort ) ws . _abort . abort ( ) ;
0 commit comments