fix: tool use id sometimes will be the same (#1982)
This commit is contained in:
@@ -182,7 +182,8 @@ function M.generate_prompts(opts)
|
|||||||
local latest_tool_id = viewed_files[path]
|
local latest_tool_id = viewed_files[path]
|
||||||
if not latest_tool_id then goto continue end
|
if not latest_tool_id then goto continue end
|
||||||
if latest_tool_id ~= item.tool_use_id then
|
if latest_tool_id ~= item.tool_use_id then
|
||||||
item.content = string.format("The file %s has been updated. Please use the latest view tool result!", path)
|
item.content =
|
||||||
|
string.format("The file %s has been updated. Please use the latest `view` tool result!", path)
|
||||||
else
|
else
|
||||||
local lines, error = Utils.read_file_from_buf_or_disk(path)
|
local lines, error = Utils.read_file_from_buf_or_disk(path)
|
||||||
if error ~= nil then Utils.error("error reading file: " .. error) end
|
if error ~= nil then Utils.error("error reading file: " .. error) end
|
||||||
@@ -288,18 +289,20 @@ function M.generate_prompts(opts)
|
|||||||
dropped_history_messages = vim.list_extend(dropped_history_messages, opts.prompt_opts.dropped_history_messages)
|
dropped_history_messages = vim.list_extend(dropped_history_messages, opts.prompt_opts.dropped_history_messages)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local cleaned_history_messages = opts.history_messages
|
||||||
|
|
||||||
local final_history_messages = {}
|
local final_history_messages = {}
|
||||||
if opts.history_messages then
|
if cleaned_history_messages then
|
||||||
if opts.disable_compact_history_messages then
|
if opts.disable_compact_history_messages then
|
||||||
final_history_messages = vim.list_extend(final_history_messages, opts.history_messages)
|
final_history_messages = vim.list_extend(final_history_messages, cleaned_history_messages)
|
||||||
else
|
else
|
||||||
if Config.history.max_tokens > 0 then
|
if Config.history.max_tokens > 0 then
|
||||||
remaining_tokens = math.min(Config.history.max_tokens, remaining_tokens)
|
remaining_tokens = math.min(Config.history.max_tokens, remaining_tokens)
|
||||||
end
|
end
|
||||||
-- Traverse the history in reverse, keeping only the latest history until the remaining tokens are exhausted and the first message role is "user"
|
-- Traverse the history in reverse, keeping only the latest history until the remaining tokens are exhausted and the first message role is "user"
|
||||||
local history_messages = {}
|
local history_messages = {}
|
||||||
for i = #opts.history_messages, 1, -1 do
|
for i = #cleaned_history_messages, 1, -1 do
|
||||||
local message = opts.history_messages[i]
|
local message = cleaned_history_messages[i]
|
||||||
local tokens = Utils.tokens.calculate_tokens(message.message.content)
|
local tokens = Utils.tokens.calculate_tokens(message.message.content)
|
||||||
remaining_tokens = remaining_tokens - tokens
|
remaining_tokens = remaining_tokens - tokens
|
||||||
if remaining_tokens > 0 then
|
if remaining_tokens > 0 then
|
||||||
@@ -310,10 +313,12 @@ function M.generate_prompts(opts)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if #history_messages == 0 then
|
if #history_messages == 0 then
|
||||||
history_messages = vim.list_slice(opts.history_messages, #opts.history_messages - 1, #opts.history_messages)
|
history_messages =
|
||||||
|
vim.list_slice(cleaned_history_messages, #cleaned_history_messages - 1, #cleaned_history_messages)
|
||||||
end
|
end
|
||||||
|
|
||||||
dropped_history_messages = vim.list_slice(opts.history_messages, 1, #opts.history_messages - #history_messages)
|
dropped_history_messages =
|
||||||
|
vim.list_slice(cleaned_history_messages, 1, #cleaned_history_messages - #history_messages)
|
||||||
|
|
||||||
-- prepend the history messages to the messages table
|
-- prepend the history messages to the messages table
|
||||||
vim.iter(history_messages):each(function(msg) table.insert(final_history_messages, msg) end)
|
vim.iter(history_messages):each(function(msg) table.insert(final_history_messages, msg) end)
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ One or more SEARCH/REPLACE blocks following this exact format:
|
|||||||
\`\`\`
|
\`\`\`
|
||||||
Critical rules:
|
Critical rules:
|
||||||
1. SEARCH content must match the associated file section to find EXACTLY:
|
1. SEARCH content must match the associated file section to find EXACTLY:
|
||||||
|
* Do not refer to the `diff` argument of the previous `replace_in_file` function call for SEARCH content matching, as it may have been modified. Always match from the latest file content in <selected_files> or from the `view` function call result.
|
||||||
* Match character-for-character including whitespace, indentation, line endings
|
* Match character-for-character including whitespace, indentation, line endings
|
||||||
* Include all comments, docstrings, etc.
|
* Include all comments, docstrings, etc.
|
||||||
2. SEARCH/REPLACE blocks will ONLY replace the first match occurrence.
|
2. SEARCH/REPLACE blocks will ONLY replace the first match occurrence.
|
||||||
|
|||||||
@@ -2311,22 +2311,23 @@ function Sidebar:create_input_container()
|
|||||||
---@param state AvanteLLMToolUseState
|
---@param state AvanteLLMToolUseState
|
||||||
local function on_tool_log(tool_id, tool_name, log, state)
|
local function on_tool_log(tool_id, tool_name, log, state)
|
||||||
if state == "generating" then on_state_change("tool calling") end
|
if state == "generating" then on_state_change("tool calling") end
|
||||||
local tool_message = vim.iter(self.chat_history.messages):find(function(message)
|
local tool_use_message = nil
|
||||||
if message.message.role ~= "assistant" then return false end
|
for idx = #self.chat_history.messages, 1, -1 do
|
||||||
|
local message = self.chat_history.messages[idx]
|
||||||
local content = message.message.content
|
local content = message.message.content
|
||||||
if type(content) ~= "table" then return false end
|
if type(content) == "table" and content[1].type == "tool_use" and content[1].id == tool_id then
|
||||||
if content[1].type ~= "tool_use" then return false end
|
tool_use_message = message
|
||||||
if content[1].id ~= tool_id then return false end
|
break
|
||||||
return true
|
end
|
||||||
end)
|
end
|
||||||
if not tool_message then
|
if not tool_use_message then
|
||||||
Utils.debug("tool_message not found", tool_id, tool_name)
|
Utils.debug("tool_use message not found", tool_id, tool_name)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local tool_use_logs = tool_message.tool_use_logs or {}
|
local tool_use_logs = tool_use_message.tool_use_logs or {}
|
||||||
local content = string.format("[%s]: %s", tool_name, log)
|
local content = string.format("[%s]: %s", tool_name, log)
|
||||||
table.insert(tool_use_logs, content)
|
table.insert(tool_use_logs, content)
|
||||||
tool_message.tool_use_logs = tool_use_logs
|
tool_use_message.tool_use_logs = tool_use_logs
|
||||||
save_history()
|
save_history()
|
||||||
self:update_content("")
|
self:update_content("")
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1413,6 +1413,66 @@ function M.uuid()
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param message avante.HistoryMessage
|
||||||
|
---@return boolean
|
||||||
|
function M.is_tool_use_message(message)
|
||||||
|
local content = message.message.content
|
||||||
|
if type(content) == "string" then return false end
|
||||||
|
if vim.islist(content) then
|
||||||
|
for _, item in ipairs(content) do
|
||||||
|
if item.type == "tool_use" then return true end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param message avante.HistoryMessage
|
||||||
|
---@return boolean
|
||||||
|
function M.is_tool_result_message(message)
|
||||||
|
local content = message.message.content
|
||||||
|
if type(content) == "string" then return false end
|
||||||
|
if vim.islist(content) then
|
||||||
|
for _, item in ipairs(content) do
|
||||||
|
if item.type == "tool_result" then return true end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param message avante.HistoryMessage
|
||||||
|
---@param messages avante.HistoryMessage[]
|
||||||
|
---@return avante.HistoryMessage | nil
|
||||||
|
function M.get_tool_use_message(message, messages)
|
||||||
|
local content = message.message.content
|
||||||
|
if type(content) == "string" then return nil end
|
||||||
|
if vim.islist(content) then
|
||||||
|
local tool_id = nil
|
||||||
|
for _, item in ipairs(content) do
|
||||||
|
if item.type == "tool_result" then
|
||||||
|
tool_id = item.tool_use_id
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not tool_id then return nil end
|
||||||
|
local idx = nil
|
||||||
|
for idx_, message_ in ipairs(messages) do
|
||||||
|
if message_.uuid == message.uuid then
|
||||||
|
idx = idx_
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not idx then return nil end
|
||||||
|
for idx_ = idx - 1, 1, -1 do
|
||||||
|
local message_ = messages[idx_]
|
||||||
|
local content_ = message_.message.content
|
||||||
|
if type(content_) == "table" and content_[1].type == "tool_use" and content_[1].id == tool_id then
|
||||||
|
return message_
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
---@param message avante.HistoryMessage
|
---@param message avante.HistoryMessage
|
||||||
---@param messages avante.HistoryMessage[]
|
---@param messages avante.HistoryMessage[]
|
||||||
---@return avante.HistoryMessage | nil
|
---@return avante.HistoryMessage | nil
|
||||||
@@ -1428,7 +1488,15 @@ function M.get_tool_result_message(message, messages)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not tool_id then return nil end
|
if not tool_id then return nil end
|
||||||
for _, message_ in ipairs(messages) do
|
local idx = nil
|
||||||
|
for idx_, message_ in ipairs(messages) do
|
||||||
|
if message_.uuid == message.uuid then
|
||||||
|
idx = idx_
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not idx then return nil end
|
||||||
|
for _, message_ in ipairs(vim.list_slice(messages, idx + 1, #messages)) do
|
||||||
local content_ = message_.message.content
|
local content_ = message_.message.content
|
||||||
if type(content_) == "table" and content_[1].type == "tool_result" and content_[1].tool_use_id == tool_id then
|
if type(content_) == "table" and content_[1].type == "tool_result" and content_[1].tool_use_id == tool_id then
|
||||||
return message_
|
return message_
|
||||||
@@ -1469,36 +1537,48 @@ function M.message_content_item_to_lines(item, message, messages)
|
|||||||
local lines = {}
|
local lines = {}
|
||||||
local state = "generating"
|
local state = "generating"
|
||||||
local hl = "AvanteStateSpinnerToolCalling"
|
local hl = "AvanteStateSpinnerToolCalling"
|
||||||
if message.state == "generated" then
|
local tool_result_message = M.get_tool_result_message(message, messages)
|
||||||
local tool_result_message = M.get_tool_result_message(message, messages)
|
if tool_result_message then
|
||||||
if tool_result_message then
|
local tool_result = tool_result_message.message.content[1]
|
||||||
local tool_result = tool_result_message.message.content[1]
|
if tool_result.is_error then
|
||||||
if tool_result.is_error then
|
state = "failed"
|
||||||
state = "failed"
|
hl = "AvanteStateSpinnerFailed"
|
||||||
hl = "AvanteStateSpinnerFailed"
|
else
|
||||||
else
|
state = "succeeded"
|
||||||
state = "succeeded"
|
hl = "AvanteStateSpinnerSucceeded"
|
||||||
hl = "AvanteStateSpinnerSucceeded"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.insert(
|
table.insert(
|
||||||
lines,
|
lines,
|
||||||
Line:new({ { "╭─" }, { " " }, { string.format(" %s ", item.name), hl }, { string.format(" %s", state) } })
|
Line:new({ { "╭─" }, { " " }, { string.format(" %s ", item.name), hl }, { string.format(" %s", state) } })
|
||||||
)
|
)
|
||||||
for idx, log in ipairs(message.tool_use_logs or {}) do
|
if message.tool_use_logs then
|
||||||
local log_ = M.trim(log, { prefix = string.format("[%s]: ", item.name) })
|
for idx, log in ipairs(message.tool_use_logs) do
|
||||||
local lines_ = vim.split(log_, "\n")
|
local log_ = M.trim(log, { prefix = string.format("[%s]: ", item.name) })
|
||||||
if idx ~= #(message.tool_use_logs or {}) then
|
local lines_ = vim.split(log_, "\n")
|
||||||
for _, line_ in ipairs(lines_) do
|
if idx ~= #(message.tool_use_logs or {}) then
|
||||||
table.insert(lines, Line:new({ { "│" }, { string.format(" %s", line_) } }))
|
for _, line_ in ipairs(lines_) do
|
||||||
end
|
|
||||||
else
|
|
||||||
for idx_, line_ in ipairs(lines_) do
|
|
||||||
if idx_ ~= #lines_ then
|
|
||||||
table.insert(lines, Line:new({ { "│" }, { string.format(" %s", line_) } }))
|
table.insert(lines, Line:new({ { "│" }, { string.format(" %s", line_) } }))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for idx_, line_ in ipairs(lines_) do
|
||||||
|
if idx_ ~= #lines_ then
|
||||||
|
table.insert(lines, Line:new({ { "│" }, { string.format(" %s", line_) } }))
|
||||||
|
else
|
||||||
|
table.insert(lines, Line:new({ { "╰─" }, { string.format(" %s", line_) } }))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif tool_result_message then
|
||||||
|
local tool_result = tool_result_message.message.content[1]
|
||||||
|
if tool_result.content then
|
||||||
|
local result_lines = vim.split(tool_result.content, "\n")
|
||||||
|
for idx, line in ipairs(result_lines) do
|
||||||
|
if idx ~= #result_lines then
|
||||||
|
table.insert(lines, Line:new({ { "│" }, { string.format(" %s", line) } }))
|
||||||
else
|
else
|
||||||
table.insert(lines, Line:new({ { "╰─" }, { string.format(" %s", line_) } }))
|
table.insert(lines, Line:new({ { "╰─" }, { string.format(" %s", line) } }))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user