vectorSearch() is never called for embedding-free VDB providers
## Problem `doSearch()` calls `vectorSearch()` only when `$vector_input` is non-empty: ```php if (!empty($vector_input)) { $response = $vdb_client->vectorSearch(...$params); } else { $response = $vdb_client->querySearch(...$params); } ``` VDB providers that do not use embeddings (LLM reasoning, BM25, keyword trees, etc.) always have an empty `$vector_input`. So `querySearch()` is always called instead of `vectorSearch()`. `querySearch()` is for browse queries with no search terms. It does not receive the query text. A search for "climate change" calls `querySearch()` with no keywords and returns nothing, regardless of how well the provider implements `vectorSearch()`. **It is not currently possible to build a working embedding-free VDB provider against `AiVdbProviderSearchApiInterface` without patching this file.** ## Steps to reproduce 1. Install `ai_search`. 2. Implement a VDB provider that uses `vectorSearch()` but generates no embeddings. The provider extracts query text from the `$query` object directly inside `vectorSearch()`. 3. Configure a Search API index with this provider. 4. Submit a text search query. 5. Observe: `querySearch()` is called, the provider's `vectorSearch()` never runs, results are empty. ## Proposed resolution Check for search keys in addition to `$vector_input` when deciding which method to call. `querySearch()` should only be called for queries with genuinely no keywords. ```php $keys = $query->getKeys(); $has_keys = !empty($keys) && !(is_array($keys) && count(array_diff_key($keys, ['#conjunction' => TRUE])) === 0); if (!empty($vector_input) || $has_keys) { $params['vector_input'] = $vector_input; $params['query'] = $query; $response = $vdb_client->vectorSearch(...$params); } else { $response = $vdb_client->querySearch(...$params); } ``` This does not change anything for embedding-based providers. They have both `$vector_input` and keys, so they take the same branch as before. Embedding-free providers now reach `vectorSearch()` via the `$has_keys` branch. Note: the `$params['vector_input']` and `$params['query']` assignments are moved inside the `vectorSearch()` branch here. That is intentional and also fixes a related crash described in issue https://git.drupalcode.org/project/ai_search/-/work_items/3584028. ## Notes Found while building [ai_pageindex](https://www.drupal.org/project/ai_pageindex), a VDB provider that uses LLM reasoning over document trees instead of embeddings. This was the root cause of all searches returning empty results. I did a quick search of the issue queue and did not find an identical report. If this is a duplicate, please share the link and close this one.
issue