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