docs: AG Native bundle reverse engineering analysis — plannerResponse/Whi renderer structure, V8 cache fix, known-issues update
This commit is contained in:
125
scratch_dom_inspector.js
Normal file
125
scratch_dom_inspector.js
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* 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('────────────────────────────────────────');
|
||||
Reference in New Issue
Block a user