diff --git a/src/clean_agent_preview.py b/src/clean_agent_preview.py index 36e51c764..4a3e981ab 100644 --- a/src/clean_agent_preview.py +++ b/src/clean_agent_preview.py @@ -3004,6 +3004,14 @@ def inline_suggestion_request(user_text): text = str(user_text or '').strip() if inline_text_transformation(text): return False + if re.search( + r"(?:file://)?/workspace/[^\s`\"']+\." + r"(?:avif|bmp|gif|jpe?g|png|svg|tiff?|webp|mp3|m4a|ogg|wav|flac|" + r"aac|mp4|m4v|mov|mkv|avi|webm)\b", + text, + re.I, + ): + return False apply_request = re.search( r'\b(?:apply|accept)\s+(?:the\s+)?(?:change|changes|suggestion|suggestions)\b', text, re.I, diff --git a/src/turn_contract.py b/src/turn_contract.py index 699c86871..9571ecbd4 100644 --- a/src/turn_contract.py +++ b/src/turn_contract.py @@ -4158,7 +4158,7 @@ def requested_capabilities(message: str, history: Iterable = (), *, active_docum re.I, ) media_action = re.search( - r"\b(?:inspect|view|watch|study|look\s+at|analy[sz]e|read|transcribe|caption|" + r"\b(?:inspect|view|watch|review|study|look\s+at|analy[sz]e|read|transcribe|caption|" r"recreate|reproduce|identify|describe|extract)\b|" r"(?:浏览|查看|观看|分析|检查|识别|转录|截图)", raw_text, @@ -4194,9 +4194,17 @@ def requested_capabilities(message: str, history: Iterable = (), *, active_docum families.add("shell_files") if re.search( r"\b(?:preview|render|open|inspect|verify)\b[^.\n]{0,120}" - r"\b(?:page|html|browser|rendered\s+result)\b", + r"\b(?:page|html|browser)\b", raw_text, re.I, + ) or ( + re.search( + r"\b(?:preview|render|open|inspect|verify)\b[^.\n]{0,120}" + r"\brendered\s+result\b", + raw_text, + re.I, + ) + and not re.search(r"\binspect_media\b", raw_text, re.I) ): families.add("search_browser") if re.search( diff --git a/tests/test_clean_agent_preview.py b/tests/test_clean_agent_preview.py index a7208e094..94ad0ada6 100644 --- a/tests/test_clean_agent_preview.py +++ b/tests/test_clean_agent_preview.py @@ -3059,6 +3059,12 @@ def test_inline_suggestion_intent_is_independent_from_document_visibility(): 'create inline suggestions only; do not apply changes.' ) assert not inline_suggestion_request('Apply the suggestions to this document') + assert not inline_suggestion_request( + 'Review the video at /workspace/input/video.mp4 and count every match point.' + ) + assert not inline_suggestion_request( + 'Review the short handheld clip at /workspace/input/video.mp4 and save an index image.' + ) assert not active_editor_suggestion_request(None, 'give suggestions to this document') diff --git a/tests/test_turn_contract.py b/tests/test_turn_contract.py index 2c9079d3b..f497ab288 100644 --- a/tests/test_turn_contract.py +++ b/tests/test_turn_contract.py @@ -4295,6 +4295,20 @@ def test_watch_workspace_video_is_media_not_generic_shell(): ) == {"media_inspection"} +def test_review_workspace_video_is_media_not_document_or_web_review(): + assert requested_capabilities( + "Review the video at /workspace/input/video.mp4, count every match point, " + "and provide the verified totals in the final message." + ) == {"media_inspection"} + + +def test_explicit_media_verification_does_not_require_browser_family(): + assert requested_capabilities( + "First inspect /workspace/input/reference.png. Create /workspace/output.html, " + "then inspect the rendered result using inspect_media on the file or a screenshot." + ) == {"media_inspection", "shell_files"} + + def test_chinese_video_to_image_artifact_keeps_media_and_workspace_tools(): assert requested_capabilities( "请完整浏览 /workspace/input/video.mp4,为每款零食截图并拼成清单图,"