[Bugfix][Responses] Fix browser.find action type (#55305)
Signed-off-by: nicole-lihui <nicole.li@daocloud.io> Co-authored-by: Chauncey <chaunceyjiang@gmail.com>
Nicole LiHui 🥜 committed
Sep 11, 2026 at 20:07 UTC
7ef4d9bfed6311e3b78a40abb4a8bb6a2fc741b0
4 files changed
+46
-2
tests/entrypoints/openai/responses/test_harmony_utils.py
+17
@@ -273,6 +273,23 @@ class TestHarmonyToResponseOutput:
273
assert output_items[0].action.type == "search"
274
assert output_items[0].action.query == "cursor:weather in San Francisco"
275
276
+ def test_browser_find_recipient_uses_responses_action_type(self):
277
+ """browser.find must use the Responses API find_in_page action type."""
278
+ message = (
279
+ Message.from_role_and_content(
280
+ Role.ASSISTANT, '{"pattern": "vLLM", "cursor": 42}'
281
+ )
282
+ .with_channel("analysis")
283
+ .with_recipient("browser.find")
284
+ )
285
+
286
+ output_items = harmony_to_response_output(message, frozenset())
287
+
288
+ assert len(output_items) == 1
289
+ assert isinstance(output_items[0], ResponseFunctionWebSearch)
290
+ assert output_items[0].action.type == "find_in_page"
291
+ assert output_items[0].action.pattern == "vLLM"
292
+
293
def test_commentary_with_empty_content_and_no_recipient(self):
294
"""Test edge case: empty commentary with recipient=None."""
295
message = Message.from_role_and_content(Role.ASSISTANT, "")
tests/entrypoints/openai/responses/test_streaming_events.py
+27
@@ -1,6 +1,9 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4
+from openai.types.responses import ResponseFunctionWebSearch
5
+from openai_harmony import Message, Role
6
+
7
from vllm.entrypoints.generate.base.protocol import (
8
DeltaFunctionCall,
9
DeltaMessage,
@@ -8,11 +11,35 @@ from vllm.entrypoints.generate.base.protocol import (
11
)
12
from vllm.entrypoints.openai.responses.streaming_events import (
13
SimpleStreamingEventProcessor,
14
+ StreamingState,
15
_StateType,
16
+ emit_browser_tool_events,
17
split_delta,
18
)
19
20
21
+def test_browser_find_uses_responses_action_type():
22
+ """Both streaming output items must use the Responses find action type."""
23
+ message = (
24
+ Message.from_role_and_content(
25
+ Role.ASSISTANT, '{"pattern": "vLLM", "cursor": 42}'
26
+ )
27
+ .with_channel("analysis")
28
+ .with_recipient("browser.find")
29
+ )
30
+
31
+ events = emit_browser_tool_events(message, StreamingState())
32
+
33
+ added, done = events[0], events[-1]
34
+ assert added.type == "response.output_item.added"
35
+ assert done.type == "response.output_item.done"
36
+ for event in (added, done):
37
+ assert isinstance(event.item, ResponseFunctionWebSearch)
38
+ assert event.item.action.type == "find_in_page"
39
+ assert event.item.action.pattern == "vLLM"
40
+ assert event.item.action.url == "cursor:42"
41
+
42
+
43
def _make_tool_call(
44
index: int, name: str | None = None, arguments: str | None = None
45
) -> DeltaToolCall:
vllm/entrypoints/openai/responses/harmony.py
+1
-1
@@ -303,7 +303,7 @@ def _parse_browser_tool_call(message: Message, recipient: str) -> ResponseOutput
303
action = ActionFind(
304
pattern=browser_call.get("pattern", ""),
305
url=f"cursor:{browser_call.get('url', '')}",
306
- type="find",
306
+ type="find_in_page",
307
)
308
else:
309
raise ValueError(f"Unknown browser action: {recipient}")
vllm/entrypoints/openai/responses/streaming_events.py
+1
-1
@@ -667,7 +667,7 @@ def emit_browser_tool_events(
667
)
668
elif function_name == "find":
669
action = response_function_web_search.ActionFind(
670
- type="find",
670
+ type="find_in_page",
671
pattern=parsed_args["pattern"],
672
# TODO: translate to url
673
url=f"cursor:{parsed_args.get('cursor', '')}",