Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion pyflowlauncher/launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ async def run(self, dispatch: Callable[[str, list], Awaitable[Any]]) -> None:
# The host sends ("query", [query, Settings.Inner]).
if len(params) > 1 and isinstance(params[1], dict):
self._settings = params[1]
params = [params[0].get('search') or params[0].get('trimmedQuery', '')]
# Query.search excludes the action keyword; trimmedQuery/rawQuery
# include it, so they must never be used as the search string.
params = [params[0].get('search') or '']
elif method != 'context_menu' and len(params) == 1 and isinstance(params[0], list):
# Actions: the host calls RPC.InvokeAsync(method, argument: Parameters),
# which wraps the whole Parameters list as one positional argument
Expand Down
19 changes: 19 additions & 0 deletions tests/integration/test_v2_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,25 @@ def test_empty_search_string(self):
])
assert query_response(responses, 1)['result']['result'][0]['Title'] == 'Hello, World!'

def test_action_keyword_not_leaked_into_search(self):
"""Typing only the action keyword sends {'search': '', 'trimmedQuery': 'kw'};
the handler must receive '' — not fall back to the keyword-bearing trimmedQuery."""
received = []
plugin = Plugin(launcher=FlowLauncherV2())

@plugin.on_method
def query(q: str):
received.append(q)
yield Result(title="ok")

run(plugin, [
{'id': 1, 'method': 'query',
'params': [{'search': '', 'trimmedQuery': 'kw', 'rawQuery': 'kw',
'actionKeyword': 'kw'}, {}]},
{'id': 2, 'method': 'close', 'params': []},
])
assert received == ['']


class TestV2Lifecycle:

Expand Down
Loading