fix(observer): v32 터미널 프롬프트 조기감지 — JUNK/PROMPT 필터 전에 명령어 추출 (v0.5.97)
근본원인: code 요소의 textContent '❯ project > command'가 PowerShell 키워드 (return, function, const)를 포함할 수 있어 JUNK_CODE_RE에 잘못 걸림. v32: ❯ 마커로 시작하는 code 텍스트는 JUNK/PROMPT 전에 명령어 직접 추출. 14/14 E2E 테스트 통과.
This commit is contained in:
122
extension/scratch/verify_v096.js
Normal file
122
extension/scratch/verify_v096.js
Normal file
@@ -0,0 +1,122 @@
|
||||
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 ===');
|
||||
Reference in New Issue
Block a user