diff --git a/lua/avante/llm.lua b/lua/avante/llm.lua index c0277d0..c60c9ab 100644 --- a/lua/avante/llm.lua +++ b/lua/avante/llm.lua @@ -536,7 +536,8 @@ function M._stream(opts) return handle_next_tool_use(tool_use_list, tool_use_index + 1, tool_histories) end -- Either on_complete handles the tool result asynchronously or we receive the result and error synchronously when either is not nil - local result, error = LLMTools.process_tool_use(opts.tools, tool_use, opts.on_tool_log, handle_tool_result) + local result, error = + LLMTools.process_tool_use(opts.tools, tool_use, opts.on_tool_log, handle_tool_result, opts.session_ctx) if result ~= nil or error ~= nil then return handle_tool_result(result, error) end end if stop_opts.reason == "cancelled" then diff --git a/lua/avante/llm_tools/bash.lua b/lua/avante/llm_tools/bash.lua index b532dcf..16d0c27 100644 --- a/lua/avante/llm_tools/bash.lua +++ b/lua/avante/llm_tools/bash.lua @@ -13,11 +13,13 @@ M.name = "bash" M.get_description = function() local provider = Providers[Config.provider] if Config.provider:match("copilot") and provider.model and provider.model:match("gpt") then - return [[Executes a given bash command in a persistent shell session with optional timeout, ensuring proper handling and security measures.]] + return [[Executes a given bash command in a persistent shell session with optional timeout, ensuring proper handling and security measures. Do not use bash command to read or modify files, or you will be fired!]] end return [[Executes a given bash command in a persistent shell session with optional timeout, ensuring proper handling and security measures. +Do not use bash command to read or modify files, or you will be fired! + Before executing the command, please follow these steps: 1. Directory Verification: diff --git a/lua/avante/llm_tools/init.lua b/lua/avante/llm_tools/init.lua index 5825454..76aa37c 100644 --- a/lua/avante/llm_tools/init.lua +++ b/lua/avante/llm_tools/init.lua @@ -26,7 +26,7 @@ function M.read_file_toplevel_symbols(opts, on_log) end ---@type AvanteLLMToolFunc<{ command: "view" | "str_replace" | "create" | "insert" | "undo_edit", path: string, old_str?: string, new_str?: string, file_text?: string, insert_line?: integer, new_str?: string, view_range?: integer[] }> -function M.str_replace_editor(opts, on_log, on_complete) +function M.str_replace_editor(opts, on_log, on_complete, session_ctx) if on_log then on_log("command: " .. opts.command) end if on_log then on_log("path: " .. vim.inspect(opts.path)) end if not on_complete then return false, "on_complete not provided" end @@ -51,7 +51,7 @@ function M.str_replace_editor(opts, on_log, on_complete) end_line = end_line, } end - return view(opts_, on_log, on_complete) + return view(opts_, on_log, on_complete, session_ctx) end if opts.command == "str_replace" then if not Path:new(abs_path):exists() then return false, "File not found: " .. abs_path end @@ -1247,9 +1247,10 @@ M._tools = { ---@param tool_use AvanteLLMToolUse ---@param on_log? fun(tool_name: string, log: string): nil ---@param on_complete? fun(result: string | nil, error: string | nil): nil +---@param session_ctx? table ---@return string | nil result ---@return string | nil error -function M.process_tool_use(tools, tool_use, on_log, on_complete) +function M.process_tool_use(tools, tool_use, on_log, on_complete, session_ctx) Utils.debug("use tool", tool_use.name, tool_use.input_json) -- Check if execution is already cancelled @@ -1344,7 +1345,7 @@ function M.process_tool_use(tools, tool_use, on_log, on_complete) return end on_complete(result, err) - end) + end, session_ctx) -- Result and error being nil means that the tool was executed asynchronously if result == nil and err == nil and on_complete then return end diff --git a/lua/avante/llm_tools/view.lua b/lua/avante/llm_tools/view.lua index c6b0e5a..15f0532 100644 --- a/lua/avante/llm_tools/view.lua +++ b/lua/avante/llm_tools/view.lua @@ -73,12 +73,22 @@ M.returns = { } ---@type AvanteLLMToolFunc<{ path: string, view_range?: { start_line: integer, end_line: integer } }> -function M.func(opts, on_log, on_complete) +function M.func(opts, on_log, on_complete, session_ctx) if not on_complete then return false, "on_complete not provided" end if Helpers.already_in_context(opts.path) then on_complete(nil, "Ooooops! This file is already in the context! Why you are trying to read it again?") return end + if session_ctx then + local view_history = session_ctx.view_history or {} + local uniform_path = Utils.uniform_path(opts.path) + if view_history[uniform_path] then + on_complete(nil, "Ooooops! You have already viewed this file! Why you are trying to read it again?") + return + end + view_history[uniform_path] = true + session_ctx.view_history = view_history + end local abs_path = Helpers.get_abs_path(opts.path) if not Helpers.has_permission_to_access(abs_path) then return false, "No permission to access path: " .. abs_path end if on_log then on_log("path: " .. abs_path) end diff --git a/lua/avante/sidebar.lua b/lua/avante/sidebar.lua index b5049f0..8f2a1b4 100644 --- a/lua/avante/sidebar.lua +++ b/lua/avante/sidebar.lua @@ -2817,6 +2817,7 @@ function Sidebar:create_input_container(opts) on_chunk = on_chunk, on_stop = on_stop, on_tool_log = on_tool_log, + session_ctx = {}, }) Llm.stream(stream_options) diff --git a/lua/avante/types.lua b/lua/avante/types.lua index e6eed1a..e87ebd2 100644 --- a/lua/avante/types.lua +++ b/lua/avante/types.lua @@ -332,6 +332,7 @@ vim.g.avante_login = vim.g.avante_login ---@field tool_use? AvanteLLMToolUse --- ---@class AvanteLLMStreamOptions: AvanteGeneratePromptsOptions +---@field session_ctx? table ---@field on_start AvanteLLMStartCallback ---@field on_chunk AvanteLLMChunkCallback ---@field on_stop AvanteLLMStopCallback @@ -339,8 +340,9 @@ vim.g.avante_login = vim.g.avante_login --- ---@alias AvanteLLMToolFunc fun( --- input: T, ---- on_log?: (fun(log: string): nil) | nil, ---- on_complete?: (fun(result: boolean | string | nil, error: string | nil): nil) | nil) +--- on_log?: (fun(log: string): nil), +--- on_complete?: (fun(result: boolean | string | nil, error: string | nil): nil), +--- session_ctx?: table) --- : (boolean | string | nil, string | nil) --- ---@class AvanteLLMTool