From 7ef4d9bfed6311e3b78a40abb4a8bb6a2fc741b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicole=20LiHui=20=F0=9F=A5=9C?= Date: Fri, 11 Sep 2026 20:07:04 +0800 Subject: [PATCH] [Bugfix][Responses] Fix browser.find action type (#55305) Signed-off-by: nicole-lihui Co-authored-by: Chauncey --- .../openai/responses/test_harmony_utils.py | 17 ++++++++++++ .../openai/responses/test_streaming_events.py | 27 +++++++++++++++++++ vllm/entrypoints/openai/responses/harmony.py | 2 +- .../openai/responses/streaming_events.py | 2 +- 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/tests/entrypoints/openai/responses/test_harmony_utils.py b/tests/entrypoints/openai/responses/test_harmony_utils.py index 14e174dec0..54c034de44 100644 --- a/tests/entrypoints/openai/responses/test_harmony_utils.py +++ b/tests/entrypoints/openai/responses/test_harmony_utils.py @@ -273,6 +273,23 @@ class TestHarmonyToResponseOutput: assert output_items[0].action.type == "search" assert output_items[0].action.query == "cursor:weather in San Francisco" + def test_browser_find_recipient_uses_responses_action_type(self): + """browser.find must use the Responses API find_in_page action type.""" + message = ( + Message.from_role_and_content( + Role.ASSISTANT, '{"pattern": "vLLM", "cursor": 42}' + ) + .with_channel("analysis") + .with_recipient("browser.find") + ) + + output_items = harmony_to_response_output(message, frozenset()) + + assert len(output_items) == 1 + assert isinstance(output_items[0], ResponseFunctionWebSearch) + assert output_items[0].action.type == "find_in_page" + assert output_items[0].action.pattern == "vLLM" + def test_commentary_with_empty_content_and_no_recipient(self): """Test edge case: empty commentary with recipient=None.""" message = Message.from_role_and_content(Role.ASSISTANT, "") diff --git a/tests/entrypoints/openai/responses/test_streaming_events.py b/tests/entrypoints/openai/responses/test_streaming_events.py index 6b649aadad..e1a8bf46f6 100644 --- a/tests/entrypoints/openai/responses/test_streaming_events.py +++ b/tests/entrypoints/openai/responses/test_streaming_events.py @@ -1,6 +1,9 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project +from openai.types.responses import ResponseFunctionWebSearch +from openai_harmony import Message, Role + from vllm.entrypoints.generate.base.protocol import ( DeltaFunctionCall, DeltaMessage, @@ -8,11 +11,35 @@ from vllm.entrypoints.generate.base.protocol import ( ) from vllm.entrypoints.openai.responses.streaming_events import ( SimpleStreamingEventProcessor, + StreamingState, _StateType, + emit_browser_tool_events, split_delta, ) +def test_browser_find_uses_responses_action_type(): + """Both streaming output items must use the Responses find action type.""" + message = ( + Message.from_role_and_content( + Role.ASSISTANT, '{"pattern": "vLLM", "cursor": 42}' + ) + .with_channel("analysis") + .with_recipient("browser.find") + ) + + events = emit_browser_tool_events(message, StreamingState()) + + added, done = events[0], events[-1] + assert added.type == "response.output_item.added" + assert done.type == "response.output_item.done" + for event in (added, done): + assert isinstance(event.item, ResponseFunctionWebSearch) + assert event.item.action.type == "find_in_page" + assert event.item.action.pattern == "vLLM" + assert event.item.action.url == "cursor:42" + + def _make_tool_call( index: int, name: str | None = None, arguments: str | None = None ) -> DeltaToolCall: diff --git a/vllm/entrypoints/openai/responses/harmony.py b/vllm/entrypoints/openai/responses/harmony.py index 4e62828fd1..461ce1f3fa 100644 --- a/vllm/entrypoints/openai/responses/harmony.py +++ b/vllm/entrypoints/openai/responses/harmony.py @@ -303,7 +303,7 @@ def _parse_browser_tool_call(message: Message, recipient: str) -> ResponseOutput action = ActionFind( pattern=browser_call.get("pattern", ""), url=f"cursor:{browser_call.get('url', '')}", - type="find", + type="find_in_page", ) else: raise ValueError(f"Unknown browser action: {recipient}") diff --git a/vllm/entrypoints/openai/responses/streaming_events.py b/vllm/entrypoints/openai/responses/streaming_events.py index b45264f8c3..40abc45b42 100644 --- a/vllm/entrypoints/openai/responses/streaming_events.py +++ b/vllm/entrypoints/openai/responses/streaming_events.py @@ -667,7 +667,7 @@ def emit_browser_tool_events( ) elif function_name == "find": action = response_function_web_search.ActionFind( - type="find", + type="find_in_page", pattern=parsed_args["pattern"], # TODO: translate to url url=f"cursor:{parsed_args.get('cursor', '')}",