diff --git a/main/tools/tool_web_search.c b/main/tools/tool_web_search.c index d1b8ecf5..fe9daeef 100644 --- a/main/tools/tool_web_search.c +++ b/main/tools/tool_web_search.c @@ -15,8 +15,13 @@ static const char *TAG = "web_search"; static char s_search_key[128] = {0}; -#define SEARCH_BUF_SIZE (16 * 1024) +#define SEARCH_BUF_SIZE (64 * 1024) #define SEARCH_RESULT_COUNT 5 +#define STR(x) #x +#define XSTR(x) STR(x) + +static const char s_brave_url[] = "https://api.search.brave.com"; +static const char s_path_template[] = "/res/v1/web/search?count=" XSTR(SEARCH_RESULT_COUNT) "&result_filter=web&q="; /* ── Response accumulator ─────────────────────────────────────── */ @@ -35,6 +40,9 @@ static esp_err_t http_event_handler(esp_http_client_event_t *evt) memcpy(sb->data + sb->len, evt->data, evt->data_len); sb->len += evt->data_len; sb->data[sb->len] = '\0'; + } else { + ESP_LOGW(TAG, "Response too large; dropped %d bytes (buf %zu/%zu)", + evt->data_len, sb->len, sb->cap); } } return ESP_OK; @@ -168,7 +176,7 @@ static esp_err_t search_via_proxy(const char *path, search_buf_t *sb) proxy_conn_t *conn = proxy_conn_open("api.search.brave.com", 443, 15000); if (!conn) return ESP_ERR_HTTP_CONNECT; - char header[512]; + char header[768]; int hlen = snprintf(header, sizeof(header), "GET %s HTTP/1.1\r\n" "Host: api.search.brave.com\r\n" @@ -247,19 +255,26 @@ esp_err_t tool_web_search_execute(const char *input_json, char *output, size_t o ESP_LOGI(TAG, "Searching: %s", query->valuestring); - /* Build URL */ - char encoded_query[256]; - url_encode(query->valuestring, encoded_query, sizeof(encoded_query)); - cJSON_Delete(input); + /* Note: queries over 256 characters long are truncated */ + size_t query_len = strnlen(query->valuestring, 256) * 3 + 3; // worse case URL-encoding expansion + char *url = calloc(1, sizeof(s_brave_url) + sizeof(s_path_template) + query_len); + if (!url) { + cJSON_Delete(input); + snprintf(output, output_size, "Error: Out of memory"); + return ESP_ERR_NO_MEM; + } - char path[384]; - snprintf(path, sizeof(path), - "/res/v1/web/search?q=%s&count=%d", encoded_query, SEARCH_RESULT_COUNT); + /* Build Query */ + memcpy(url, s_brave_url, sizeof(s_brave_url)); + memcpy(url + sizeof(s_brave_url) - 1, s_path_template, sizeof(s_path_template)); + url_encode(query->valuestring, url + sizeof(s_brave_url) + sizeof(s_path_template) - 2, query_len); + cJSON_Delete(input); /* Allocate response buffer from PSRAM */ search_buf_t sb = {0}; sb.data = heap_caps_calloc(1, SEARCH_BUF_SIZE, MALLOC_CAP_SPIRAM); if (!sb.data) { + free(url); snprintf(output, output_size, "Error: Out of memory"); return ESP_ERR_NO_MEM; } @@ -268,12 +283,11 @@ esp_err_t tool_web_search_execute(const char *input_json, char *output, size_t o /* Make HTTP request */ esp_err_t err; if (http_proxy_is_enabled()) { - err = search_via_proxy(path, &sb); + err = search_via_proxy(url + sizeof(s_brave_url) - 1, &sb); // just the path portion } else { - char url[512]; - snprintf(url, sizeof(url), "https://api.search.brave.com%s", path); err = search_direct(url, &sb); } + free(url); if (err != ESP_OK) { free(sb.data);