feat: add Kagi as web search engine provider (#1331)

This commit is contained in:
Hanchin Hsieh
2025-02-21 11:45:23 +08:00
committed by GitHub
parent 581e61fae1
commit 40ab7ef537
3 changed files with 54 additions and 2 deletions

View File

@@ -620,16 +620,25 @@ Therefore, I have adopted Cursors method to implement planning applying. For
## Web Search Engines
Avante's tools include some web search engines, currently support [tavily](https://tavily.com/), [serpapi](https://serpapi.com/), [searchapi](https://www.searchapi.io/) and google's [programmable search engine](https://developers.google.com/custom-search/v1/overview). The default is tavily, and can be changed through configuring `Config.web_search_engine.provider`:
Avante's tools include some web search engines, currently support:
- [tavily](https://tavily.com/)
- [serpapi](https://serpapi.com/)
- [searchapi](https://www.searchapi.io/)
- google's [programmable search engine](https://developers.google.com/custom-search/v1/overview)
- [kagi](https://help.kagi.com/kagi/api/search.html)
The default is tavily, and can be changed through configuring `Config.web_search_engine.provider`:
```lua
web_search_engine = {
provider = "tavily", -- tavily, serpapi, searchapi or google
provider = "tavily", -- tavily, serpapi, searchapi, google or kagi
}
```
You need to set the environment variable `TAVILY_API_KEY` , `SERPAPI_API_KEY`, `SEARCHAPI_API_KEY` to use tavily or serpapi or searchapi.
To use google, set the `GOOGLE_SEARCH_API_KEY` as the [API key](https://developers.google.com/custom-search/v1/overview), and `GOOGLE_SEARCH_ENGINE_ID` as the [search engine](https://programmablesearchengine.google.com) ID.
To use kagi, set the `KAGI_API_KEY` as the [API Token](https://kagi.com/settings?p=api).
## Disable Tools

View File

@@ -125,6 +125,32 @@ M._defaults = {
return "", nil
end,
},
kagi = {
api_key_name = "KAGI_API_KEY",
extra_request_body = {
limit = "10",
},
---@type WebSearchEngineProviderResponseBodyFormatter
format_response_body = function(body)
if body.data ~= nil then
local jsn = vim
.iter(body.data)
:map(
function(result)
return {
title = result.title,
url = result.url,
snippet = result.snippet,
}
end
)
:take(10)
:totable()
return vim.json.encode(jsn), nil
end
return "", nil
end,
},
},
},
---@type AvanteSupportedProvider

View File

@@ -379,6 +379,23 @@ function M.web_search(opts, on_log)
if resp.status ~= 200 then return nil, "Error: " .. resp.body end
local jsn = vim.json.decode(resp.body)
return search_engine.format_response_body(jsn)
elseif provider_type == "kagi" then
local query_params = vim.tbl_deep_extend("force", {
q = opts.query,
}, search_engine.extra_request_body)
local query_string = ""
for key, value in pairs(query_params) do
query_string = query_string .. key .. "=" .. vim.uri_encode(value) .. "&"
end
local resp = curl.get("https://kagi.com/api/v0/search?" .. query_string, {
headers = {
["Authorization"] = "Bot " .. api_key,
["Content-Type"] = "application/json",
},
})
if resp.status ~= 200 then return nil, "Error: " .. resp.body end
local jsn = vim.json.decode(resp.body)
return search_engine.format_response_body(jsn)
end
end