diff --git a/lua/avante/config.lua b/lua/avante/config.lua
index 8473311..48d8663 100644
--- a/lua/avante/config.lua
+++ b/lua/avante/config.lua
@@ -345,6 +345,7 @@ M._defaults = {
},
history = {
max_tokens = 4096,
+ carried_entry_count = nil,
storage_path = vim.fn.stdpath("state") .. "/avante",
paste = {
extension = "png",
diff --git a/lua/avante/llm.lua b/lua/avante/llm.lua
index 6cc1589..652984e 100644
--- a/lua/avante/llm.lua
+++ b/lua/avante/llm.lua
@@ -60,10 +60,11 @@ end
---@param bufnr integer
---@param history avante.ChatHistory
+---@param entries? avante.ChatHistoryEntry[]
---@param cb fun(memory: avante.ChatMemory | nil): nil
-function M.summarize_memory(bufnr, history, cb)
+function M.summarize_memory(bufnr, history, entries, cb)
local system_prompt = [[You are a helpful AI assistant tasked with summarizing conversations.]]
- local entries = Utils.history.filter_active_entries(history.entries)
+ if not entries then entries = Utils.history.filter_active_entries(history.entries) end
if #entries == 0 then
cb(nil)
return
@@ -202,9 +203,7 @@ function M.generate_prompts(opts)
if memory ~= "" then table.insert(messages, { role = "user", content = memory }) end
end
- if instructions then
- table.insert(messages, { role = "user", content = string.format("%s", instructions) })
- end
+ if instructions then table.insert(messages, { role = "user", content = instructions }) end
local remaining_tokens = max_tokens - Utils.tokens.calculate_tokens(system_prompt)
@@ -212,20 +211,29 @@ function M.generate_prompts(opts)
remaining_tokens = remaining_tokens - Utils.tokens.calculate_tokens(message.content)
end
+ local dropped_history_messages = {}
if opts.history_messages then
if Config.history.max_tokens > 0 then remaining_tokens = math.min(Config.history.max_tokens, remaining_tokens) end
-- 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 = {}
for i = #opts.history_messages, 1, -1 do
local message = opts.history_messages[i]
- local tokens = Utils.tokens.calculate_tokens(message.content)
- remaining_tokens = remaining_tokens - tokens
- if remaining_tokens > 0 then
+ if Config.history.carried_entry_count ~= nil then
+ if #history_messages > Config.history.carried_entry_count then break end
table.insert(history_messages, message)
else
- break
+ local tokens = Utils.tokens.calculate_tokens(message.content)
+ remaining_tokens = remaining_tokens - tokens
+ if remaining_tokens > 0 then
+ table.insert(history_messages, message)
+ else
+ break
+ end
end
end
+
+ dropped_history_messages = vim.list_slice(opts.history_messages, 1, #opts.history_messages - #history_messages)
+
-- prepend the history messages to the messages table
vim.iter(history_messages):each(function(msg) table.insert(messages, 1, msg) end)
if #messages > 0 and messages[1].role == "assistant" then table.remove(messages, 1) end
@@ -254,6 +262,7 @@ Merge all changes from the snippet into the below.
image_paths = image_paths,
tools = opts.tools,
tool_histories = opts.tool_histories,
+ dropped_history_messages = dropped_history_messages,
}
end
@@ -493,6 +502,15 @@ function M._stream(opts)
local prompt_opts = M.generate_prompts(opts)
+ if
+ prompt_opts.dropped_history_messages
+ and #prompt_opts.dropped_history_messages > 0
+ and opts.on_memory_summarize
+ then
+ opts.on_memory_summarize(prompt_opts.dropped_history_messages)
+ return
+ end
+
local resp_headers = {}
---@type AvanteHandlerOptions
diff --git a/lua/avante/sidebar.lua b/lua/avante/sidebar.lua
index 8bbe142..4bd5fbc 100644
--- a/lua/avante/sidebar.lua
+++ b/lua/avante/sidebar.lua
@@ -2578,7 +2578,7 @@ function Sidebar:create_input_container(opts)
prompts_opts.history_messages = vim.list_slice(prompts_opts.history_messages, 5)
- Llm.summarize_memory(self.code.bufnr, self.chat_history, function(memory)
+ Llm.summarize_memory(self.code.bufnr, self.chat_history, nil, function(memory)
if memory then prompts_opts.memory = memory.content end
cb(prompts_opts)
end)
@@ -2815,6 +2815,28 @@ function Sidebar:create_input_container(opts)
session_ctx = {},
})
+ local function on_memory_summarize(dropped_history_messages)
+ local entries = Utils.history.filter_active_entries(self.chat_history.entries)
+
+ if self.chat_history.memory then
+ entries = vim
+ .iter(entries)
+ :filter(function(entry) return entry.timestamp > self.chat_history.memory.last_summarized_timestamp end)
+ :totable()
+ end
+
+ entries = vim.list_slice(entries, 1, #dropped_history_messages)
+
+ Llm.summarize_memory(self.code.bufnr, self.chat_history, entries, function(memory)
+ if memory then stream_options.memory = memory.content end
+ stream_options.history_messages =
+ vim.list_slice(stream_options.history_messages, #dropped_history_messages + 1)
+ Llm.stream(stream_options)
+ end)
+ end
+
+ stream_options.on_memory_summarize = on_memory_summarize
+
Llm.stream(stream_options)
end)
end
diff --git a/lua/avante/suggestion.lua b/lua/avante/suggestion.lua
index aa3f2d4..9292751 100644
--- a/lua/avante/suggestion.lua
+++ b/lua/avante/suggestion.lua
@@ -95,7 +95,7 @@ L5: pass
},
{
role = "user",
- content = '{"insertSpaces":true,"tabSize":4,"indentSize":4,"position":{"row":1,"col":7}}',
+ content = '{"insertSpaces":true,"tabSize":4,"indentSize":4,"position":{"row":1,"col":7}}',
},
{
role = "assistant",
diff --git a/lua/avante/templates/base.avanterules b/lua/avante/templates/base.avanterules
index 674e489..a6a6dc8 100644
--- a/lua/avante/templates/base.avanterules
+++ b/lua/avante/templates/base.avanterules
@@ -4,6 +4,8 @@ Respect and use existing conventions, libraries, etc that are already present in
Make sure code comments are in English when generating them.
+Memory is crucial, you must follow the instructions in !
+
{% include "_tools-guidelines.avanterules" %}
{% if system_info -%}
diff --git a/lua/avante/types.lua b/lua/avante/types.lua
index e87ebd2..ab575ff 100644
--- a/lua/avante/types.lua
+++ b/lua/avante/types.lua
@@ -96,6 +96,7 @@ vim.g.avante_login = vim.g.avante_login
---@field image_paths? string[]
---@field tools? AvanteLLMTool[]
---@field tool_histories? AvanteLLMToolHistory[]
+---@field dropped_history_messages? AvanteLLMMessage[]
---
---@class AvanteGeminiMessage
---@field role "user"
@@ -331,11 +332,14 @@ vim.g.avante_login = vim.g.avante_login
---@field tool_result? AvanteLLMToolResult
---@field tool_use? AvanteLLMToolUse
---
+---@alias AvanteLLMMemorySummarizeCallback fun(dropped_history_messages: AvanteLLMMessage[]): nil
+---
---@class AvanteLLMStreamOptions: AvanteGeneratePromptsOptions
---@field session_ctx? table
---@field on_start AvanteLLMStartCallback
---@field on_chunk AvanteLLMChunkCallback
---@field on_stop AvanteLLMStopCallback
+---@field on_memory_summarize? AvanteLLMMemorySummarizeCallback
---@field on_tool_log? function(tool_name: string, log: string): nil
---
---@alias AvanteLLMToolFunc fun(