/** * AG Native DOM Inspector — CDP를 통해 AG의 renderer에 연결하여 DOM을 덤프 * AG가 --remote-debugging-port 없이 실행 중이므로, * 대안으로 AG 내부 extension의 executeJavaScript를 통해 DOM을 캡처합니다. * * 사용법: AG에서 Gravity Bridge가 활성화된 후, 이 스크립트를 extension 내에서 실행 * 또는 AG의 DevTools Console에서 직접 실행 */ // AG DevTools Console에서 실행할 스크립트 (Ctrl+Shift+I로 열기) const domInspectScript = ` (function() { // 1. conversation-view 찾기 var cv = document.querySelector('[data-testid="conversation-view"]'); console.log('=== AG Native DOM Inspector ==='); console.log('conversation-view found:', !!cv); if (!cv) { // document의 전체 구조를 간략히 출력 function summarize(el, depth) { if (depth > 5) return ''; var tag = el.tagName ? el.tagName.toLowerCase() : '#text'; var cls = (el.className && typeof el.className === 'string') ? el.className.substring(0, 80) : ''; var id = el.id || ''; var dataAttrs = []; if (el.attributes) { for (var i = 0; i < el.attributes.length; i++) { if (el.attributes[i].name.startsWith('data-')) { dataAttrs.push(el.attributes[i].name + '=' + el.attributes[i].value.substring(0, 50)); } } } var indent = ' '.repeat(depth); var line = indent + '<' + tag; if (id) line += '#' + id; if (cls) line += ' class="' + cls + '"'; if (dataAttrs.length) line += ' ' + dataAttrs.join(' '); line += '>'; var result = line + '\\n'; if (el.children && depth < 4) { for (var c = 0; c < Math.min(el.children.length, 15); c++) { result += summarize(el.children[c], depth + 1); } if (el.children.length > 15) { result += indent + ' ... +' + (el.children.length - 15) + ' more\\n'; } } return result; } console.log('Full body structure:'); console.log(summarize(document.body, 0)); return; } // 2. conversation-view 내부 구조 덤프 function walkDetail(el, depth) { if (depth > 8) return null; var info = { tag: el.tagName ? el.tagName.toLowerCase() : '#text', cls: (el.className && typeof el.className === 'string') ? el.className.substring(0, 150) : '', dataAttrs: {}, text: '', childCount: el.children ? el.children.length : 0, children: [] }; if (el.attributes) { for (var i = 0; i < el.attributes.length; i++) { var attr = el.attributes[i]; if (attr.name.startsWith('data-') || attr.name === 'role' || attr.name === 'aria-label' || attr.name === 'title') { info.dataAttrs[attr.name] = (attr.value || '').substring(0, 100); } } } if (!el.children || el.children.length === 0) { var t = (el.textContent || '').trim(); if (t.length > 0 && t.length < 150) info.text = t; } if (el.children) { for (var c = 0; c < Math.min(el.children.length, 12); c++) { var child = walkDetail(el.children[c], depth + 1); if (child) info.children.push(child); } if (el.children.length > 12) { info.children.push({tag: '...', text: '+' + (el.children.length - 12) + ' more'}); } } return info; } var result = walkDetail(cv, 0); console.log(JSON.stringify(result, null, 2)); // 3. 특정 요소들 확인 console.log('\\n=== Key Selectors ==='); console.log('[data-step-index] count:', cv.querySelectorAll('[data-step-index]').length); console.log('.text-ide-message-block-bot-color count:', cv.querySelectorAll('.text-ide-message-block-bot-color').length); console.log('[class*="prose"] count:', cv.querySelectorAll('[class*="prose"]').length); console.log('[class*="markdown"] count:', cv.querySelectorAll('[class*="markdown"]').length); console.log('[class*="px-2"][class*="py-1"] count:', cv.querySelectorAll('[class*="px-2"][class*="py-1"]').length); console.log('button count:', cv.querySelectorAll('button').length); // 4. 버튼 텍스트 목록 var btns = cv.querySelectorAll('button'); console.log('\\n=== Buttons in conversation-view ==='); for (var b = 0; b < btns.length; b++) { var txt = (btns[b].textContent || '').trim().substring(0, 80); console.log(' [' + b + '] "' + txt + '"'); } })(); `; console.log('=== AG Native DOM Inspector Script ==='); console.log(''); console.log('AG DevTools Console에서 아래 스크립트를 실행하세요:'); console.log('AG에서 DevTools를 열려면: Ctrl+Shift+I'); console.log(''); console.log('────────────────────────────────────────'); console.log(domInspectScript); console.log('────────────────────────────────────────');