""" Inject a DOM probe into AG Native to capture the actual conversation DOM structure. Posts the DOM structure to the HTTP bridge's /dump-html endpoint. """ import requests, json BASE = "http://127.0.0.1:34332" # We already have observer script running in workbench-jetski-agent.html # But the issue is: the script is in the OUTER workbench, while the # conversation UI might be in a webview/iframe. # Let's first check what the observer CAN see by triggering a dump # We'll post a custom HTML dump request # Actually, let's analyze from a different angle: # The observer's scanChatBodies() uses these selectors: # '.text-ide-message-block-bot-color', '[data-testid*="bot"]', etc. # If none match, it returns nothing. But we ARE getting DOM content # (the garbage text), so SOMETHING is matching. # The garbage text ("Running command", "content_copy", "Always run", etc.) # This is the tool execution UI, not the AI response. # Let's check what the current status says about sessionStalled print("=== Bridge Status ===") status = requests.get(f"{BASE}/status").json() print(json.dumps(status, indent=2)) # Check if we can identify the DOM structure by examining what # the observer script actually matched. # The fact that it sends "Running command\n...\n content_copy\n Always run" # means it's grabbing a tool execution panel, not the AI text response. # Key insight: In AG Native UI (Tailwind/React), the conversation is in # the SAME document as the workbench (not in a separate webview/iframe). # The observer IS running in the right context, BUT the CSS selectors # (.text-ide-message-block-bot-color) don't match AG Native's actual classes. # What's happening: scanChatBodies() falls through to the broader selectors # like [class*="agent-convo"] or [class*="bot-message"], which might be # accidentally matching the tool panel UI. # SOLUTION: We need to know the actual CSS class names for: # 1. AI response text containers (the markdown output) # 2. Tool call approval containers (Run/Allow/Cancel buttons) print("\n=== DOM Probe via dump-html (injecting probe) ===") # The observer's deep-inspect didn't work, but maybe we can # create a targeted probe via a modified observer script # Let's check what HTML files are currently being served print("\nChecking if we can reach the webview...") try: # The observer script's scan() function runs every 3s. # Let's see what it's finding by checking recent chat snapshots on disk import os bridge_path = os.path.expanduser("~/.gemini/antigravity/bridge") pending_dir = os.path.join(bridge_path, "pending") if os.path.exists(pending_dir): files = sorted(os.listdir(pending_dir), key=lambda f: os.path.getmtime(os.path.join(pending_dir, f)), reverse=True) print(f"\nRecent pending files: {len(files)}") for f in files[:5]: fpath = os.path.join(pending_dir, f) try: data = json.loads(open(fpath, encoding='utf-8').read()) print(f" {f}: cmd=\"{data.get('command','?')[:50]}\" src={data.get('source','?')} type={data.get('step_type','?')}") except Exception as e: print(f" {f}: error: {e}") # Check brain directory for session artifacts brain_dir = os.path.expanduser("~/.gemini/antigravity/brain/bdfc07d3-d87e-453a-b785-e38c2e9254e3") if os.path.exists(brain_dir): print(f"\nBrain dir exists: {brain_dir}") entries = os.listdir(brain_dir) print(f" Contents: {entries[:20]}") # Check for conversation log log_dir = os.path.join(brain_dir, ".system_generated", "logs") if os.path.exists(log_dir): print(f" Log dir: {os.listdir(log_dir)}") else: print(f"\nBrain dir NOT found: {brain_dir}") # List available brain dirs parent = os.path.expanduser("~/.gemini/antigravity/brain") if os.path.exists(parent): dirs = sorted(os.listdir(parent), key=lambda d: os.path.getmtime(os.path.join(parent, d)), reverse=True) print(f" Available: {dirs[:5]}") except Exception as e: print(f"Error: {e}")