From 6458b43aed9b0e9c5daaff37e57d7f451f6b5124 Mon Sep 17 00:00:00 2001 From: pewdiepie-archdaemon Date: Thu, 17 Sep 2026 21:32:56 +0000 Subject: [PATCH] Require explicit link-only intent before bypassing answer synthesis --- src/clean_agent_preview.py | 17 ++++++++++++----- tests/test_search_observation_budget.py | 19 +++++++++++++++++-- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/clean_agent_preview.py b/src/clean_agent_preview.py index ccc003345..1ec0ebf0f 100644 --- a/src/clean_agent_preview.py +++ b/src/clean_agent_preview.py @@ -3278,6 +3278,17 @@ def requested_web_source_links(user_text): )) +def source_link_only_request(user_text): + """Only bypass synthesis for a complete, explicit link-return command.""" + return bool(re.fullmatch( + r'\s*(?:please\s+)?(?:return|give|show|provide|find)\s+(?:me\s+)?' + r'(?:(?:only|just)\s+)?(?:(?:\d+|a|one|two|three|four|five)\s+)?' + r'(?:official\s+)?(?:source\s+)?links?' + r'(?:\s+(?:for|to)\s+[^\n.!?]+)?[.!?]*\s*', + str(user_text or ''), re.I, + )) and not re.search(r'\b(?:and|then|explain|compare|summari[sz]e)\b', str(user_text or ''), re.I) + + def web_source_links(raw, *, max_items=1, prefer_official=False, query=''): """Extract stable title/URL pairs from the web tool's source preamble.""" text = str(raw or '') @@ -5309,11 +5320,7 @@ async def stream_preview(*, endpoint_url, model, messages, headers, turn_contrac prefer_official=official_requested, query=args.get('query', ''), ) - source_only_request = not re.search( - r'\b(?:latest|latset|current|recent|today|compare|explain|summari[sz]e)\b', - direct_user_text, re.I, - ) - if requested_links and source_links and source_only_request: + if requested_links and source_links and source_link_only_request(direct_user_text): # For an exact requested link count, evidence owns # the final rendering so model prose cannot add a # wrong or duplicate source. diff --git a/tests/test_search_observation_budget.py b/tests/test_search_observation_budget.py index cda66631d..8ee1769ef 100644 --- a/tests/test_search_observation_budget.py +++ b/tests/test_search_observation_budget.py @@ -4,6 +4,20 @@ import json import pytest +@pytest.mark.parametrize('prompt,only', [ + ('Return one official source link', True), + ('Find two source links for quantum computing', True), + ('Give me just one link', True), + ('more about the second story, with sources', False), + ('why is this important? sources pls', False), + ('Find two links and explain the tradeoffs', False), + ('Find official English manual for Sony WH-1000XM5', False), +]) +def test_source_only_rendering_requires_positive_link_only_intent(prompt, only): + from src.clean_agent_preview import source_link_only_request + assert source_link_only_request(prompt) == only + + def test_forced_search_dispatch_preserves_schema_without_mutating_request(): from src.clean_agent_preview import search_tool_choice_request search = {'type': 'function', 'function': {'name': 'web_search', 'parameters': {'required': ['query']}}} @@ -70,7 +84,8 @@ def test_external_edits_are_not_mistaken_for_inline_text(prompt): @pytest.mark.asyncio @pytest.mark.parametrize('repair_missing_link', [False, True]) -async def test_runtime_does_not_append_unverified_search_result_as_citation(monkeypatch, repair_missing_link): +@pytest.mark.parametrize('prompt', ['latest Python version? official source please', 'more about the second story, with sources']) +async def test_runtime_does_not_append_unverified_search_result_as_citation(monkeypatch, repair_missing_link, prompt): import src.clean_agent_preview as runtime from src.tool_schemas import FUNCTION_TOOL_SCHEMAS from src.tool_policy import ToolPolicy @@ -107,7 +122,7 @@ async def test_runtime_does_not_append_unverified_search_result_as_citation(monk contract = resolve_full_inventory_contract(schemas=schemas, policy=ToolPolicy()) raw = [chunk async for chunk in runtime.stream_preview( endpoint_url='http://test', model='test', - messages=[{'role': 'user', 'content': 'latest Python version? official source please'}], + messages=[{'role': 'user', 'content': prompt}], headers={}, turn_contract=contract, session_id='test', owner='test', disabled_tools=set(), tool_policy=ToolPolicy(), max_rounds=3 if repair_missing_link else 2, )]