From 08fd08b9a6857361973ab321e246c52dfe0c583a Mon Sep 17 00:00:00 2001 From: Variet Worker Date: Sat, 18 Apr 2026 08:18:35 +0900 Subject: [PATCH] feat(observer): diagnostic log relay via HTTP + auto-approve enrichment fallback (v0.5.63) #task-634 --- extension/package-lock.json | 4 ++-- extension/package.json | 2 +- extension/src/http-bridge.ts | 22 ++++++++++++++++++ extension/src/observer-script.ts | 40 +++++++++++++++++++++++++++++--- 4 files changed, 62 insertions(+), 6 deletions(-) diff --git a/extension/package-lock.json b/extension/package-lock.json index 8af4ff4..a727d1e 100644 --- a/extension/package-lock.json +++ b/extension/package-lock.json @@ -1,12 +1,12 @@ { "name": "gravity-bridge", - "version": "0.5.60", + "version": "0.5.63", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gravity-bridge", - "version": "0.5.60", + "version": "0.5.63", "dependencies": { "cheerio": "^1.2.0", "ws": "^8.19.0" diff --git a/extension/package.json b/extension/package.json index d532a47..16fb3ea 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.60", + "version": "0.5.63", "publisher": "variet", "engines": { "vscode": "^1.100.0" diff --git a/extension/src/http-bridge.ts b/extension/src/http-bridge.ts index 55d57a7..686fdd9 100644 --- a/extension/src/http-bridge.ts +++ b/extension/src/http-bridge.ts @@ -126,6 +126,21 @@ export function startHttpBridge(ctx: HttpBridgeContext, sdk: any): Promise logBody += c); + req.on('end', () => { + try { + const logData = JSON.parse(logBody); + ctx.logToFile(`[OBSERVER-LOG] ${logData.msg || logBody.substring(0, 500)}`); + } catch { ctx.logToFile(`[OBSERVER-LOG] ${logBody.substring(0, 500)}`); } + res.writeHead(200); res.end('ok'); + }); + return; + } + if (req.method === 'POST' && url.pathname === '/dump-html') { let dumpBody = ''; req.setEncoding('utf8'); @@ -287,6 +302,13 @@ function _handlePending(req: any, res: any, ctx: HttpBridgeContext) { const promptMatch = rawDesc.match(/[>»]\s*(.+)/); if (promptMatch && promptMatch[1].trim().length > 3) { displayCmd = promptMatch[1].trim().substring(0, 200); + } else { + // v19: Fallback — use longest line from description as command text + const descLines = rawDesc.split(/\n/).map((l: string) => l.trim()).filter((l: string) => l.length > 3); + if (descLines.length > 0) { + descLines.sort((a: string, b: string) => b.length - a.length); + displayCmd = descLines[0].substring(0, 200); + } } } const rid = data.request_id || Date.now().toString(); diff --git a/extension/src/observer-script.ts b/extension/src/observer-script.ts index 425623e..5a7b06d 100644 --- a/extension/src/observer-script.ts +++ b/extension/src/observer-script.ts @@ -9,7 +9,13 @@ export function generateApprovalObserverScript(_port: number): string { var THROTTLE_MS=500; var CLEANUP_MS=300000; - function log(m){console.log('[GB Observer] '+m);} + function log(m){ + console.log('[GB Observer] '+m); + // v19: Relay important logs to extension via HTTP so they appear in extension.log + if (BASE && (m.indexOf('CV-CLASSES')!==-1 || m.indexOf('Conversation view')!==-1 || m.indexOf('BEACON')!==-1 || m.indexOf('ERROR')!==-1 || m.indexOf('chat relay')!==-1 || m.indexOf('user-cls')!==-1)) { + 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'); // DIAGNOSTIC BEACON: immediate POST to confirm script execution in renderer @@ -338,7 +344,8 @@ export function generateApprovalObserverScript(_port: number): string { // ══════════════════════════════════════════════════════════════════ var _dumpCount=0; - var MAX_DUMPS=5; + var MAX_DUMPS=8; + var _conversationDumped=false; function walkNode(el, depth, maxDepth, maxChildren) { if (depth > maxDepth) return {tag:'…',text:'depth limit'}; @@ -720,8 +727,31 @@ export function generateApprovalObserverScript(_port: number): string { } if (cv) { + // v19: Trigger DOM dump when conversation view is first found (prev dumps may have captured Settings tab) + if (!_conversationDumped) { + _conversationDumped = true; + log('Conversation view found — triggering chat-context DOM dump'); + // Log all unique class names under #conversation for selector discovery + var allCvEls = cv.querySelectorAll('*'); + var clsSet = {}; + for (var ci2 = 0; ci2 < allCvEls.length; ci2++) { + var cn = allCvEls[ci2].className; + if (typeof cn === 'string' && cn.length > 0) { + var parts = cn.split(/\\s+/); + for (var pi = 0; pi < parts.length; pi++) { + if (parts[pi].length > 3 && !clsSet[parts[pi]]) clsSet[parts[pi]] = true; + } + } + } + var clsList = Object.keys(clsSet).sort().join(', '); + log('CV-CLASSES (' + Object.keys(clsSet).length + '): ' + clsList.substring(0, 1500)); + // Force a dump with conversation context + dumpDOMStructure(); + } + // AG Native path: find AI and User response blocks by class pattern - var responseBlocks = cv.querySelectorAll('.leading-relaxed.select-text, .text-ide-message-block-user-color, .text-ide-message-block-bot-color, .bg-ide-message-block-user-background'); + // v19: Also look for common AG Native message container patterns + var responseBlocks = cv.querySelectorAll('.leading-relaxed.select-text, .text-ide-message-block-user-color, .text-ide-message-block-bot-color, .bg-ide-message-block-user-background, [data-message-role="user"], [data-role="user"]'); if (responseBlocks.length > 0) { // Process the LAST (most recent) response block @@ -747,6 +777,10 @@ export function generateApprovalObserverScript(_port: number): string { var blockText = extractCleanStepText(lastBlock); var clsStr = (typeof lastBlock.className === 'string') ? lastBlock.className : ''; + // v19: Log block classes for user message selector discovery + var parentCls = lastBlock.parentElement ? ((typeof lastBlock.parentElement.className === 'string') ? lastBlock.parentElement.className : '') : ''; + var grandCls = (lastBlock.parentElement && lastBlock.parentElement.parentElement) ? ((typeof lastBlock.parentElement.parentElement.className === 'string') ? lastBlock.parentElement.parentElement.className : '') : ''; + log('user-cls-debug block=' + clsStr.substring(0, 150) + ' | parent=' + parentCls.substring(0, 150) + ' | grand=' + grandCls.substring(0, 150) + ' | text=' + (blockText||'').substring(0, 50)); var isUser = clsStr.indexOf('user-color') !== -1 || clsStr.indexOf('user-background') !== -1 || clsStr.indexOf('user-message') !== -1; var role = isUser ? 'user' : 'bot';