From 1662ac4f6bea91c19f65e3de2cde21a1ad0bf006 Mon Sep 17 00:00:00 2001 From: Variet Worker Date: Sun, 19 Apr 2026 07:02:04 +0900 Subject: [PATCH] =?UTF-8?q?fix(observer):=20regex=20=E2=86=92=20=EB=AC=B8?= =?UTF-8?q?=EC=9E=90=EC=97=B4=20=EB=B9=84=EA=B5=90=EB=A1=9C=20isGenericDes?= =?UTF-8?q?c=20=EC=88=98=EC=A0=95=20=E2=80=94=20template=20literal=20escap?= =?UTF-8?q?ing=20=ED=9A=8C=ED=94=BC=20(v0.5.84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extension/package-lock.json | 4 +- extension/package.json | 2 +- extension/src/observer-script.ts | 90 +++++++++++++++++--------------- 3 files changed, 51 insertions(+), 45 deletions(-) diff --git a/extension/package-lock.json b/extension/package-lock.json index e8c5d68..7dc275c 100644 --- a/extension/package-lock.json +++ b/extension/package-lock.json @@ -1,12 +1,12 @@ { "name": "gravity-bridge", - "version": "0.5.83", + "version": "0.5.84", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gravity-bridge", - "version": "0.5.83", + "version": "0.5.84", "dependencies": { "cheerio": "^1.2.0", "ws": "^8.19.0" diff --git a/extension/package.json b/extension/package.json index d9f649c..ecbd161 100644 --- a/extension/package.json +++ b/extension/package.json @@ -2,7 +2,7 @@ "name": "gravity-bridge", "displayName": "Gravity Bridge", "description": "Discord-based unified approval system for Antigravity AI interactions.", - "version": "0.5.83", + "version": "0.5.84", "publisher": "variet", "engines": { "vscode": "^1.100.0" diff --git a/extension/src/observer-script.ts b/extension/src/observer-script.ts index 3402075..c1f65e4 100644 --- a/extension/src/observer-script.ts +++ b/extension/src/observer-script.ts @@ -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 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 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