diff --git a/lua/avante/llm_tools/helpers.lua b/lua/avante/llm_tools/helpers.lua index 72cee0c..3bbdf4b 100644 --- a/lua/avante/llm_tools/helpers.lua +++ b/lua/avante/llm_tools/helpers.lua @@ -61,4 +61,15 @@ function M.has_permission_to_access(abs_path) return not M.is_ignored(abs_path) end +---@param path string +---@return boolean +function M.already_in_context(path) + local sidebar = require("avante").get() + if sidebar and sidebar.file_selector then + local rel_path = Utils.uniform_path(path) + return vim.tbl_contains(sidebar.file_selector.selected_filepaths, rel_path) + end + return false +end + return M diff --git a/lua/avante/llm_tools/init.lua b/lua/avante/llm_tools/init.lua index bee7188..5825454 100644 --- a/lua/avante/llm_tools/init.lua +++ b/lua/avante/llm_tools/init.lua @@ -276,24 +276,6 @@ function M.write_global_file(opts, on_log, on_complete) end) end ----@type AvanteLLMToolFunc<{ rel_path: string }> -function M.create_file(opts, on_log) - local abs_path = Helpers.get_abs_path(opts.rel_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 - ---create directory if it doesn't exist - local dir = Path:new(abs_path):parent() - if not dir:exists() then dir:mkdir({ parents = true }) end - ---create file if it doesn't exist - if not dir:joinpath(opts.rel_path):exists() then - local file = io.open(abs_path, "w") - if not file then return false, "file not found: " .. abs_path end - file:close() - end - - return true, nil -end - ---@type AvanteLLMToolFunc<{ rel_path: string, new_rel_path: string }> function M.rename_file(opts, on_log, on_complete) local abs_path = Helpers.get_abs_path(opts.rel_path) @@ -1008,33 +990,6 @@ M._tools = { }, }, }, - { - name = "create_file", - description = "Create a new file in current project scope", - param = { - type = "table", - fields = { - { - name = "rel_path", - description = "Relative path to the file in current project scope", - type = "string", - }, - }, - }, - returns = { - { - name = "success", - description = "True if the file was created successfully, false otherwise", - type = "boolean", - }, - { - name = "error", - description = "Error message if the file was not created successfully", - type = "string", - optional = true, - }, - }, - }, { name = "rename_file", description = "Rename a file in current project scope", diff --git a/lua/avante/llm_tools/view.lua b/lua/avante/llm_tools/view.lua index 25ed697..c6b0e5a 100644 --- a/lua/avante/llm_tools/view.lua +++ b/lua/avante/llm_tools/view.lua @@ -75,6 +75,10 @@ M.returns = { ---@type AvanteLLMToolFunc<{ path: string, view_range?: { start_line: integer, end_line: integer } }> function M.func(opts, on_log, on_complete) 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 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 9f268c2..b5049f0 100644 --- a/lua/avante/sidebar.lua +++ b/lua/avante/sidebar.lua @@ -252,6 +252,7 @@ end ---@field is_searching boolean ---@field is_replacing boolean ---@field is_thinking boolean +---@field waiting_for_breakline boolean ---@field last_search_tag_start_line integer ---@field last_replace_tag_start_line integer ---@field last_think_tag_start_line integer @@ -278,6 +279,7 @@ local function transform_result_content(selected_files, result_content, prev_fil local current_filepath + local waiting_for_breakline = false local i = 1 while true do if i > #result_lines then break end @@ -414,6 +416,7 @@ local function transform_result_content(selected_files, result_content, prev_fil if search_start_tag_idx_in_transformed_lines > 0 then transformed_lines = vim.list_slice(transformed_lines, 1, search_start_tag_idx_in_transformed_lines - 1) end + waiting_for_breakline = true vim.list_extend(transformed_lines, { string.format("Replace lines: %d-%d", start_line, end_line), string.format("```%s", match_filetype), @@ -456,6 +459,7 @@ local function transform_result_content(selected_files, result_content, prev_fil is_thinking = false last_think_tag_end_line = i end + waiting_for_breakline = false table.insert(transformed_lines, line_content) ::continue:: i = i + 1 @@ -465,6 +469,7 @@ local function transform_result_content(selected_files, result_content, prev_fil return { current_filepath = current_filepath, content = table.concat(transformed_lines, "\n"), + waiting_for_breakline = waiting_for_breakline, is_searching = is_searching, is_replacing = is_replacing, is_thinking = is_thinking, @@ -2645,6 +2650,7 @@ function Sidebar:create_input_container(opts) self:update_content(content_prefix .. generating_text) local original_response = "" + local waiting_for_breakline = false local transformed_response = "" local displayed_response = "" local current_path = "" @@ -2702,7 +2708,15 @@ function Sidebar:create_input_container(opts) local selected_files = self.file_selector:get_selected_files_contents() - local transformed = transform_result_content(selected_files, transformed_response .. chunk, current_path) + local transformed_response_ + if waiting_for_breakline and chunk and chunk:sub(1, 1) ~= "\n" then + transformed_response_ = transformed_response .. "\n" .. chunk + else + transformed_response_ = transformed_response .. chunk + end + + local transformed = transform_result_content(selected_files, transformed_response_, current_path) + waiting_for_breakline = transformed.waiting_for_breakline transformed_response = transformed.content if transformed.current_filepath and transformed.current_filepath ~= "" then current_path = transformed.current_filepath diff --git a/lua/avante/templates/_tools-guidelines.avanterules b/lua/avante/templates/_tools-guidelines.avanterules index d5a7f88..900b1a0 100644 --- a/lua/avante/templates/_tools-guidelines.avanterules +++ b/lua/avante/templates/_tools-guidelines.avanterules @@ -3,9 +3,9 @@ Don't directly search for code context in historical messages. Instead, prioriti Tools Usage Guide: - You have access to tools, but only use them when necessary. If a tool is not required, respond as normal. - Please DON'T be so aggressive in using tools, as many tasks can be better completed without tools. - - Files will be provided to you as context through tag! - - Before using the `view` tool each time, always repeatedly check whether the file is already in the tag. If it is already there, do not use the `view` tool, just read the file content directly from the tag. - - If you use the `view` tool when file content is already provided in the tag, you will be fired! + - Files will be provided to you as context through tag! + - Before using the `view` tool each time, always repeatedly check whether the file is already in the tag. If it is already there, do not use the `view` tool, just read the file content directly from the tag. + - If you use the `view` tool when file content is already provided in the tag, you will be fired! - If the `rag_search` tool exists, prioritize using it to do the search! - If the `rag_search` tool exists, only use tools like `search_keyword` `search_files` `view` `list_files` etc when absolutely necessary! - Keep the `query` parameter of `rag_search` tool as concise as possible! Try to keep it within five English words! diff --git a/tests/llm_tools_spec.lua b/tests/llm_tools_spec.lua index c53cb1c..d056adc 100644 --- a/tests/llm_tools_spec.lua +++ b/tests/llm_tools_spec.lua @@ -10,6 +10,7 @@ local view = require("avante.llm_tools.view") local bash = require("avante.llm_tools.bash") LlmToolHelpers.confirm = function(msg, cb) return cb(true) end +LlmToolHelpers.already_in_context = function(path) return false end describe("llm_tools", function() local test_dir = "/tmp/test_llm_tools" @@ -99,18 +100,6 @@ describe("llm_tools", function() end) end) - describe("create_file", function() - it("should create new file", function() - LlmTools.create_file({ rel_path = "new_file.txt" }, nil, function(success, err) - assert.is_nil(err) - assert.is_true(success) - - local file_exists = io.open(test_dir .. "/new_file.txt", "r") ~= nil - assert.is_true(file_exists) - end) - end) - end) - describe("create_dir", function() it("should create new directory", function() LlmTools.create_dir({ rel_path = "new_dir" }, nil, function(success, err)