From 1c36cfc8120681ffe3261cba83f00338630da606 Mon Sep 17 00:00:00 2001 From: doodleEsc <1056315827@qq.com> Date: Mon, 7 Apr 2025 15:05:22 +0800 Subject: [PATCH] fix: enhance web search functionality with proxy support (#1823) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: enhance web search functionality with proxy support - Remove unnecessary blank line in README.md - Add missing closing details tag in both README.md and README_zh.md - Add proxy support to the web search engine configuration in config.lua - Ensure the web search function uses the proxy setting when available in init.lua - Fix a potential nil access in the response body format check in config.lua Signed-off-by: 范立洲 * [pre-commit.ci lite] apply automatic fixes --------- Signed-off-by: 范立洲 Co-authored-by: 范立洲 Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- README.md | 29 +++++---- README_zh.md | 114 ++++++++++++++++++---------------- lua/avante/config.lua | 1 + lua/avante/llm_tools/init.lua | 37 +++++++---- 4 files changed, 101 insertions(+), 80 deletions(-) diff --git a/README.md b/README.md index 515ab4a..a28d73e 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,6 @@ [查看中文版](README_zh.md) - > [!NOTE] > > 🥰 This project is undergoing rapid iterations, and many exciting features will be added successively. Stay tuned! @@ -436,6 +435,7 @@ _See [config.lua#L9](./lua/avante/config.lua) for the full config_ }, } ``` + ## Blink.cmp users @@ -641,6 +641,7 @@ The following key bindings are available for use with `avante.nvim`: ### Neotree shortcut In the neotree sidebar, you can also add a new keyboard shortcut to quickly add `file/folder` to `Avante Selected Files`. +
Neotree configuration @@ -685,6 +686,7 @@ return { }, } ``` +
## Commands @@ -692,17 +694,17 @@ return { | Command | Description | Examples | | ---------------------------------- | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | | `:AvanteAsk [question] [position]` | Ask AI about your code. Optional `position` set window position and `ask` enable/disable direct asking mode | `:AvanteAsk position=right Refactor this code here` | -| `:AvanteBuild` | Build dependencies for the project | | -| `:AvanteChat` | Start a chat session with AI about your codebase. Default is `ask`=false | | -| `:AvanteClear` | Clear the chat history | | -| `:AvanteEdit` | Edit the selected code blocks | | -| `:AvanteFocus` | Switch focus to/from the sidebar | | -| `:AvanteRefresh` | Refresh all Avante windows | | -| `:AvanteStop` | Stop the current AI request | | -| `:AvanteSwitchProvider` | Switch AI provider (e.g. openai) | | -| `:AvanteShowRepoMap` | Show repo map for project's structure | | -| `:AvanteToggle` | Toggle the Avante sidebar | | -| `:AvanteModels` | Show model list | | +| `:AvanteBuild` | Build dependencies for the project | | +| `:AvanteChat` | Start a chat session with AI about your codebase. Default is `ask`=false | | +| `:AvanteClear` | Clear the chat history | | +| `:AvanteEdit` | Edit the selected code blocks | | +| `:AvanteFocus` | Switch focus to/from the sidebar | | +| `:AvanteRefresh` | Refresh all Avante windows | | +| `:AvanteStop` | Stop the current AI request | | +| `:AvanteSwitchProvider` | Switch AI provider (e.g. openai) | | +| `:AvanteShowRepoMap` | Show repo map for project's structure | | +| `:AvanteToggle` | Toggle the Avante sidebar | | +| `:AvanteModels` | Show model list | | ## Highlight Groups @@ -814,6 +816,7 @@ The default is Tavily, and can be changed through configuring `Config.web_search ```lua web_search_engine = { provider = "tavily", -- tavily, serpapi, searchapi, google or kagi + proxy = nil, -- proxy support, e.g., http://127.0.0.1:7890 } ``` @@ -906,6 +909,7 @@ Avante allows you to define custom tools that can be used by the AI during code }, } ``` + ## MCP @@ -927,7 +931,6 @@ Avante leverages [Claude Text Editor Tool](https://docs.anthropic.com/en/docs/bu > [!NOTE] > To enable **Claude Text Editor Tool Mode**, you must use the `claude-3-5-sonnet-*` or `claude-3-7-sonnet-*` model with the `claude` provider! This feature is not supported by any other models! - ## Custom prompts By default, `avante.nvim` provides three different modes to interact with: `planning`, `editing`, and `suggesting`, followed with three different prompts per mode. diff --git a/README_zh.md b/README_zh.md index e168bdd..b4e752d 100644 --- a/README_zh.md +++ b/README_zh.md @@ -28,7 +28,6 @@ [View in English](README.md) - > [!NOTE] > > 🥰 该项目正在快速迭代中,许多令人兴奋的功能将陆续添加。敬请期待! @@ -436,6 +435,7 @@ _请参见 [config.lua#L9](./lua/avante/config.lua) 以获取完整配置_ }, } ``` + ## Blink.cmp 用户 @@ -613,25 +613,25 @@ _请参见 [config.lua#L9](./lua/avante/config.lua) 以获取完整配置_ 以下键绑定可用于 `avante.nvim`: -| 键绑定 | 描述 | -| ----------------------------------------- | -------------------------------------------- | -| Leaderaa | 显示侧边栏 | -| Leaderat | 切换侧边栏可见性 | -| Leaderar | 刷新侧边栏 | -| Leaderaf | 切换侧边栏焦点 | -| Leadera? | 选择模型 | -| Leaderae | 编辑选定的块 | -| LeaderaS | 停止当前 AI 请求 | -| co | 选择我们的 | -| ct | 选择他们的 | -| ca | 选择所有他们的 | -| c0 | 选择无 | -| cb | 选择两者 | -| cc | 选择光标 | -| ]x | 移动到上一个冲突 | -| [x | 移动到下一个冲突 | +| 键绑定 | 描述 | +| ----------------------------------------- | ----------------------------- | +| Leaderaa | 显示侧边栏 | +| Leaderat | 切换侧边栏可见性 | +| Leaderar | 刷新侧边栏 | +| Leaderaf | 切换侧边栏焦点 | +| Leadera? | 选择模型 | +| Leaderae | 编辑选定的块 | +| LeaderaS | 停止当前 AI 请求 | +| co | 选择我们的 | +| ct | 选择他们的 | +| ca | 选择所有他们的 | +| c0 | 选择无 | +| cb | 选择两者 | +| cc | 选择光标 | +| ]x | 移动到上一个冲突 | +| [x | 移动到下一个冲突 | | [[ | 跳转到上一个代码块 (结果窗口) | -| ]] | 跳转到下一个代码块 (结果窗口) | +| ]] | 跳转到下一个代码块 (结果窗口) | > [!NOTE] > @@ -641,6 +641,7 @@ _请参见 [config.lua#L9](./lua/avante/config.lua) 以获取完整配置_ ### Neotree 快捷方式 在 neotree 侧边栏中,您还可以添加新的键盘快捷方式,以快速将 `file/folder` 添加到 `Avante Selected Files`。 +
Neotree 配置 @@ -685,41 +686,42 @@ return { }, } ``` +
## 命令 -| 命令 | 描述 | 示例 | -| ---------------------------------- | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | +| 命令 | 描述 | 示例 | +| ---------------------------------- | ---------------------------------------------------------------------------------------- | --------------------------------------------------- | | `:AvanteAsk [question] [position]` | 询问 AI 关于您的代码的问题。可选的 `position` 设置窗口位置和 `ask` 启用/禁用直接询问模式 | `:AvanteAsk position=right Refactor this code here` | -| `:AvanteBuild` | 构建项目的依赖项 | | -| `:AvanteChat` | 启动与 AI 的聊天会话,讨论您的代码库。默认情况下 `ask`=false | | -| `:AvanteClear` | 清除聊天记录 | | -| `:AvanteEdit` | 编辑选定的代码块 | | -| `:AvanteFocus` | 切换焦点到/从侧边栏 | | -| `:AvanteRefresh` | 刷新所有 Avante 窗口 | | -| `:AvanteStop` | 停止当前 AI 请求 | | -| `:AvanteSwitchProvider` | 切换 AI 提供者(例如 openai) | | -| `:AvanteShowRepoMap` | 显示项目结构的 repo map | | -| `:AvanteToggle` | 切换 Avante 侧边栏 | | -| `:AvanteModels` | 显示模型列表 | | +| `:AvanteBuild` | 构建项目的依赖项 | | +| `:AvanteChat` | 启动与 AI 的聊天会话,讨论您的代码库。默认情况下 `ask`=false | | +| `:AvanteClear` | 清除聊天记录 | | +| `:AvanteEdit` | 编辑选定的代码块 | | +| `:AvanteFocus` | 切换焦点到/从侧边栏 | | +| `:AvanteRefresh` | 刷新所有 Avante 窗口 | | +| `:AvanteStop` | 停止当前 AI 请求 | | +| `:AvanteSwitchProvider` | 切换 AI 提供者(例如 openai) | | +| `:AvanteShowRepoMap` | 显示项目结构的 repo map | | +| `:AvanteToggle` | 切换 Avante 侧边栏 | | +| `:AvanteModels` | 显示模型列表 | | ## 高亮组 -| 高亮组 | 描述 | 备注 | -| --------------------------- | --------------------------------------------- | -------------------------------------------- | -| AvanteTitle | 标题 | | -| AvanteReversedTitle | 用于圆角边框 | | -| AvanteSubtitle | 选定代码标题 | | -| AvanteReversedSubtitle | 用于圆角边框 | | -| AvanteThirdTitle | 提示标题 | | -| AvanteReversedThirdTitle | 用于圆角边框 | | -| AvanteConflictCurrent | 当前冲突高亮 | 默认值为 `Config.highlights.diff.current` | -| AvanteConflictIncoming | 即将到来的冲突高亮 | 默认值为 `Config.highlights.diff.incoming` | -| AvanteConflictCurrentLabel | 当前冲突标签高亮 | 默认值为 `AvanteConflictCurrent` 的阴影 | -| AvanteConflictIncomingLabel | 即将到来的冲突标签高亮 | 默认值为 `AvanteConflictIncoming` 的阴影 | -| AvantePopupHint | 弹出菜单中的使用提示 | | -| AvanteInlineHint | 在可视模式下显示的行尾提示 | | +| 高亮组 | 描述 | 备注 | +| --------------------------- | -------------------------- | ------------------------------------------ | +| AvanteTitle | 标题 | | +| AvanteReversedTitle | 用于圆角边框 | | +| AvanteSubtitle | 选定代码标题 | | +| AvanteReversedSubtitle | 用于圆角边框 | | +| AvanteThirdTitle | 提示标题 | | +| AvanteReversedThirdTitle | 用于圆角边框 | | +| AvanteConflictCurrent | 当前冲突高亮 | 默认值为 `Config.highlights.diff.current` | +| AvanteConflictIncoming | 即将到来的冲突高亮 | 默认值为 `Config.highlights.diff.incoming` | +| AvanteConflictCurrentLabel | 当前冲突标签高亮 | 默认值为 `AvanteConflictCurrent` 的阴影 | +| AvanteConflictIncomingLabel | 即将到来的冲突标签高亮 | 默认值为 `AvanteConflictIncoming` 的阴影 | +| AvantePopupHint | 弹出菜单中的使用提示 | | +| AvanteInlineHint | 在可视模式下显示的行尾提示 | | 有关更多信息,请参见 [highlights.lua](./lua/avante/highlights.lua) @@ -811,6 +813,8 @@ Avante 的工具包括一些 Web 搜索引擎,目前支持: ```lua web_search_engine = { provider = "tavily", -- tavily, serpapi, searchapi, google 或 kagi + proxy = nil, -- proxy support, e.g., http://127.0.0.1:7890 + } ``` @@ -903,6 +907,7 @@ Avante 允许您定义自定义工具,AI 可以在代码生成和分析期间 }, } ``` + ## MCP @@ -924,7 +929,6 @@ Avante 利用 [Claude 文本编辑器工具](https://docs.anthropic.com/en/docs/ > [!NOTE] > 要启用 **Claude 文本编辑器工具模式**,您必须使用 `claude-3-5-sonnet-*` 或 `claude-3-7-sonnet-*` 模型与 `claude` 提供者!此功能不支持任何其他模型! - ## 自定义提示 默认情况下,`avante.nvim` 提供三种不同的模式进行交互:`planning`、`editing` 和 `suggesting`,每种模式都有三种不同的提示。 @@ -1009,15 +1013,15 @@ vim.keymap.set("n", "am", function() vim.api.nvim_exec_autocmds("User", 我们要向以下开源项目的贡献者表示衷心的感谢,他们的代码为 avante.nvim 的开发提供了宝贵的灵感和参考: -| Nvim 插件 | 许可证 | 功能 | 位置 | -| --------------------------------------------------------------------- | ------------------ | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| [git-conflict.nvim](https://github.com/akinsho/git-conflict.nvim) | 无许可证 | 差异比较功能 | [lua/avante/diff.lua](https://github.com/yetone/avante.nvim/blob/main/lua/avante/diff.lua) | +| Nvim 插件 | 许可证 | 功能 | 位置 | +| --------------------------------------------------------------------- | ----------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------- | +| [git-conflict.nvim](https://github.com/akinsho/git-conflict.nvim) | 无许可证 | 差异比较功能 | [lua/avante/diff.lua](https://github.com/yetone/avante.nvim/blob/main/lua/avante/diff.lua) | | [ChatGPT.nvim](https://github.com/jackMort/ChatGPT.nvim) | Apache 2.0 许可证 | 令牌计数的计算 | [lua/avante/utils/tokens.lua](https://github.com/yetone/avante.nvim/blob/main/lua/avante/utils/tokens.lua) | -| [img-clip.nvim](https://github.com/HakonHarnes/img-clip.nvim) | MIT 许可证 | 剪贴板图像支持 | [lua/avante/clipboard.lua](https://github.com/yetone/avante.nvim/blob/main/lua/avante/clipboard.lua) | -| [copilot.lua](https://github.com/zbirenbaum/copilot.lua) | MIT 许可证 | Copilot 支持 | [lua/avante/providers/copilot.lua](https://github.com/yetone/avante.nvim/blob/main/lua/avante/providers/copilot.lua) | -| [jinja.vim](https://github.com/HiPhish/jinja.vim) | MIT 许可证 | 模板文件类型支持 | [syntax/jinja.vim](https://github.com/yetone/avante.nvim/blob/main/syntax/jinja.vim) | -| [codecompanion.nvim](https://github.com/olimorris/codecompanion.nvim) | MIT 许可证 | Secrets 逻辑支持 | [lua/avante/providers/init.lua](https://github.com/yetone/avante.nvim/blob/main/lua/avante/providers/init.lua) | -| [aider](https://github.com/paul-gauthier/aider) | Apache 2.0 许可证 | 规划模式用户提示 | [lua/avante/templates/planning.avanterules](https://github.com/yetone/avante.nvim/blob/main/lua/avante/templates/planning.avanterules) | +| [img-clip.nvim](https://github.com/HakonHarnes/img-clip.nvim) | MIT 许可证 | 剪贴板图像支持 | [lua/avante/clipboard.lua](https://github.com/yetone/avante.nvim/blob/main/lua/avante/clipboard.lua) | +| [copilot.lua](https://github.com/zbirenbaum/copilot.lua) | MIT 许可证 | Copilot 支持 | [lua/avante/providers/copilot.lua](https://github.com/yetone/avante.nvim/blob/main/lua/avante/providers/copilot.lua) | +| [jinja.vim](https://github.com/HiPhish/jinja.vim) | MIT 许可证 | 模板文件类型支持 | [syntax/jinja.vim](https://github.com/yetone/avante.nvim/blob/main/syntax/jinja.vim) | +| [codecompanion.nvim](https://github.com/olimorris/codecompanion.nvim) | MIT 许可证 | Secrets 逻辑支持 | [lua/avante/providers/init.lua](https://github.com/yetone/avante.nvim/blob/main/lua/avante/providers/init.lua) | +| [aider](https://github.com/paul-gauthier/aider) | Apache 2.0 许可证 | 规划模式用户提示 | [lua/avante/templates/planning.avanterules](https://github.com/yetone/avante.nvim/blob/main/lua/avante/templates/planning.avanterules) | 这些项目的源代码的高质量和独创性在我们的开发过程中提供了极大的帮助。我们向这些项目的作者和贡献者表示诚挚的感谢和敬意。正是开源社区的无私奉献推动了像 avante.nvim 这样的项目向前发展。 diff --git a/lua/avante/config.lua b/lua/avante/config.lua index 2c04d8b..eb13d9b 100644 --- a/lua/avante/config.lua +++ b/lua/avante/config.lua @@ -47,6 +47,7 @@ M._defaults = { }, web_search_engine = { provider = "tavily", + proxy = nil, providers = { tavily = { api_key_name = "TAVILY_API_KEY", diff --git a/lua/avante/llm_tools/init.lua b/lua/avante/llm_tools/init.lua index 2c8c946..eaea341 100644 --- a/lua/avante/llm_tools/init.lua +++ b/lua/avante/llm_tools/init.lua @@ -212,6 +212,7 @@ end ---@type AvanteLLMToolFunc<{ query: string }> function M.web_search(opts, on_log) local provider_type = Config.web_search_engine.provider + local proxy = Config.web_search_engine.proxy if provider_type == nil then return nil, "Search engine provider is not set" end if on_log then on_log("provider: " .. provider_type) end if on_log then on_log("query: " .. opts.query) end @@ -223,7 +224,7 @@ function M.web_search(opts, on_log) return nil, "Environment variable " .. search_engine.api_key_name .. " is not set" end if provider_type == "tavily" then - local resp = curl.post("https://api.tavily.com/search", { + local curl_opts = { headers = { ["Content-Type"] = "application/json", ["Authorization"] = "Bearer " .. api_key, @@ -231,7 +232,9 @@ function M.web_search(opts, on_log) body = vim.json.encode(vim.tbl_deep_extend("force", { query = opts.query, }, search_engine.extra_request_body)), - }) + } + if proxy then curl_opts.proxy = proxy end + local resp = curl.post("https://api.tavily.com/search", curl_opts) 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) @@ -244,11 +247,13 @@ function M.web_search(opts, on_log) for key, value in pairs(query_params) do query_string = query_string .. key .. "=" .. vim.uri_encode(value) .. "&" end - local resp = curl.get("https://serpapi.com/search?" .. query_string, { + local curl_opts = { headers = { ["Content-Type"] = "application/json", }, - }) + } + if proxy then curl_opts.proxy = proxy end + local resp = curl.get("https://serpapi.com/search?" .. query_string, curl_opts) 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) @@ -261,11 +266,13 @@ function M.web_search(opts, on_log) for key, value in pairs(query_params) do query_string = query_string .. key .. "=" .. vim.uri_encode(value) .. "&" end - local resp = curl.get("https://searchapi.io/api/v1/search?" .. query_string, { + local curl_opts = { headers = { ["Content-Type"] = "application/json", }, - }) + } + if proxy then curl_opts.proxy = proxy end + local resp = curl.get("https://searchapi.io/api/v1/search?" .. query_string, curl_opts) 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) @@ -283,11 +290,13 @@ function M.web_search(opts, on_log) for key, value in pairs(query_params) do query_string = query_string .. key .. "=" .. vim.uri_encode(value) .. "&" end - local resp = curl.get("https://www.googleapis.com/customsearch/v1?" .. query_string, { + local curl_opts = { headers = { ["Content-Type"] = "application/json", }, - }) + } + if proxy then curl_opts.proxy = proxy end + local resp = curl.get("https://www.googleapis.com/customsearch/v1?" .. query_string, curl_opts) 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) @@ -299,12 +308,14 @@ function M.web_search(opts, on_log) 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, { + local curl_opts = { headers = { ["Authorization"] = "Bot " .. api_key, ["Content-Type"] = "application/json", }, - }) + } + if proxy then curl_opts.proxy = proxy end + local resp = curl.get("https://kagi.com/api/v0/search?" .. query_string, curl_opts) 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) @@ -316,12 +327,14 @@ function M.web_search(opts, on_log) for key, value in pairs(query_params) do query_string = query_string .. key .. "=" .. vim.uri_encode(value) .. "&" end - local resp = curl.get("https://api.search.brave.com/res/v1/web/search?" .. query_string, { + local curl_opts = { headers = { ["Content-Type"] = "application/json", ["X-Subscription-Token"] = api_key, }, - }) + } + if proxy then curl_opts.proxy = proxy end + local resp = curl.get("https://api.search.brave.com/res/v1/web/search?" .. query_string, curl_opts) 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)