"""Trace the DOM path from body to AI response container.""" import json, os fpath = os.path.join(os.path.expanduser('~'), '.gemini', 'antigravity', 'bridge', 'dump_html_5.json') with open(fpath, 'r', encoding='utf-8-sig') as f: data = json.load(f) body = data.get('body', data.get('bodyTree', {})) def find_path_to_class(node, target_cls, path=None, depth=0): """Find the DOM path down to a node with a matching class.""" if path is None: path = [] if not isinstance(node, dict): return [] tag = node.get('tag', '') cls = node.get('cls', '') children = node.get('children', []) text = node.get('text', '') attrs = node.get('attrs', {}) entry = { 'depth': depth, 'tag': tag, 'cls': cls[:120], 'children': len(children), 'text': text[:60] if text else '', 'attrs': {k:v[:40] for k,v in attrs.items() if k not in ('style',)} } if target_cls.lower() in cls.lower(): return path + [entry] for i, child in enumerate(children): result = find_path_to_class(child, target_cls, path + [entry], depth+1) if result: return result return [] # Find path to the AI response container print("=== PATH TO 'leading-relaxed select-text' ===") path = find_path_to_class(body, 'leading-relaxed select-text') for p in path: indent = ' ' * p['depth'] print(f'{indent}[{p["tag"]}] cls="{p["cls"]}" children={p["children"]} {p["attrs"]}') if p['text']: print(f'{indent} text: "{p["text"]}"') # Now get the full subtree of the AI response container def get_subtree(node, target_cls, depth=0): if not isinstance(node, dict): return None cls = node.get('cls', '') if target_cls.lower() in cls.lower(): return node for child in node.get('children', []): result = get_subtree(child, target_cls, depth+1) if result: return result return None print("\n=== AI RESPONSE CONTAINER SUBTREE ===") container = get_subtree(body, 'leading-relaxed select-text') if container: def print_tree(node, depth=0, max_depth=4): if not isinstance(node, dict) or depth > max_depth: return tag = node.get('tag','') cls = node.get('cls','')[:80] text = node.get('text','') children = node.get('children', []) indent = ' ' * depth line = f'{indent}[{tag}]' if cls: line += f' cls="{cls}"' line += f' children={len(children)}' if text: line += f' text="{text[:60]}"' print(line) for c in children: print_tree(c, depth+1, max_depth) print_tree(container, 0, 3) # Also search for the chat panel container - what wraps the entire conversation print("\n=== SEARCH FOR CHAT PANEL WRAPPERS ===") chat_patterns = ['chat', 'antigravity', 'gemini', 'panel', 'agentview', 'sidebar', 'conversation'] for pat in chat_patterns: path = find_path_to_class(body, pat) if path: last = path[-1] print(f' Pattern "{pat}" found at depth={last["depth"]} [{last["tag"]}] cls="{last["cls"]}" children={last["children"]}') # Find the parent chain from body to the container - look by scanning ALL class names print("\n=== ALL UNIQUE CLASS NAMES (depth <= 12) ===") all_classes = set() def collect_classes(node, depth=0, max_depth=12): if not isinstance(node, dict) or depth > max_depth: return cls = node.get('cls', '') if cls: for c in cls.split(): if len(c) > 3 and not c.startswith('{') and 'mtk' not in c: all_classes.add(c) for child in node.get('children', []): collect_classes(child, depth+1, max_depth) collect_classes(body) # Print classes sorted, grouped by potential relevance relevant = sorted([c for c in all_classes if any(k in c.lower() for k in ['chat', 'message', 'response', 'agent', 'gemini', 'turn', 'model', 'user', 'bot', 'conversation', 'markdown', 'prose', 'text-', 'content'])]) print("Relevant classes:") for c in relevant: print(f' {c}')