diff --git a/README.md b/README.md
index a3b74b6..7a8c0d6 100644
--- a/README.md
+++ b/README.md
@@ -989,8 +989,8 @@ In case you want to ban some tools to avoid its usage (like Claude 3.7 overusing
Tool list
-> rag_search, python, git_diff, git_commit, list_files, search_files, search_keyword, read_file_toplevel_symbols,
-> read_file, create_file, rename_file, delete_file, create_dir, rename_dir, delete_dir, bash, web_search, fetch
+> rag_search, python, git_diff, git_commit, glob, search_keyword, read_file_toplevel_symbols,
+> read_file, create_file, move_path, copy_path, delete_path, create_dir, bash, web_search, fetch
## Custom Tools
diff --git a/README_zh.md b/README_zh.md
index 209aea5..8f7f9a2 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -847,8 +847,8 @@ Avante 默认启用工具,但某些 LLM 模型不支持工具。您可以通
工具列表
-> rag_search, python, git_diff, git_commit, list_files, search_files, search_keyword, read_file_toplevel_symbols,
-> read_file, create_file, rename_file, delete_file, create_dir, rename_dir, delete_dir, bash, web_search, fetch
+> rag_search, python, git_diff, git_commit, glob, search_keyword, read_file_toplevel_symbols,
+> read_file, create_file, move_path, copy_path, delete_path, create_dir, bash, web_search, fetch
## 自定义工具
diff --git a/lua/avante/highlights.lua b/lua/avante/highlights.lua
index f28bc10..0dab5e9 100644
--- a/lua/avante/highlights.lua
+++ b/lua/avante/highlights.lua
@@ -48,6 +48,7 @@ local Highlights = {
AVANTE_STATE_SPINNER_THINKING = { name = "AvanteStateSpinnerThinking", fg = "#1e222a", bg = "#c678dd" },
AVANTE_STATE_SPINNER_COMPACTING = { name = "AvanteStateSpinnerCompacting", fg = "#1e222a", bg = "#c678dd" },
AVANTE_TASK_COMPLETED = { name = "AvanteTaskCompleted", fg = "#98c379", bg_link = "Normal" },
+ AVANTE_THINKING = { name = "AvanteThinking", fg = "#1e222a", bg = "#c678dd" },
}
Highlights.conflict = {
diff --git a/lua/avante/llm.lua b/lua/avante/llm.lua
index 24c9a42..a6befd6 100644
--- a/lua/avante/llm.lua
+++ b/lua/avante/llm.lua
@@ -735,10 +735,10 @@ function M._stream(opts)
return handle_next_tool_use(partial_tool_use_list, tool_use_index + 1, tool_results)
end
local is_edit_tool_use = Utils.is_edit_func_call_tool_use(partial_tool_use)
- local is_attempt_completion_tool_use = partial_tool_use.name == "attempt_completion"
- if partial_tool_use.state == "generating" and not is_edit_tool_use and not is_attempt_completion_tool_use then
- return
- end
+ local support_streaming = false
+ local llm_tool = vim.iter(prompt_opts.tools):find(function(tool) return tool.name == partial_tool_use.name end)
+ if llm_tool then support_streaming = llm_tool.support_streaming == true end
+ if partial_tool_use.state == "generating" and not is_edit_tool_use and not support_streaming then return end
if type(partial_tool_use.input) == "table" then partial_tool_use.input.tool_use_id = partial_tool_use.id end
if partial_tool_use.state == "generating" then
if type(partial_tool_use.input) == "table" then
diff --git a/lua/avante/llm_tools/attempt_completion.lua b/lua/avante/llm_tools/attempt_completion.lua
index d89ca9c..6f5af5b 100644
--- a/lua/avante/llm_tools/attempt_completion.lua
+++ b/lua/avante/llm_tools/attempt_completion.lua
@@ -15,6 +15,8 @@ After each tool use, the user will respond with the result of that tool use, i.e
IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool.
]]
+M.support_streaming = true
+
M.enabled = function() return Config.mode == "agentic" end
---@type AvanteLLMToolParam
@@ -54,7 +56,7 @@ M.returns = {
},
}
----@type AvanteLLMToolOnRender
+---@type avante.LLMToolOnRender
function M.on_render(opts)
local lines = {}
table.insert(lines, Line:new({ { "✓ Task Completed", Highlights.AVANTE_TASK_COMPLETED } }))
diff --git a/lua/avante/llm_tools/bash.lua b/lua/avante/llm_tools/bash.lua
index dfa5ff3..5f56a99 100644
--- a/lua/avante/llm_tools/bash.lua
+++ b/lua/avante/llm_tools/bash.lua
@@ -219,6 +219,7 @@ function M.func(opts, on_log, on_complete, session_ctx)
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 not Path:new(abs_path):exists() then return false, "Path not found: " .. abs_path end
+ if not opts.command then return false, "Command is required" end
if on_log then on_log("command: " .. opts.command) end
---change cwd to abs_path
---@param output string
diff --git a/lua/avante/llm_tools/init.lua b/lua/avante/llm_tools/init.lua
index a15347a..e9af7a5 100644
--- a/lua/avante/llm_tools/init.lua
+++ b/lua/avante/llm_tools/init.lua
@@ -95,21 +95,20 @@ function M.write_global_file(opts, on_log, on_complete)
end)
end
----@type AvanteLLMToolFunc<{ path: string, new_path: string }>
-function M.rename_file(opts, on_log, on_complete)
- local abs_path = Helpers.get_abs_path(opts.path)
+---@type AvanteLLMToolFunc<{ source_path: string, destination_path: string }>
+function M.move_path(opts, on_log, on_complete)
+ local abs_path = Helpers.get_abs_path(opts.source_path)
if not Helpers.has_permission_to_access(abs_path) then return false, "No permission to access path: " .. abs_path end
- if not Path:new(abs_path):exists() then return false, "File not found: " .. abs_path end
- if not Path:new(abs_path):is_file() then return false, "Path is not a file: " .. abs_path end
- local new_abs_path = Helpers.get_abs_path(opts.new_path)
+ if not Path:new(abs_path):exists() then return false, "The source path not found: " .. abs_path end
+ local new_abs_path = Helpers.get_abs_path(opts.destination_path)
if on_log then on_log(abs_path .. " -> " .. new_abs_path) end
if not Helpers.has_permission_to_access(new_abs_path) then
return false, "No permission to access path: " .. new_abs_path
end
- if Path:new(new_abs_path):exists() then return false, "File already exists: " .. new_abs_path end
+ if Path:new(new_abs_path):exists() then return false, "The destination path already exists: " .. new_abs_path end
if not on_complete then return false, "on_complete not provided" end
Helpers.confirm(
- "Are you sure you want to rename the file: " .. abs_path .. " to: " .. new_abs_path,
+ "Are you sure you want to move the path: " .. abs_path .. " to: " .. new_abs_path,
function(ok, reason)
if not ok then
on_complete(false, "User declined, reason: " .. (reason or "unknown"))
@@ -121,35 +120,61 @@ function M.rename_file(opts, on_log, on_complete)
)
end
----@type AvanteLLMToolFunc<{ path: string, new_path: string }>
-function M.copy_file(opts, on_log)
- local abs_path = Helpers.get_abs_path(opts.path)
+---@type AvanteLLMToolFunc<{ source_path: string, destination_path: string }>
+function M.copy_path(opts, on_log, on_complete)
+ local abs_path = Helpers.get_abs_path(opts.source_path)
if not Helpers.has_permission_to_access(abs_path) then return false, "No permission to access path: " .. abs_path end
- if not Path:new(abs_path):exists() then return false, "File not found: " .. abs_path end
- if not Path:new(abs_path):is_file() then return false, "Path is not a file: " .. abs_path end
- local new_abs_path = Helpers.get_abs_path(opts.new_path)
+ if not Path:new(abs_path):exists() then return false, "The source path not found: " .. abs_path end
+ local new_abs_path = Helpers.get_abs_path(opts.destination_path)
if not Helpers.has_permission_to_access(new_abs_path) then
return false, "No permission to access path: " .. new_abs_path
end
- if Path:new(new_abs_path):exists() then return false, "File already exists: " .. new_abs_path end
- if on_log then on_log("Copying file: " .. abs_path .. " to " .. new_abs_path) end
- Path:new(new_abs_path):write(Path:new(abs_path):read())
- return true, nil
+ if Path:new(new_abs_path):exists() then return false, "The destination path already exists: " .. new_abs_path end
+ if not on_complete then return false, "on_complete not provided" end
+ Helpers.confirm(
+ "Are you sure you want to copy the path: " .. abs_path .. " to: " .. new_abs_path,
+ function(ok, reason)
+ if not ok then
+ on_complete(false, "User declined, reason: " .. (reason or "unknown"))
+ return
+ end
+ if on_log then on_log("Copying path: " .. abs_path .. " to " .. new_abs_path) end
+ if Path:new(abs_path):is_dir() then
+ Path:new(new_abs_path):mkdir({ parents = true })
+ for _, entry in ipairs(Path:new(abs_path):list()) do
+ local new_entry_path = Path:new(new_abs_path):joinpath(entry)
+ if entry:match("^%.") then goto continue end
+ if Path:new(new_entry_path):exists() then
+ if Path:new(new_entry_path):is_dir() then
+ Path:new(new_entry_path):rmdir()
+ else
+ Path:new(new_entry_path):unlink()
+ end
+ end
+ vim.fn.mkdir(new_entry_path, "p")
+ Path:new(new_entry_path):write(Path:new(abs_path):joinpath(entry):read())
+ ::continue::
+ end
+ else
+ Path:new(new_abs_path):write(Path:new(abs_path):read())
+ end
+ on_complete(true, nil)
+ end
+ )
end
---@type AvanteLLMToolFunc<{ path: string }>
-function M.delete_file(opts, on_log, on_complete)
+function M.delete_path(opts, on_log, on_complete)
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 not Path:new(abs_path):exists() then return false, "File not found: " .. abs_path end
- if not Path:new(abs_path):is_file() then return false, "Path is not a file: " .. abs_path end
+ if not Path:new(abs_path):exists() then return false, "Path not found: " .. abs_path end
if not on_complete then return false, "on_complete not provided" end
- Helpers.confirm("Are you sure you want to delete the file: " .. abs_path, function(ok, reason)
+ Helpers.confirm("Are you sure you want to delete the path: " .. abs_path, function(ok, reason)
if not ok then
on_complete(false, "User declined, reason: " .. (reason or "unknown"))
return
end
- if on_log then on_log("Deleting file: " .. abs_path) end
+ if on_log then on_log("Deleting path: " .. abs_path) end
os.remove(abs_path)
on_complete(true, nil)
end)
@@ -172,50 +197,6 @@ function M.create_dir(opts, on_log, on_complete)
end)
end
----@type AvanteLLMToolFunc<{ path: string, new_path: string }>
-function M.rename_dir(opts, on_log, on_complete)
- 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 not Path:new(abs_path):exists() then return false, "Directory not found: " .. abs_path end
- if not Path:new(abs_path):is_dir() then return false, "Path is not a directory: " .. abs_path end
- local new_abs_path = Helpers.get_abs_path(opts.new_path)
- if not Helpers.has_permission_to_access(new_abs_path) then
- return false, "No permission to access path: " .. new_abs_path
- end
- if Path:new(new_abs_path):exists() then return false, "Directory already exists: " .. new_abs_path end
- if not on_complete then return false, "on_complete not provided" end
- Helpers.confirm(
- "Are you sure you want to rename directory " .. abs_path .. " to " .. new_abs_path .. "?",
- function(ok, reason)
- if not ok then
- on_complete(false, "User declined, reason: " .. (reason or "unknown"))
- return
- end
- if on_log then on_log("Renaming directory: " .. abs_path .. " to " .. new_abs_path) end
- os.rename(abs_path, new_abs_path)
- on_complete(true, nil)
- end
- )
-end
-
----@type AvanteLLMToolFunc<{ path: string }>
-function M.delete_dir(opts, on_log, on_complete)
- 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 not Path:new(abs_path):exists() then return false, "Directory not found: " .. abs_path end
- if not Path:new(abs_path):is_dir() then return false, "Path is not a directory: " .. abs_path end
- if not on_complete then return false, "on_complete not provided" end
- Helpers.confirm("Are you sure you want to delete the directory: " .. abs_path, function(ok, reason)
- if not ok then
- on_complete(false, "User declined, reason: " .. (reason or "unknown"))
- return
- end
- if on_log then on_log("Deleting directory: " .. abs_path) end
- os.remove(abs_path)
- on_complete(true, nil)
- end)
-end
-
---@type AvanteLLMToolFunc<{ query: string }>
function M.web_search(opts, on_log)
local provider_type = Config.web_search_engine.provider
@@ -896,25 +877,42 @@ M._tools = {
},
},
{
- name = "rename_file",
- description = "Rename a file in current project scope",
+ name = "move_path",
+ description = [[Moves or rename a file or directory in the project, and returns confirmation that the move succeeded.
+If the source and destination directories are the same, but the filename is different, this performs a rename. Otherwise, it performs a move.
+
+This tool should be used when it's desirable to move or rename a file or directory without changing its contents at all.]],
param = {
type = "table",
fields = {
{
- name = "path",
- description = "Relative path to the file in current project scope",
+ name = "source_path",
+ description = [[The source path of the file or directory to move/rename.
+
+
+If the project has the following files:
+
+- directory1/a/something.txt
+- directory2/a/things.txt
+- directory3/a/other.txt
+
+You can move the first file by providing a source_path of "directory1/a/something.txt"
+]],
type = "string",
},
{
- name = "new_path",
- description = "New relative path for the file",
+ name = "destination_path",
+ description = [[The destination path where the file or directory should be moved/renamed to. If the paths are the same except for the filename, then this will be a rename.
+
+
+To move "directory1/a/something.txt" to "directory2/b/renamed.txt", provide a destination_path of "directory2/b/renamed.txt"
+]],
type = "string",
},
},
usage = {
- path = "Relative path to the file in current project scope",
- new_path = "New relative path for the file",
+ source_path = "The source path of the file or directory to move/rename",
+ destination_path = "The destination path where the file or directory should be moved/renamed to",
},
},
returns = {
@@ -932,19 +930,81 @@ M._tools = {
},
},
{
- name = "delete_file",
- description = "Delete a file in current project scope",
+ name = "copy_path",
+ description = [[Copies a file or directory from the project to a new location, and returns confirmation that the copy succeeded.
+
+This tool should be used when it's desirable to copy a file or directory without changing its contents at all.]],
+ param = {
+ type = "table",
+ fields = {
+ {
+ name = "source_path",
+ description = [[The source path of the file or directory to copy.
+
+
+If the project has the following files:
+
+- directory1/a/something.txt
+- directory2/a/things.txt
+- directory3/a/other.txt
+
+You can copy the first file by providing a source_path of "directory1/a/something.txt"
+]],
+ type = "string",
+ },
+ {
+ name = "destination_path",
+ description = [[The destination path where the file or directory should be copied to.
+
+
+To copy "directory1/a/something.txt" to "directory2/b/copied.txt", provide a destination_path of "directory2/b/copied.txt"
+]],
+ type = "string",
+ },
+ },
+ usage = {
+ source_path = "The source path of the file or directory to copy",
+ destination_path = "The destination path where the file or directory should be copied to",
+ },
+ },
+ returns = {
+ {
+ name = "success",
+ description = "True if the file was copied successfully, false otherwise",
+ type = "boolean",
+ },
+ {
+ name = "error",
+ description = "Error message if the file was not copied successfully",
+ type = "string",
+ optional = true,
+ },
+ },
+ },
+ {
+ name = "delete_path",
+ description = "Deletes the file or directory (and the directory's contents, recursively) at the specified path in the project, and returns confirmation of the deletion.",
param = {
type = "table",
fields = {
{
name = "path",
- description = "Relative path to the file in current project scope",
+ description = [[The path of the file or directory to delete.
+
+If the project has the following files:
+
+- directory1/a/something.txt
+- directory2/a/things.txt
+- directory3/a/other.txt
+
+You can delete the first file by providing a path of "directory1/a/something.txt"
+
+ ]],
type = "string",
},
},
usage = {
- path = "Relative path to the file in current project scope",
+ path = "Relative path to the file or directory in the current project scope",
},
},
returns = {
@@ -991,72 +1051,7 @@ M._tools = {
},
},
},
- {
- name = "rename_dir",
- description = "Rename a directory in current project scope",
- param = {
- type = "table",
- fields = {
- {
- name = "path",
- description = "Relative path to the project directory",
- type = "string",
- },
- {
- name = "new_path",
- description = "New relative path for the directory",
- type = "string",
- },
- },
- usage = {
- path = "Relative path to the project directory",
- new_path = "New relative path for the directory",
- },
- },
- returns = {
- {
- name = "success",
- description = "True if the directory was renamed successfully, false otherwise",
- type = "boolean",
- },
- {
- name = "error",
- description = "Error message if the directory was not renamed successfully",
- type = "string",
- optional = true,
- },
- },
- },
- {
- name = "delete_dir",
- description = "Delete a directory in current project scope",
- param = {
- type = "table",
- fields = {
- {
- name = "path",
- description = "Relative path to the project directory",
- type = "string",
- },
- },
- usage = {
- path = "Relative path to the project directory",
- },
- },
- returns = {
- {
- name = "success",
- description = "True if the directory was deleted successfully, false otherwise",
- type = "boolean",
- },
- {
- name = "error",
- description = "Error message if the directory was not deleted successfully",
- type = "string",
- optional = true,
- },
- },
- },
+ require("avante.llm_tools.thinking"),
require("avante.llm_tools.get_diagnostics"),
require("avante.llm_tools.bash"),
require("avante.llm_tools.attempt_completion"),
@@ -1188,8 +1183,6 @@ M.run_python = M.python
---@return string | nil result
---@return string | nil error
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
if Helpers.is_cancelled then
Utils.debug("Tool execution cancelled before starting: " .. tool_use.name)
diff --git a/lua/avante/llm_tools/replace_in_file.lua b/lua/avante/llm_tools/replace_in_file.lua
index e72bd15..78e4124 100644
--- a/lua/avante/llm_tools/replace_in_file.lua
+++ b/lua/avante/llm_tools/replace_in_file.lua
@@ -16,6 +16,7 @@ M.name = "replace_in_file"
M.description =
"Request to replace sections of content in an existing file using SEARCH/REPLACE blocks that define exact changes to specific parts of the file. This tool should be used when you need to make targeted changes to specific parts of a file."
+M.support_streaming = true
-- function M.enabled() return Config.provider:match("ollama") == nil end
---@type AvanteLLMToolParam
diff --git a/lua/avante/llm_tools/thinking.lua b/lua/avante/llm_tools/thinking.lua
new file mode 100644
index 0000000..0b45b86
--- /dev/null
+++ b/lua/avante/llm_tools/thinking.lua
@@ -0,0 +1,65 @@
+local Line = require("avante.ui.line")
+local Base = require("avante.llm_tools.base")
+local Highlights = require("avante.highlights")
+local Utils = require("avante.utils")
+
+---@class AvanteLLMTool
+local M = setmetatable({}, Base)
+
+M.name = "thinking"
+
+M.description =
+ "A tool for thinking through problems, brainstorming ideas, or planning without executing any actions. Use this tool when you need to work through complex problems, develop strategies, or outline approaches before taking action."
+
+M.support_streaming = true
+
+---@type AvanteLLMToolParam
+M.param = {
+ type = "table",
+ fields = {
+ {
+ name = "content",
+ description = "Content to think about. This should be a description of what to think about or a problem to solve.",
+ type = "string",
+ },
+ },
+}
+
+---@type AvanteLLMToolReturn[]
+M.returns = {
+ {
+ name = "success",
+ description = "Whether the task was completed successfully",
+ type = "string",
+ },
+ {
+ name = "thoughts",
+ description = "The thoughts that guided the solution",
+ type = "string",
+ },
+}
+
+---@class ThinkingInput
+---@field content string
+
+---@type avante.LLMToolOnRender
+function M.on_render(opts, _, state)
+ local lines = {}
+ local text = state == "generating" and "Thinking" or "Thoughts"
+ table.insert(lines, Line:new({ { Utils.icon("🤔 ") .. text, Highlights.AVANTE_THINKING } }))
+ table.insert(lines, Line:new({ { "" } }))
+ local content = opts.content or ""
+ local text_lines = vim.split(content, "\n")
+ for _, text_line in ipairs(text_lines) do
+ table.insert(lines, Line:new({ { "> " .. text_line } }))
+ end
+ return lines
+end
+
+---@type AvanteLLMToolFunc
+function M.func(opts, on_log, on_complete, session_ctx)
+ if not on_complete then return false, "on_complete not provided" end
+ on_complete(true, nil)
+end
+
+return M
diff --git a/lua/avante/llm_tools/view.lua b/lua/avante/llm_tools/view.lua
index 7d92d39..2ff684a 100644
--- a/lua/avante/llm_tools/view.lua
+++ b/lua/avante/llm_tools/view.lua
@@ -8,9 +8,11 @@ local M = setmetatable({}, Base)
M.name = "view"
-M.description =
- [[The view tool allows you to examine the contents of a file or list the contents of a directory. It can read the entire file or a specific range of lines. If the file content is already in the context, do not use this tool.
-IMPORTANT NOTE: If the file content exceeds a certain size, the returned content will be truncated, and `is_truncated` will be set to true. If `is_truncated` is true, use the `start_line` parameter and `end_line` parameter to specify the range to view.
+M.description = [[Reads the content of the given file in the project.
+
+ - Never attempt to read a path that hasn't been previously mentioned.
+
+IMPORTANT NOTE: If the file content exceeds a certain size, the returned content will be truncated, and `is_truncated` will be set to true. If `is_truncated` is true, please use the `start_line` parameter and `end_line` parameter to call this `view` tool again.
]]
M.enabled = function(opts)
@@ -35,18 +37,29 @@ M.param = {
fields = {
{
name = "path",
- description = "The path to the file in the current project scope",
+ description = [[The relative path of the file to read.
+
+This path should never be absolute, and the first component of the path should always be a root directory in a project.
+
+
+If the project has the following root directories:
+
+- directory1
+- directory2
+
+If you want to access `file.txt` in `directory1`, you should use the path `directory1/file.txt`. If you want to access `file.txt` in `directory2`, you should use the path `directory2/file.txt`.
+]],
type = "string",
},
{
name = "start_line",
- description = "The start line of the view range, 1-indexed",
+ description = "Optional line number to start reading on (1-based index)",
type = "integer",
optional = true,
},
{
name = "end_line",
- description = "The end line of the view range, 1-indexed, and -1 for the end line means read to the end of the file",
+ description = "Optional line number to end reading on (1-based index, inclusive)",
type = "integer",
optional = true,
},
diff --git a/lua/avante/templates/_tools-guidelines.avanterules b/lua/avante/templates/_tools-guidelines.avanterules
index 1cce91e..24f6b3d 100644
--- a/lua/avante/templates/_tools-guidelines.avanterules
+++ b/lua/avante/templates/_tools-guidelines.avanterules
@@ -7,6 +7,7 @@ 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!
+- You should make good use of the `thinking` tool, as it can help you better solve tasks, especially complex ones.
- 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!
diff --git a/lua/avante/templates/base.avanterules b/lua/avante/templates/base.avanterules
index de5c3ce..6ee8670 100644
--- a/lua/avante/templates/base.avanterules
+++ b/lua/avante/templates/base.avanterules
@@ -1,5 +1,5 @@
-Act as an expert software developer.
-Always use best practices when coding.
+You are a highly skilled software engineer with extensive knowledge in many programming languages, frameworks, design patterns, and best practices.
+
Respect and use existing conventions, libraries, etc that are already present in the code base.
Make sure code comments are in English when generating them.
diff --git a/lua/avante/types.lua b/lua/avante/types.lua
index db522c7..ddde46e 100644
--- a/lua/avante/types.lua
+++ b/lua/avante/types.lua
@@ -387,7 +387,7 @@ vim.g.avante_login = vim.g.avante_login
--- session_ctx?: table)
--- : (boolean | string | nil, string | nil)
---
---- @alias AvanteLLMToolOnRender fun(input: T, logs: string[]): avante.ui.Line[]
+--- @alias avante.LLMToolOnRender fun(input: T, logs: string[], state: avante.HistoryMessageState | nil): avante.ui.Line[]
---
---@class AvanteLLMTool
---@field name string
@@ -397,7 +397,8 @@ vim.g.avante_login = vim.g.avante_login
---@field param AvanteLLMToolParam
---@field returns AvanteLLMToolReturn[]
---@field enabled? fun(opts: { user_input: string, history_messages: AvanteLLMMessage[] }): boolean
----@field on_render? AvanteLLMToolOnRender
+---@field on_render? avante.LLMToolOnRender
+---@field support_streaming? boolean
---@class AvanteLLMToolPublic : AvanteLLMTool
---@field func AvanteLLMToolFunc
diff --git a/lua/avante/utils/init.lua b/lua/avante/utils/init.lua
index 60cd1c8..a9a809a 100644
--- a/lua/avante/utils/init.lua
+++ b/lua/avante/utils/init.lua
@@ -1624,7 +1624,7 @@ function M.message_content_item_to_lines(item, message, messages)
local hl = "AvanteStateSpinnerToolCalling"
local ok, llm_tool = pcall(require, "avante.llm_tools." .. item.name)
if ok then
- if llm_tool.on_render then return llm_tool.on_render(item.input, message.tool_use_logs) end
+ if llm_tool.on_render then return llm_tool.on_render(item.input, message.tool_use_logs, message.state) end
end
local tool_result_message = M.get_tool_result_message(message, messages)
if tool_result_message then
diff --git a/tests/llm_tools_spec.lua b/tests/llm_tools_spec.lua
index c730c3c..82747c5 100644
--- a/tests/llm_tools_spec.lua
+++ b/tests/llm_tools_spec.lua
@@ -112,9 +112,9 @@ describe("llm_tools", function()
end)
end)
- describe("delete_file", function()
+ describe("delete_path", function()
it("should delete existing file", function()
- LlmTools.delete_file({ path = "test.txt" }, nil, function(success, err)
+ LlmTools.delete_path({ path = "test.txt" }, nil, function(success, err)
assert.is_nil(err)
assert.is_true(success)