refactor(ai): streaming chunks to avoid excessive redraw. (#73)

* perf(ai): token streaming with quick refactoring

Signed-off-by: Aaron Pham <contact@aarnphm.xyz>

* fix: window resize and AvanteSwitchProvider

Signed-off-by: Aaron Pham <contact@aarnphm.xyz>

* revert: config change

Signed-off-by: Aaron Pham <contact@aarnphm.xyz>

* chore: return early

Signed-off-by: Aaron Pham <contact@aarnphm.xyz>

---------

Signed-off-by: Aaron Pham <contact@aarnphm.xyz>
This commit is contained in:
Aaron Pham
2024-08-18 15:03:25 -04:00
committed by GitHub
parent 0fddfc7d8f
commit 5fa4f701dd
6 changed files with 414 additions and 249 deletions

View File

@@ -141,6 +141,15 @@ function Sidebar:intialize()
mode = { "n" },
key = "q",
handler = function()
api.nvim_exec_autocmds("User", { pattern = AiBot.CANCEL_PATTERN })
self.renderer:close()
end,
},
{
mode = { "n" },
key = "<Esc>",
handler = function()
api.nvim_exec_autocmds("User", { pattern = AiBot.CANCEL_PATTERN })
self.renderer:close()
end,
},
@@ -171,10 +180,16 @@ function Sidebar:intialize()
api.nvim_create_autocmd("VimResized", {
group = self.augroup,
callback = function()
if not self.view:is_open() then
return
end
local new_layout = Config.get_renderer_layout_options()
vim.api.nvim_win_set_width(self.view.win, new_layout.width)
vim.api.nvim_win_set_height(self.view.win, new_layout.height)
self.renderer:set_size({ width = new_layout.width, height = new_layout.height })
vim.defer_fn(function()
vim.cmd("AvanteRefresh")
end, 200)
end,
})
@@ -228,34 +243,51 @@ function Sidebar:is_focused()
end
---@param content string concatenated content of the buffer
---@param opts? {focus?: boolean, scroll?: boolean, callback?: fun(): nil} whether to focus the result view
---@param opts? {focus?: boolean, stream?: boolean, scroll?: boolean, callback?: fun(): nil} whether to focus the result view
function Sidebar:update_content(content, opts)
opts = vim.tbl_deep_extend("force", { focus = true, scroll = true, callback = nil }, opts or {})
vim.defer_fn(function()
api.nvim_set_option_value("modifiable", true, { buf = self.view.buf })
api.nvim_buf_set_lines(self.view.buf, 0, -1, false, vim.split(content, "\n"))
api.nvim_set_option_value("modifiable", false, { buf = self.view.buf })
api.nvim_set_option_value("filetype", "Avante", { buf = self.view.buf })
if opts.callback ~= nil then
opts.callback()
end
if opts.focus and not self:is_focused() then
xpcall(function()
--- set cursor to bottom of result view
api.nvim_set_current_win(self.winid.result)
end, function(err)
return err
end)
end
opts = vim.tbl_deep_extend("force", { focus = true, scroll = true, stream = false, callback = nil }, opts or {})
if opts.stream then
vim.schedule(function()
api.nvim_set_option_value("modifiable", true, { buf = self.view.buf })
local current_window = vim.api.nvim_get_current_win()
local cursor_position = vim.api.nvim_win_get_cursor(current_window)
local row, col = cursor_position[1], cursor_position[2]
if opts.scroll then
xpcall(function()
api.nvim_win_set_cursor(self.winid.result, { api.nvim_buf_line_count(self.bufnr.result), 0 })
end, function(err)
return err
end)
end
end, 0)
local lines = vim.split(content, "\n")
vim.api.nvim_put(lines, "c", true, true)
local num_lines = #lines
local last_line_length = #lines[num_lines]
vim.api.nvim_win_set_cursor(current_window, { row + num_lines - 1, col + last_line_length })
end)
else
vim.defer_fn(function()
api.nvim_set_option_value("modifiable", true, { buf = self.view.buf })
api.nvim_buf_set_lines(self.view.buf, 0, -1, false, vim.split(content, "\n"))
api.nvim_set_option_value("modifiable", false, { buf = self.view.buf })
api.nvim_set_option_value("filetype", "Avante", { buf = self.view.buf })
if opts.callback ~= nil then
opts.callback()
end
if opts.focus and not self:is_focused() then
xpcall(function()
--- set cursor to bottom of result view
api.nvim_set_current_win(self.winid.result)
end, function(err)
return err
end)
end
if opts.scroll then
xpcall(function()
api.nvim_win_set_cursor(self.winid.result, { api.nvim_buf_line_count(self.bufnr.result), 0 })
end, function(err)
return err
end)
end
end, 0)
end
return self
end
@@ -638,7 +670,7 @@ function Sidebar:render()
local filetype = api.nvim_get_option_value("filetype", { buf = self.code.buf })
AiBot.call_ai_api_stream(
AiBot.invoke_llm_stream(
request,
filetype,
content_with_line_numbers,
@@ -646,7 +678,7 @@ function Sidebar:render()
function(chunk)
signal.is_loading = true
full_response = full_response .. chunk
self:update_content(content_prefix .. full_response)
self:update_content(chunk, { stream = true, scroll = false })
vim.schedule(function()
vim.cmd("redraw")
end)