const {generateApprovalObserverScript} = require('../out/observer-script'); let s = generateApprovalObserverScript(18080); // 1. SYNTAX CHECK try { new Function(s); console.log('[1] SYNTAX: OK'); } catch(e) { console.log('[1] SYNTAX ERROR:', e.message); process.exit(1); } // 2. v30 block exists let v30Start = s.indexOf('// v30:'); let v30End = s.indexOf('// v23:', v30Start); console.log('[2] v30 block:', v30Start > 0 && v30End > v30Start ? 'OK' : 'MISSING'); // 3. Key features present console.log('[3] rcCands:', s.indexOf('rcCands') > 0 ? 'OK' : 'MISSING'); console.log('[4] content_copy filter:', s.indexOf('content_copy|content_paste') > 0 ? 'OK' : 'MISSING'); console.log('[5] sort by length:', s.indexOf('.sort(') > 0 ? 'OK' : 'MISSING'); console.log('[6] icon strip replace:', (s.match(/content_copy/g)||[]).length >= 2 ? 'OK (filter+strip)' : 'CHECK'); // 4. Simulate exact DOM from BTN-DOM-DUMP + CONTEXT logs let promptRe = /[\u003e\u00bb\u276f]\s+(.+)/; let stripRe = /\s*(content_copy|content_paste|play_arrow|check_circle|keyboard_arrow[_a-z]*)\s*$/; let iconFilterRe = /^(content_copy|content_paste|play_arrow|check_circle|chevron_|keyboard_arrow|more_horiz|more_vert|expand_|alternate_email|arrow_drop)/; let btnFilterRe = /^(Always|Run|Allow|Cancel|Deny|keyboard_arrow)/i; function simulate(name, siblings) { console.log('\n=== ' + name + ' ==='); let rcFound = false; for (let sib of siblings) { if (sib === 'Running command' || (sib.indexOf('Running command') !== -1 && sib.length < 30)) { rcFound = true; break; } } if (!rcFound) { console.log(' RC header NOT FOUND'); return null; } let cands = []; for (let sib of siblings) { if (sib === 'Running command') continue; if (sib.length < 5) continue; if (iconFilterRe.test(sib)) { console.log(' SKIP icon: "' + sib.substring(0,30) + '"'); continue; } if (btnFilterRe.test(sib)) { console.log(' SKIP btn: "' + sib.substring(0,30) + '"'); continue; } if (sib.indexOf('Always run') !== -1 && sib.indexOf('Cancel') !== -1) { console.log(' SKIP btn-bar: "' + sib.substring(0,30) + '"'); continue; } cands.push(sib); } cands.sort((a,b) => b.length - a.length); console.log(' Candidates: ' + cands.length); for (let i = 0; i < cands.length; i++) { console.log(' [' + i + '] len=' + cands[i].length + ': "' + cands[i].substring(0,80) + '"'); } for (let cand of cands) { let m = promptRe.exec(cand); if (m && m[1].trim().length > 3) { let cmdV = m[1].trim().replace(stripRe, '').trim(); if (cmdV.length < 3) continue; console.log(' RESULT: "' + cmdV + '"'); return cmdV; } if (cand.length > 10 && /[\u276f\u003e]/.test(cand)) { let raw = cand.replace(stripRe, '').trim(); console.log(' RESULT (raw): "' + raw + '"'); return raw; } } console.log(' RESULT: NO MATCH'); return null; } // Case 1: From BTN-DOM-DUMP (3 siblings, command + content_copy icon) simulate('Case1: Normal command with icon', [ 'Running command', '\u276f gravity_control > Start-Sleep 12; $logFile content_copy', 'Always run keyboard_arrow_up Cancel' ]); // Case 2: content_copy as standalone sibling simulate('Case2: Icon as separate div', [ 'Running command', 'content_copy', '\u276f gravity_control > npm run compile', 'Always run Cancel' ]); // Case 3: No icon appended simulate('Case3: Clean command', [ 'Running command', '\u276f gravity_control > git add -A; git commit -m "test"', 'Always run Cancel' ]); // Case 4: Very long command simulate('Case4: Long command', [ 'Running command', '\u276f gravity_control > Select-String -Path "$env:USERPROFILE\\.gemini\\antigravity\\bridge\\extension.log" -Pattern "CONTEXT" content_copy', 'Always run keyboard_arrow_up Cancel' ]); // Case 5: Prompt only (no command yet) simulate('Case5: Prompt only', [ 'Running command', '\u276f gravity_control > ', 'Always run Cancel' ]); // Case 6: Multiple icon texts simulate('Case6: Multiple icons', [ 'Running command', 'play_arrow', 'content_copy', '\u276f gravity_control > dir content_copy', 'Always run Cancel' ]); // Case 7: Observed log pattern - "content_copy" was cmdV // This means the regex matched on just "content_copy" with a > before it // Possible: the sibling text is "> content_copy" (very short prompt) simulate('Case7: Short prompt with icon only', [ 'Running command', '> content_copy', 'Always run Cancel' ]); console.log('\n=== ALL TESTS COMPLETE ===');