fix(observer): regex → 문자열 비교로 isGenericDesc 수정 — template literal escaping 회피 (v0.5.84)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
export function generateApprovalObserverScript(_port: number): string {
|
||||
return `
|
||||
// ── Gravity Bridge v17: Always Run Auto-Approve + Retry Detection ──
|
||||
// ?? Gravity Bridge v17: Always Run Auto-Approve + Retry Detection ??
|
||||
// v17: "Always run" auto-approve at bridge level + Retry button relay to Discord
|
||||
(function(){
|
||||
'use strict';
|
||||
@@ -16,7 +16,7 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
try { fetch(BASE+'/log', {method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({msg:m.substring(0,2000)})}); } catch(e){}
|
||||
}
|
||||
}
|
||||
log('v17 Script loaded — Always Run Auto-Approve + Retry Detection');
|
||||
log('v17 Script loaded ??Always Run Auto-Approve + Retry Detection');
|
||||
|
||||
// DIAGNOSTIC BEACON: immediate POST to confirm script execution in renderer
|
||||
try {
|
||||
@@ -39,7 +39,7 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Noise filter: lines that are UI artifacts, not real content ──
|
||||
// ?? Noise filter: lines that are UI artifacts, not real content ??
|
||||
var NOISE_RE = new RegExp(
|
||||
'^(' +
|
||||
'chevron_right|chevron_left|arrow_drop_down|arrow_drop_up|arrow_right|arrow_left|' +
|
||||
@@ -114,10 +114,10 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
return type+'|'+txt+'|'+idx;
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════════════════════
|
||||
// ?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧
|
||||
// v7: STEP-AWARE CONTEXT EXTRACTION
|
||||
// Find the closest [data-step-index] ancestor, extract step info
|
||||
// ══════════════════════════════════════════════════════════════════
|
||||
// ?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧
|
||||
|
||||
function getStepContainer(el) {
|
||||
var node = el;
|
||||
@@ -129,9 +129,9 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
}
|
||||
|
||||
// v14: Climb DOM tree to find context near the button
|
||||
// STRICT SCOPE: Only 5 levels up — beyond that we're in unrelated UI territory.
|
||||
// STRICT SCOPE: Only 5 levels up ??beyond that we're in unrelated UI territory.
|
||||
// JUNK FILTERS: CSS rules, source code, Material icon gluing are all rejected.
|
||||
// NO FALLBACK: span/div/p text collection is removed entirely — it always grabs chat/UI text.
|
||||
// NO FALLBACK: span/div/p text collection is removed entirely ??it always grabs chat/UI text.
|
||||
var PROMPT_ONLY_RE = /^[^\\n]*[\\/\>\\xbb$#]\\s*$/;
|
||||
// v14: Detect CSS rules, JS source code, or extension internals in code text
|
||||
var JUNK_CODE_RE = /(!important|::selection|background-color:|var\\(--|font-size:|border-[a-z]|padding:|margin:|display:\\s|\\{[^}]*:[^}]*\\}|===|!==|\\|\\||\\bfunction\\s*\\(|\\bconst\\s+\\w+\\s*=|\\bvar\\s+\\w+\\s*=|\\bif\\s*\\(|\\breturn\\b|\\bimport\\s|\\bexport\\s|\\bclass\\s+\\w|\\bnew\\s+\\w|\\.test\\(|\\.match\\(|\\.replace\\(|_RE[.\\s]|\\brawDesc\\b|\\brawCmd\\b|\\benrichedCmd\\b|\\bquerySelector)/;
|
||||
@@ -144,7 +144,7 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
var _bestCodeHeader = '';
|
||||
var _sawCodeEls = false;
|
||||
var _allSkipped = true;
|
||||
// v22: Increased from 5 to 10 — AG Native command display (SRi) can be many levels up
|
||||
// v22: Increased from 5 to 10 ??AG Native command display (SRi) can be many levels up
|
||||
for (var depth = 0; depth < 10 && node; depth++) {
|
||||
if (!node.querySelector) { _debugTrail.push('d'+depth+':noQS'); node = node.parentElement; continue; }
|
||||
// v22: Prioritize pre.font-mono (AG Native command line display from SRi component)
|
||||
@@ -205,7 +205,7 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
_debugTrail.push('sibling_d'+depth+':tag='+siblings[si].tagName.toLowerCase()+',code='+sibCode.substring(0,40));
|
||||
_bestCodeText = sibCode;
|
||||
_allSkipped = false;
|
||||
// Found in sibling — return immediately
|
||||
// Found in sibling ??return immediately
|
||||
var sibParts = [];
|
||||
var sibHdr = siblings[si].querySelector('h1, h2, h3, [class*="header"], [class*="title"], [class*="cursor-pointer"]');
|
||||
if (sibHdr) sibParts.push(cleanLines((sibHdr.textContent || '').trim().substring(0, 200)));
|
||||
@@ -234,7 +234,7 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
function extractStepContext(btn) {
|
||||
var stepEl = getStepContainer(btn);
|
||||
if (!stepEl) {
|
||||
// v9 FALLBACK: no data-step-index — climb DOM for pre/code blocks
|
||||
// v9 FALLBACK: no data-step-index ??climb DOM for pre/code blocks
|
||||
return extractContextFromNearby(btn);
|
||||
}
|
||||
|
||||
@@ -270,7 +270,7 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
if (codeText && !headerText.includes(codeText.substring(0, 20))) parts.push(codeText);
|
||||
if (ariaLabel && ariaLabel.length > 5 && !headerText.includes(ariaLabel)) parts.push(ariaLabel);
|
||||
|
||||
var result = parts.join(' — ');
|
||||
var result = parts.join(' ??');
|
||||
if (!result) result = cleanButtonText(btn);
|
||||
return 'Step #' + stepIdx + ': ' + result;
|
||||
}
|
||||
@@ -286,7 +286,7 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
for(var i=0; i<ACTION_WORDS.length; i++) {
|
||||
if(txt.indexOf(ACTION_WORDS[i]) !== -1) return true;
|
||||
}
|
||||
// v9: Removed "Running N commands" — it's a group header, not an approval button
|
||||
// v9: Removed "Running N commands" ??it's a group header, not an approval button
|
||||
return false;
|
||||
}
|
||||
function isRejectBtn(txt) {
|
||||
@@ -366,18 +366,18 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
startObserver();
|
||||
});
|
||||
|
||||
// ══════════════════════════════════════════════════════════════════
|
||||
// v8: FULL DOM STRUCTURE DUMP (unconditional — no selector dependency)
|
||||
// ?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧
|
||||
// v8: FULL DOM STRUCTURE DUMP (unconditional ??no selector dependency)
|
||||
// Dumps entire document.body tree to /dump-html for real DOM analysis
|
||||
// Auto-triggers at 5s, 15s, 60s after load to capture React-rendered state
|
||||
// ══════════════════════════════════════════════════════════════════
|
||||
// ?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧
|
||||
|
||||
var _dumpCount=0;
|
||||
var MAX_DUMPS=8;
|
||||
var _conversationDumpCount=0;
|
||||
|
||||
function walkNode(el, depth, maxDepth, maxChildren) {
|
||||
if (depth > maxDepth) return {tag:'…',text:'depth limit'};
|
||||
if (depth > maxDepth) return {tag:'??,text:'depth limit'};
|
||||
if (!el || !el.tagName) return null;
|
||||
var info = {
|
||||
tag: el.tagName ? el.tagName.toLowerCase() : '#text',
|
||||
@@ -413,7 +413,7 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
if (childInfo) info.children.push(childInfo);
|
||||
}
|
||||
if (el.children.length > limit) {
|
||||
info.children.push({tag: '…', text: '+' + (el.children.length - limit) + ' more children'});
|
||||
info.children.push({tag: '??, text: '+' + (el.children.length - limit) + ' more children'});
|
||||
}
|
||||
}
|
||||
return info;
|
||||
@@ -508,11 +508,11 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
setTimeout(function(){ log('Auto-dump @60s'); dumpDOMStructure(); }, 60000);
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════════════════════
|
||||
// ?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧
|
||||
// v15: AG-NATIVE + CASCADE DUAL CHAT BODY SCANNING
|
||||
// AG Native: #conversation > ... > .leading-relaxed.select-text
|
||||
// Cascade: [data-testid="conversation-view"] > [data-step-index]
|
||||
// ══════════════════════════════════════════════════════════════════
|
||||
// ?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧
|
||||
|
||||
var _lastScrapedStepIndex = -1;
|
||||
var _lastStepText = '';
|
||||
@@ -684,7 +684,7 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
}
|
||||
}
|
||||
|
||||
// v19: Post-process — wrap markdown table patterns in code blocks for Discord
|
||||
// v19: Post-process ??wrap markdown table patterns in code blocks for Discord
|
||||
// AG Native renders tables as divs, not <table> HTML, so DOM-level handler can't catch them.
|
||||
// Detect consecutive lines with pipe separators (| col1 | col2 |) and wrap in code block fences
|
||||
var bt = String.fromCharCode(96, 96, 96);
|
||||
@@ -749,12 +749,12 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
// One-time DOM dump
|
||||
dumpDOMStructure();
|
||||
|
||||
// ── STRATEGY 1: AG Native — #conversation or .antigravity-agent-side-panel ──
|
||||
// ?? STRATEGY 1: AG Native ??#conversation or .antigravity-agent-side-panel ??
|
||||
var cv = document.querySelector('#conversation');
|
||||
if (!cv) {
|
||||
cv = document.querySelector('.antigravity-agent-side-panel');
|
||||
}
|
||||
// v19: Fallback — find conversation by tracing from known content elements
|
||||
// v19: Fallback ??find conversation by tracing from known content elements
|
||||
if (!cv) {
|
||||
var probe = document.querySelector('.leading-relaxed.select-text') || document.querySelector('.text-ide-message-block-bot-color');
|
||||
if (probe) {
|
||||
@@ -818,11 +818,11 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
}
|
||||
|
||||
// v22: AI response = .leading-relaxed.select-text, User message = .select-text.rounded-lg (Esn component, msn class)
|
||||
// Source: jetskiAgent/main.js — msn="bg-gray-500/10 border border-gray-500/20 p-2 rounded-lg w-full text-sm select-text"
|
||||
// Source: jetskiAgent/main.js ??msn="bg-gray-500/10 border border-gray-500/20 p-2 rounded-lg w-full text-sm select-text"
|
||||
var responseBlocks = cv.querySelectorAll('.leading-relaxed.select-text, .select-text.rounded-lg');
|
||||
|
||||
if (responseBlocks.length > 0) {
|
||||
// v22: Filter out thinking/reasoning blocks — they have ancestor with max-h-[200px]
|
||||
// v22: Filter out thinking/reasoning blocks ??they have ancestor with max-h-[200px]
|
||||
// These are internal AI reasoning and should NOT be relayed to Discord
|
||||
var filteredBlocks = [];
|
||||
for (var fbi = 0; fbi < responseBlocks.length; fbi++) {
|
||||
@@ -847,7 +847,7 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
if (lastBlock.dataset.agChatScraped === 'true' || lastBlock.dataset.agChatScraped === 'pending') {
|
||||
// Check for NEW blocks since last scrape
|
||||
if (filteredBlocks.length > _lastResponseBlockCount) {
|
||||
// New block appeared — process it
|
||||
// New block appeared ??process it
|
||||
for (var rbi = filteredBlocks.length - 1; rbi >= 0; rbi--) {
|
||||
if (filteredBlocks[rbi].dataset.agChatScraped !== 'true' && filteredBlocks[rbi].dataset.agChatScraped !== 'pending') {
|
||||
lastBlock = filteredBlocks[rbi];
|
||||
@@ -896,7 +896,7 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
var waitTime = isUser ? 500 : 3000;
|
||||
if (Date.now() - _lastStepTextTime < waitTime) return; // Still waiting
|
||||
|
||||
// v21: DOM-based chat relay RE-ENABLED — GetCascadeTrajectorySteps does NOT
|
||||
// v21: DOM-based chat relay RE-ENABLED ??GetCascadeTrajectorySteps does NOT
|
||||
// return steps for in-progress cascades, making Step Probe RT-CAPTURE useless.
|
||||
// Observer DOM extraction is the ONLY real-time path for AI response relay.
|
||||
_lastStepTextSent = true;
|
||||
@@ -913,11 +913,11 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
.catch(function(e) { el.dataset.agChatScraped = 'false'; log('AG-Native chat send error: ' + e.message); });
|
||||
})(lastBlock, blockText, filteredBlocks.length, role);
|
||||
}
|
||||
return; // AG Native path handled — don't fall through to Cascade path
|
||||
return; // AG Native path handled ??don't fall through to Cascade path
|
||||
}
|
||||
}
|
||||
|
||||
// ── STRATEGY 2: Cascade — [data-testid="conversation-view"] ──
|
||||
// ?? STRATEGY 2: Cascade ??[data-testid="conversation-view"] ??
|
||||
cv = document.querySelector('[data-testid="conversation-view"]');
|
||||
if (!cv) {
|
||||
// FALLBACK: Try older selectors
|
||||
@@ -989,7 +989,7 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
if (_lastStepTextSent) continue;
|
||||
if (Date.now() - _lastStepTextTime < 3000) break; // Still waiting
|
||||
|
||||
// Content is stable — send it
|
||||
// Content is stable ??send it
|
||||
_lastStepTextSent = true;
|
||||
_lastScrapedStepIndex = stepIdx;
|
||||
stepEl.dataset.agChatScraped = 'pending';
|
||||
@@ -1007,9 +1007,9 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
}
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════════════════════
|
||||
// ?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧
|
||||
// BUTTON SCANNING (approval detection)
|
||||
// ══════════════════════════════════════════════════════════════════
|
||||
// ?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧?먥븧
|
||||
|
||||
function scan(){
|
||||
if(!_ready)return;
|
||||
@@ -1018,7 +1018,7 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
var allBtns=document.querySelectorAll('button, [role="button"], a.monaco-button, .monaco-text-button, vscode-button');
|
||||
if(!allBtns.length)return;
|
||||
|
||||
// v25: One-shot debug — find Accept/Reject elements in ANY tag (run once per 30s)
|
||||
// v25: One-shot debug ??find Accept/Reject elements in ANY tag (run once per 30s)
|
||||
if (!scan._lastAcceptScan || now - scan._lastAcceptScan > 30000) {
|
||||
scan._lastAcceptScan = now;
|
||||
var allEls = document.querySelectorAll('button, a, div, span, [role="button"]');
|
||||
@@ -1037,10 +1037,10 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
var txt=cleanButtonText(b);
|
||||
if(txt.length <= 1) continue;
|
||||
|
||||
// v9: Skip group header buttons — not approval buttons
|
||||
// v9: Skip group header buttons ??not approval buttons
|
||||
if (/^Running\\s*\\d+\\s*commands?$/i.test(txt)) continue;
|
||||
|
||||
// v24: Relaxed visibility check — Accept all/Reject all buttons in AG Native
|
||||
// v24: Relaxed visibility check ??Accept all/Reject all buttons in AG Native
|
||||
// editor bottom bar may have offsetParent===null (different rendering layer)
|
||||
var isDiffReviewBtn = txt.includes('Accept') || txt === 'Reject all';
|
||||
if(!isDiffReviewBtn && (b.disabled||b.hidden||(!b.offsetParent&&b.style.display!=='fixed')))continue;
|
||||
@@ -1081,15 +1081,20 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
_sent[groupKey]={rid:rid,ts:now};
|
||||
for(var mk=0;mk<bidList.length;mk++)_sent[bidList[mk]]={rid:rid,ts:now};
|
||||
|
||||
// v26: Deferred context — if desc is generic ("Always run", button text only),
|
||||
// v26: Deferred context (string match, not regex — avoids template literal escaping issues)
|
||||
function _isGenericDesc(d) {
|
||||
var t = d.trim().toLowerCase();
|
||||
return t === 'always run' || t === 'run' || t === 'allow' || t === 'accept' || t === 'retry' || t === txt.toLowerCase();
|
||||
}
|
||||
// v26: Deferred context ??if desc is generic ("Always run", button text only),
|
||||
// delay 500ms and re-extract to allow DOM rendering to complete
|
||||
var isGenericDesc = /^(Always\\s+run|Run|Allow|Accept|Retry)$/i.test(desc.trim()) || desc === txt;
|
||||
var isGenericDesc = _isGenericDesc(desc);
|
||||
if (isGenericDesc && matchedType === 'command') {
|
||||
log('DEFERRED-CONTEXT: desc="' + desc.substring(0,30) + '" — waiting 500ms for DOM render');
|
||||
log('DEFERRED-CONTEXT: desc="' + desc.substring(0,30) + '" ??waiting 500ms for DOM render');
|
||||
(function(b2, rid2, btnRefs2, bidList2, groupKey2, txt2, type2, buttonsArr2) {
|
||||
setTimeout(function() {
|
||||
var retryDesc = extractContext(b2);
|
||||
var finalDesc = /^(Always\\s+run|Run|Allow|Accept|Retry)$/i.test(retryDesc.trim()) ? desc : retryDesc;
|
||||
var finalDesc = _isGenericDesc(retryDesc) ? desc : retryDesc;
|
||||
log('DEFERRED-RESULT: "' + finalDesc.substring(0,80) + '"');
|
||||
var payload = {
|
||||
request_id: rid2,
|
||||
@@ -1229,7 +1234,7 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
|
||||
function startObserver(){
|
||||
if(_obs)return;
|
||||
log('startObserver() — scheduling auto-dumps and mutation observer');
|
||||
log('startObserver() ??scheduling auto-dumps and mutation observer');
|
||||
scheduleAutoDumps();
|
||||
new MutationObserver(function(mutations){
|
||||
for(var i=0;i<mutations.length;i++){
|
||||
@@ -1241,7 +1246,7 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
}).observe(document.body,{childList:true,subtree:true});
|
||||
setInterval(scheduleScan,3000);
|
||||
|
||||
// ── TRIGGER-CLICK POLLING ──
|
||||
// ?? TRIGGER-CLICK POLLING ??
|
||||
(function pollTriggerClick(){
|
||||
if(_ready&&BASE){
|
||||
fetch(BASE+'/trigger-click?t='+Date.now()).then(function(r){return r.json();}).then(function(d){
|
||||
@@ -1264,12 +1269,12 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
setTimeout(pollTriggerClick, 2000);
|
||||
})();
|
||||
|
||||
// ── DEEP-INSPECT POLLING (v8: full body dump) ──
|
||||
// ?? DEEP-INSPECT POLLING (v8: full body dump) ??
|
||||
(function pollDeepInspect(){
|
||||
if(_ready&&BASE){
|
||||
fetch(BASE+'/deep-inspect-trigger?t='+Date.now()).then(function(r){return r.json();}).then(function(d){
|
||||
if(!d.inspect)return;
|
||||
log('Deep inspect triggered — full body dump');
|
||||
log('Deep inspect triggered ??full body dump');
|
||||
// Force a fresh DOM dump
|
||||
_dumpCount = Math.max(0, _dumpCount - 1); // allow one more dump
|
||||
dumpDOMStructure();
|
||||
@@ -1319,3 +1324,4 @@ export function generateApprovalObserverScript(_port: number): string {
|
||||
})();
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user