diff --git a/telegram/bot.py b/telegram/bot.py index 98e3ad4..594988e 100644 --- a/telegram/bot.py +++ b/telegram/bot.py @@ -60,6 +60,7 @@ from http_chat_proxy import ( extract_paid_work_order_id, extract_smart_research_goal, post_chat_proxy, + should_attach_structured_market_context, smart_research_command_names, ) @@ -1208,9 +1209,12 @@ async def handle_tagged(update: Update, context: ContextTypes.DEFAULT_TYPE): if AGENT_HTTP_RESEARCH_PROXY_URL and smart_research_goal: payment_gate = _smart_research_payment_gate(msg.chat_id) proxy_research_goal = smart_research_goal - market_context, market_data_audit, market_duration, market_tokens = await _market_context_for_message( - smart_research_goal - ) + if should_attach_structured_market_context(smart_research_goal): + market_context, market_data_audit, market_duration, market_tokens = await _market_context_for_message( + smart_research_goal + ) + else: + market_context, market_data_audit, market_duration, market_tokens = "", {}, 0, [] if market_context: logger.info( "%s smart research added structured market context for %s in %dms", diff --git a/telegram/http_chat_proxy.py b/telegram/http_chat_proxy.py index 88aaaaf..ad71a5a 100644 --- a/telegram/http_chat_proxy.py +++ b/telegram/http_chat_proxy.py @@ -50,6 +50,22 @@ _PAID_WORK_ORDER_ID_RE = re.compile( r"\b((?:sponsored_work_orders|payment_receipts):[a-f0-9]{16,64})\b", re.IGNORECASE, ) +_MARKET_CONTEXT_RE = re.compile( + r"\b(" + r"volume|fdv|fully\s+diluted|market\s+cap|mcap|liquidity|price|chart|" + r"token|coin|pair|pool|dex|dexscreener|birdeye|jupiter|" + r"buy|sell|should\s+i|yes\s+or\s+no" + r")\b", + re.IGNORECASE, +) +_SOCIAL_DISCUSSION_RE = re.compile( + r"\b(twitter|x\.com|x\/twitter|tweet|tweets|social)\b.*" + r"\b(current|latest|recent|discussion|discussions|trend|trends|narrative|sentiment|fault|blame|position|stance)\b" + r"|" + r"\b(current|latest|recent|discussion|discussions|trend|trends|narrative|sentiment|fault|blame|position|stance)\b.*" + r"\b(twitter|x\.com|x\/twitter|tweet|tweets|social)\b", + re.IGNORECASE, +) def smart_research_command_names( @@ -158,6 +174,16 @@ def extract_paid_work_order_id(message: str) -> str | None: return match.group(1) +def should_attach_structured_market_context(message: str) -> bool: + """Return true only for explicit market-data questions, not social narrative research.""" + text = message.strip() + if not text: + return False + if _SOCIAL_DISCUSSION_RE.search(text): + return False + return bool(_MARKET_CONTEXT_RE.search(text)) + + def build_smart_research_proxy_payload( *, research_goal: str, diff --git a/tests/test_telegram_leo_x402_bridge.py b/tests/test_telegram_leo_x402_bridge.py index ec08a90..2ba8412 100644 --- a/tests/test_telegram_leo_x402_bridge.py +++ b/tests/test_telegram_leo_x402_bridge.py @@ -18,6 +18,7 @@ from http_chat_proxy import ( # noqa: E402 extract_paid_work_order_id, extract_chat_proxy_reply, extract_smart_research_goal, + should_attach_structured_market_context, smart_research_command_names, ) from market_data import extract_market_data_tokens, format_price_context # noqa: E402 @@ -238,6 +239,20 @@ def test_market_data_token_extraction_maps_natural_market_question(): assert extract_market_data_tokens(message) == ["OMFG", "AVICI", "UMBRA"] +@pytest.mark.parametrize( + ("message", "expected"), + [ + ("what is the volume and fdv of omnipair avici umbra? should i buy them yes or no", True), + ("show me price and liquidity for AVICI", True), + ("what are the current discussions about MetaDAO Ranger Finance on Twitter?", False), + ("who was at fault for Ranger according to Twitter?", False), + ("how much revenue does MetaDAO make today?", False), + ], +) +def test_should_attach_structured_market_context_only_for_market_data_intent(message, expected): + assert should_attach_structured_market_context(message) is expected + + def test_market_data_context_formats_dexscreener_fdv_volume_liquidity(): context = format_price_context( {