diff --git a/src/clean_agent_preview.py b/src/clean_agent_preview.py index 3ec0556e1..8ef6ead64 100644 --- a/src/clean_agent_preview.py +++ b/src/clean_agent_preview.py @@ -3156,7 +3156,8 @@ def requested_web_source_links(user_text): return bool(re.search( r'\b(?:return|give|show|include|provide|cite|find)\b.{0,35}\b(?:source\s+)?links?\b' r'|\b(?:\d+|one|two|three|four|five)\s+(?:official\s+)?(?:source\s+)?links?\b' - r'|\bofficial\s+source\b', + r'|\bofficial\s+source\b' + r'|\b(?:find|locate|get|download)\b.{0,80}\b(?:manual|guide|handbook|pdf)\b.{0,40}\b(?:online|official)\b', str(user_text or ''), re.IGNORECASE, )) @@ -3184,6 +3185,7 @@ def web_source_links(raw, *, max_items=1, prefer_official=False, query=''): secondary_hosts = { 'wikipedia.org', 'reddit.com', 'medium.com', 'youtube.com', 'facebook.com', 'linkedin.com', 'x.com', 'twitter.com', + 'manuals.plus', 'manualslib.com', } primary = [] official_domains = official_domains_for_text(query) @@ -3196,7 +3198,7 @@ def web_source_links(raw, *, max_items=1, prefer_official=False, query=''): host == domain or host.endswith('.' + domain) for domain in official_domains ) - if query_host_match or (not official_domains and host.endswith(('.gov', '.edu'))): + if query_host_match or not official_domains: primary.append(row) rows = primary links = [] @@ -3350,7 +3352,7 @@ def requested_web_link_limit(user_text): re.IGNORECASE, ) if not match: - return None + return 1 if requested_web_source_links(text) else None token = (match.group(1) or match.group(2)).casefold() return max(1, min(5, int(token) if token.isdigit() else words[token])) diff --git a/tests/test_clean_agent_preview.py b/tests/test_clean_agent_preview.py index 8b4bba04b..f54cfca0e 100644 --- a/tests/test_clean_agent_preview.py +++ b/tests/test_clean_agent_preview.py @@ -1913,6 +1913,31 @@ def test_web_fetch_collapses_single_and_batch_url_fields_without_losing_targets( } +def test_manual_locator_prefers_manufacturer_link_and_requests_one_result(): + from src.clean_agent_preview import ( + requested_web_link_limit, requested_web_source_links, web_source_links, + ) + + prompt = 'Find the official WIKING Miro 3 English manual online' + raw = ( + '[1] WIKING Miro manual\nhttps://manuals.plus/wiking-miro\n' + '[2] WIKING Miro 3 manuals\nhttps://www.manualslib.com/wiking-miro-3\n' + '[3] WIKING Miro English manual PDF\n' + 'https://www.hwam.com/media/wiking/miro-en.pdf\n' + ) + + assert requested_web_source_links(prompt) + assert requested_web_link_limit(prompt) == 1 + assert web_source_links( + raw, max_items=1, prefer_official=True, query=prompt, + ) == [ + ( + 'https://www.hwam.com/media/wiking/miro-en.pdf', + '[Source: WIKING Miro English manual PDF](https://www.hwam.com/media/wiking/miro-en.pdf)', + ) + ] + + def test_preview_allows_only_reversible_client_local_ui_control(): assert preview_call_allowed( 'ui_control', {'action': 'open_panel', 'name': 'gallery'}, 'open gallery'