feat(search): add CLI web_search command and Tavily bearer auth
Signed-off-by: Asklv <boironic@gmail.com>
This commit is contained in:
@@ -608,6 +608,78 @@ static int cmd_tool_exec(int argc, char **argv)
|
|||||||
return (err == ESP_OK) ? 0 : 1;
|
return (err == ESP_OK) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- web_search command --- */
|
||||||
|
static struct {
|
||||||
|
struct arg_str *query;
|
||||||
|
struct arg_end *end;
|
||||||
|
} web_search_args;
|
||||||
|
|
||||||
|
static bool json_escape_string(const char *in, char *out, size_t out_size)
|
||||||
|
{
|
||||||
|
if (!in || !out || out_size == 0) return false;
|
||||||
|
size_t o = 0;
|
||||||
|
for (size_t i = 0; in[i] != '\0'; ++i) {
|
||||||
|
const char c = in[i];
|
||||||
|
const char *esc = NULL;
|
||||||
|
switch (c) {
|
||||||
|
case '\\': esc = "\\\\"; break;
|
||||||
|
case '\"': esc = "\\\""; break;
|
||||||
|
case '\n': esc = "\\n"; break;
|
||||||
|
case '\r': esc = "\\r"; break;
|
||||||
|
case '\t': esc = "\\t"; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
if (esc) {
|
||||||
|
size_t n = strlen(esc);
|
||||||
|
if (o + n >= out_size) return false;
|
||||||
|
memcpy(&out[o], esc, n);
|
||||||
|
o += n;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((unsigned char)c < 0x20) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (o + 1 >= out_size) return false;
|
||||||
|
out[o++] = c;
|
||||||
|
}
|
||||||
|
out[o] = '\0';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmd_web_search(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int nerrors = arg_parse(argc, argv, (void **)&web_search_args);
|
||||||
|
if (nerrors != 0) {
|
||||||
|
arg_print_errors(stderr, web_search_args.end, argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char escaped_query[512];
|
||||||
|
if (!json_escape_string(web_search_args.query->sval[0], escaped_query, sizeof(escaped_query))) {
|
||||||
|
printf("Query too long.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char input_json[640];
|
||||||
|
int n = snprintf(input_json, sizeof(input_json), "{\"query\":\"%s\"}", escaped_query);
|
||||||
|
if (n <= 0 || n >= (int)sizeof(input_json)) {
|
||||||
|
printf("Query too long.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *output = calloc(1, 4096);
|
||||||
|
if (!output) {
|
||||||
|
printf("Out of memory.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t err = tool_web_search_execute(input_json, output, 4096);
|
||||||
|
printf("web_search status: %s\n", esp_err_to_name(err));
|
||||||
|
printf("%s\n", output[0] ? output : "(empty)");
|
||||||
|
free(output);
|
||||||
|
return (err == ESP_OK) ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* --- restart command --- */
|
/* --- restart command --- */
|
||||||
static int cmd_restart(int argc, char **argv)
|
static int cmd_restart(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@@ -896,6 +968,17 @@ esp_err_t serial_cli_init(void)
|
|||||||
};
|
};
|
||||||
esp_console_cmd_register(&tool_exec_cmd);
|
esp_console_cmd_register(&tool_exec_cmd);
|
||||||
|
|
||||||
|
/* web_search */
|
||||||
|
web_search_args.query = arg_str1(NULL, NULL, "<query>", "Search query");
|
||||||
|
web_search_args.end = arg_end(1);
|
||||||
|
esp_console_cmd_t web_search_cmd = {
|
||||||
|
.command = "web_search",
|
||||||
|
.help = "Run web search tool directly (e.g. web_search \"latest esp-idf\")",
|
||||||
|
.func = &cmd_web_search,
|
||||||
|
.argtable = &web_search_args,
|
||||||
|
};
|
||||||
|
esp_console_cmd_register(&web_search_cmd);
|
||||||
|
|
||||||
/* restart */
|
/* restart */
|
||||||
esp_console_cmd_t restart_cmd = {
|
esp_console_cmd_t restart_cmd = {
|
||||||
.command = "restart",
|
.command = "restart",
|
||||||
|
|||||||
@@ -190,7 +190,6 @@ static char *build_tavily_payload(const char *query)
|
|||||||
{
|
{
|
||||||
cJSON *root = cJSON_CreateObject();
|
cJSON *root = cJSON_CreateObject();
|
||||||
if (!root) return NULL;
|
if (!root) return NULL;
|
||||||
cJSON_AddStringToObject(root, "api_key", s_tavily_key);
|
|
||||||
cJSON_AddStringToObject(root, "query", query);
|
cJSON_AddStringToObject(root, "query", query);
|
||||||
cJSON_AddNumberToObject(root, "max_results", SEARCH_RESULT_COUNT);
|
cJSON_AddNumberToObject(root, "max_results", SEARCH_RESULT_COUNT);
|
||||||
cJSON_AddBoolToObject(root, "include_answer", false);
|
cJSON_AddBoolToObject(root, "include_answer", false);
|
||||||
@@ -315,6 +314,9 @@ static esp_err_t tavily_search_direct(const char *query, search_buf_t *sb)
|
|||||||
esp_http_client_set_method(client, HTTP_METHOD_POST);
|
esp_http_client_set_method(client, HTTP_METHOD_POST);
|
||||||
esp_http_client_set_header(client, "Accept", "application/json");
|
esp_http_client_set_header(client, "Accept", "application/json");
|
||||||
esp_http_client_set_header(client, "Content-Type", "application/json");
|
esp_http_client_set_header(client, "Content-Type", "application/json");
|
||||||
|
char auth[192];
|
||||||
|
snprintf(auth, sizeof(auth), "Bearer %s", s_tavily_key);
|
||||||
|
esp_http_client_set_header(client, "Authorization", auth);
|
||||||
esp_http_client_set_post_field(client, payload, strlen(payload));
|
esp_http_client_set_post_field(client, payload, strlen(payload));
|
||||||
|
|
||||||
esp_err_t err = esp_http_client_perform(client);
|
esp_err_t err = esp_http_client_perform(client);
|
||||||
@@ -347,9 +349,10 @@ static esp_err_t tavily_search_via_proxy(const char *query, search_buf_t *sb)
|
|||||||
"Host: api.tavily.com\r\n"
|
"Host: api.tavily.com\r\n"
|
||||||
"Accept: application/json\r\n"
|
"Accept: application/json\r\n"
|
||||||
"Content-Type: application/json\r\n"
|
"Content-Type: application/json\r\n"
|
||||||
|
"Authorization: Bearer %s\r\n"
|
||||||
"Content-Length: %d\r\n"
|
"Content-Length: %d\r\n"
|
||||||
"Connection: close\r\n\r\n",
|
"Connection: close\r\n\r\n",
|
||||||
(int)strlen(payload));
|
s_tavily_key, (int)strlen(payload));
|
||||||
|
|
||||||
if (proxy_conn_write(conn, header, hlen) < 0 ||
|
if (proxy_conn_write(conn, header, hlen) < 0 ||
|
||||||
proxy_conn_write(conn, payload, strlen(payload)) < 0) {
|
proxy_conn_write(conn, payload, strlen(payload)) < 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user