fix: structural hardening for grid selection and Reel author resolution

This commit is contained in:
2026-05-03 23:41:00 +02:00
parent 8a6c8a2249
commit 32731ed7ec
3 changed files with 134 additions and 20 deletions

View File

@@ -135,23 +135,16 @@ class IntentResolver:
# NEW REGRESSION FIX: Exclude interaction buttons (comment, like, share) when looking for author or media
# This prevents the weak VLM from hallucinating bounding box numbers that point to "Comment".
interaction_suffixes = ["comment", "like", "share", "send", "save", "button_icon"]
interaction_suffixes = ["comment", "like", "share", "send", "save", "button_icon", "scrubber"]
is_interaction = any(s in rid for s in interaction_suffixes) or any(s in desc for s in interaction_suffixes)
node_text_lower = (node.text or "").lower()
is_follow = "follow" in rid or "follow" in node_text_lower or "follow" in desc
is_media_intent = "media content" in intent_lower or "image" in intent_lower or "video" in intent_lower
if is_author_intent and (is_interaction or is_follow):
if (is_author_intent or is_media_intent) and (is_interaction or is_follow):
logger.debug(
f"🛡️ [Author Interaction Guard] Excluded interaction/follow button '{node.resource_id}' "
f"(desc='{node.content_desc}', text='{node.text}') for author intent '{intent_description}'"
)
continue
if is_media_intent and (is_interaction or is_follow):
logger.debug(
f"🛡️ [Media Interaction Guard] Excluded interaction/follow button '{node.resource_id}' "
f"(desc='{node.content_desc}') for media intent '{intent_description}'"
f"🛡️ [Interaction Guard] Excluded non-target element '{node.resource_id}' "
f"(desc='{node.content_desc}', text='{node.text}') for intent '{intent_description}'"
)
continue
@@ -233,15 +226,27 @@ class IntentResolver:
return node
if "post author username" in intent_lower or "tap post username" in intent_lower:
# 1. Feed Posts
for node in candidates:
if "row_feed_photo_profile_imageview" in (node.resource_id or "").lower():
rid = (node.resource_id or "").lower()
if "row_feed_photo_profile_imageview" in rid:
logger.info(f"🎯 [Structural Fast-Path] Found post author avatar image: {node.content_desc}")
return node
for node in candidates:
if "row_feed_photo_profile_name" in (node.resource_id or "").lower():
rid = (node.resource_id or "").lower()
if "row_feed_photo_profile_name" in rid:
logger.info(f"🎯 [Structural Fast-Path] Found post author username text: {node.text}")
return node
# 2. Reels (Clips)
for node in candidates:
rid = (node.resource_id or "").lower()
if "clips_author_username" in rid or "clips_author_container" in rid:
logger.info(
f"🎯 [Structural Fast-Path] Found Reel author username: {node.text or node.content_desc}"
)
return node
if "feed post content" in intent_lower or "post media content" in intent_lower:
for node in candidates:
rid = (node.resource_id or "").lower()

View File

@@ -184,14 +184,19 @@ class TelepathicEngine:
if not root:
return None
# Find grid-like visual nodes
# Find grid-like visual nodes using structural markers
all_nodes = self._parser.get_all_nodes(root)
grid_candidates = [
n
for n in all_nodes
if not n.text
and ("photo" in n.content_desc.lower() or "video" in n.content_desc.lower() or (50000 < n.area < 400000))
]
grid_candidates = []
for n in all_nodes:
rid = (n.resource_id or "").lower()
desc = (n.content_desc or "").lower()
# Structural anchor for Instagram grid items
if "grid_card_layout_container" in rid:
grid_candidates.append(n)
# Fallback for older versions or profile grids if resource-id is missing
elif not n.text and ("photo" in desc or "video" in desc) and (50000 < n.area < 400000):
grid_candidates.append(n)
best = self._evaluator.evaluate_grid_visuals(device, persona_interests, grid_candidates)
if best: