feat(api): support native chat mode (#541)

Signed-off-by: Aaron Pham <contact@aarnphm.xyz>
This commit is contained in:
Aaron Pham 2024-09-05 02:43:31 -04:00 committed by GitHub
parent a8ef7de7d8
commit 29e109e447
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 45 additions and 23 deletions

View File

@ -1,4 +1,4 @@
function avante#build(...) abort function avante#build(...) abort
let l:source = get(a:, 1, v:false) let l:source = get(a:, 1, v:false)
return join(luaeval("require('avante').build(_A)", l:source), "\n") return join(luaeval("require('avante_lib').load()"),"\n",luaeval("require('avante.api').build(_A)", l:source), "\n")
endfunction endfunction

View File

@ -73,9 +73,9 @@ M.build = function(opts)
local output = stdout local output = stdout
if #output == 0 then if #output == 0 then
table.insert(output, "") table.insert(output, "")
Utils.info("outputs: " .. output) Utils.debug(output)
else else
Utils.error("error: " .. stderr) Utils.debug(stderr)
end end
end end
end) end)
@ -87,6 +87,7 @@ end
---@class AskOptions ---@class AskOptions
---@field question? string optional questions ---@field question? string optional questions
---@field win? table<string, any> windows options similar to |nvim_open_win()| ---@field win? table<string, any> windows options similar to |nvim_open_win()|
---@field ask? boolean
---@param opts? AskOptions ---@param opts? AskOptions
M.ask = function(opts) M.ask = function(opts)

View File

@ -36,16 +36,25 @@ H.commands = function()
---@type AskOptions ---@type AskOptions
local args = { question = nil, win = {} } local args = { question = nil, win = {} }
local q_parts = {} local q_parts = {}
local q_ask = nil
for _, arg in ipairs(opts.fargs) do for _, arg in ipairs(opts.fargs) do
local value = arg:match("position=(%w+)") local value = arg:match("position=(%w+)")
if value then local ask = arg:match("ask=(%w+)")
if ask ~= nil then
q_ask = ask == "true"
elseif value then
args.win.position = value args.win.position = value
else else
table.insert(q_parts, arg) table.insert(q_parts, arg)
end end
end end
args.question = #q_parts > 0 and table.concat(q_parts, " ") or nil require("avante.api").ask(
require("avante.api").ask(args) vim.tbl_deep_extend(
"force",
args,
{ ask = q_ask, question = #q_parts > 0 and table.concat(q_parts, " ") or nil }
)
)
end, { end, {
desc = "avante: ask AI for code suggestions", desc = "avante: ask AI for code suggestions",
nargs = "*", nargs = "*",
@ -56,6 +65,7 @@ H.commands = function()
---@param x string ---@param x string
vim.tbl_map(function(x) return "position=" .. x end, { "left", "right", "top", "bottom" }) vim.tbl_map(function(x) return "position=" .. x end, { "left", "right", "top", "bottom" })
) )
vim.list_extend(candidates, vim.tbl_map(function(x) return "ask=" .. x end, { "true", "false" }))
return candidates return candidates
end, end,
}) })
@ -283,6 +293,8 @@ M.toggle = { api = true }
---@param opts? AskOptions ---@param opts? AskOptions
M.toggle_sidebar = function(opts) M.toggle_sidebar = function(opts)
opts = opts or {} opts = opts or {}
if opts.ask == nil then opts.ask = true end
local sidebar = M.get() local sidebar = M.get()
if not sidebar then if not sidebar then
M._init(api.nvim_get_current_tabpage()) M._init(api.nvim_get_current_tabpage())

View File

@ -29,6 +29,7 @@ local group = api.nvim_create_augroup("avante_llm", { clear = true })
---@field memory_context string | nil ---@field memory_context string | nil
--- ---
---@class StreamOptions: TemplateOptions ---@class StreamOptions: TemplateOptions
---@field ask boolean
---@field bufnr integer ---@field bufnr integer
---@field instructions string ---@field instructions string
---@field mode LlmMode ---@field mode LlmMode
@ -60,7 +61,7 @@ M.stream = function(opts)
local template_opts = { local template_opts = {
use_xml_format = Provider.use_xml_format, use_xml_format = Provider.use_xml_format,
ask = true, -- TODO: add mode without ask instruction ask = opts.ask, -- TODO: add mode without ask instruction
question = original_instructions, question = original_instructions,
code_lang = opts.code_lang, code_lang = opts.code_lang,
file_content = opts.file_content, file_content = opts.file_content,

View File

@ -395,6 +395,7 @@ function Selection:create_editing_input()
Llm.stream({ Llm.stream({
bufnr = code_bufnr, bufnr = code_bufnr,
ask = true,
file_content = code_content, file_content = code_content,
code_lang = filetype, code_lang = filetype,
selected_code = self.selection.content, selected_code = self.selection.content,

View File

@ -66,7 +66,7 @@ function Sidebar:reset()
self.input = nil self.input = nil
end end
---@param opts? AskOptions ---@param opts AskOptions
function Sidebar:open(opts) function Sidebar:open(opts)
local in_visual_mode = Utils.in_visual_mode() and self:in_code_win() local in_visual_mode = Utils.in_visual_mode() and self:in_code_win()
if not self:is_open() then if not self:is_open() then
@ -122,7 +122,7 @@ end
function Sidebar:in_code_win() return self.code.winid == api.nvim_get_current_win() end function Sidebar:in_code_win() return self.code.winid == api.nvim_get_current_win() end
---@param opts? table<string, any> ---@param opts AskOptions
function Sidebar:toggle(opts) function Sidebar:toggle(opts)
local in_visual_mode = Utils.in_visual_mode() and self:in_code_win() local in_visual_mode = Utils.in_visual_mode() and self:in_code_win()
if self:is_open() and not in_visual_mode then if self:is_open() and not in_visual_mode then
@ -592,7 +592,9 @@ function Sidebar:render_result()
self:render_header(self.result.winid, self.result.bufnr, header_text, Highlights.TITLE, Highlights.REVERSED_TITLE) self:render_header(self.result.winid, self.result.bufnr, header_text, Highlights.TITLE, Highlights.REVERSED_TITLE)
end end
function Sidebar:render_input() ---@param ask? boolean
function Sidebar:render_input(ask)
if ask == nil then ask = true end
if not self.input or not self.input.bufnr or not api.nvim_buf_is_valid(self.input.bufnr) then return end if not self.input or not self.input.bufnr or not api.nvim_buf_is_valid(self.input.bufnr) then return end
local filetype = api.nvim_get_option_value("filetype", { buf = self.code.bufnr }) local filetype = api.nvim_get_option_value("filetype", { buf = self.code.bufnr })
@ -614,11 +616,13 @@ function Sidebar:render_input()
local code_file_fullpath = api.nvim_buf_get_name(self.code.bufnr) local code_file_fullpath = api.nvim_buf_get_name(self.code.bufnr)
local code_filename = fn.fnamemodify(code_file_fullpath, ":t") local code_filename = fn.fnamemodify(code_file_fullpath, ":t")
local header_text = string.format("󱜸 Chat with %s %s (<Tab>: switch focus)", icon, code_filename) local header_text =
string.format("󱜸 %s %s %s (<Tab>: switch focus)", ask and "Ask" or "Chat with", icon, code_filename)
if self.code.selection ~= nil then if self.code.selection ~= nil then
header_text = string.format( header_text = string.format(
"󱜸 Chat with %s %s(%d:%d) (<Tab>: switch focus)", "󱜸 %s %s %s(%d:%d) (<Tab>: switch focus)",
ask and "Ask" or "Chat with",
icon, icon,
code_filename, code_filename,
self.code.selection.range.start.line, self.code.selection.range.start.line,
@ -664,7 +668,8 @@ function Sidebar:render_selected_code()
) )
end end
function Sidebar:on_mount() ---@param opts AskOptions
function Sidebar:on_mount(opts)
self:refresh_winids() self:refresh_winids()
api.nvim_set_option_value("wrap", Config.windows.wrap, { win = self.result.winid }) api.nvim_set_option_value("wrap", Config.windows.wrap, { win = self.result.winid })
@ -795,7 +800,7 @@ function Sidebar:on_mount()
}) })
self:render_result() self:render_result()
self:render_input() self:render_input(opts.ask)
self:render_selected_code() self:render_selected_code()
self.augroup = api.nvim_create_augroup("avante_sidebar_" .. self.id .. self.result.winid, { clear = true }) self.augroup = api.nvim_create_augroup("avante_sidebar_" .. self.id .. self.result.winid, { clear = true })
@ -1148,7 +1153,8 @@ end
local hint_window = nil local hint_window = nil
function Sidebar:create_input() ---@param opts AskOptions
function Sidebar:create_input(opts)
if self.input then self.input:unmount() end if self.input then self.input:unmount() end
if not self.code.bufnr or not api.nvim_buf_is_valid(self.code.bufnr) then return end if not self.code.bufnr or not api.nvim_buf_is_valid(self.code.bufnr) then return end
@ -1266,6 +1272,7 @@ function Sidebar:create_input()
Llm.stream({ Llm.stream({
bufnr = self.code.bufnr, bufnr = self.code.bufnr,
ask = opts.ask,
file_content = content_with_line_numbers, file_content = content_with_line_numbers,
code_lang = filetype, code_lang = filetype,
selected_code = selected_code_content_with_line_numbers, selected_code = selected_code_content_with_line_numbers,
@ -1396,7 +1403,7 @@ function Sidebar:create_input()
local width = #hint_text local width = #hint_text
-- Set the floating window options -- Set the floating window options
local opts = { local win_opts = {
relative = "win", relative = "win",
win = self.input.winid, win = self.input.winid,
width = width, width = width,
@ -1410,7 +1417,7 @@ function Sidebar:create_input()
} }
-- Create the floating window -- Create the floating window
hint_window = api.nvim_open_win(buf, false, opts) hint_window = api.nvim_open_win(buf, false, win_opts)
api.nvim_win_set_hl_ns(hint_window, Highlights.hint_ns) api.nvim_win_set_hl_ns(hint_window, Highlights.hint_ns)
end end
@ -1461,14 +1468,14 @@ function Sidebar:create_input()
end, end,
}) })
self:refresh_winids()
api.nvim_create_autocmd("User", { api.nvim_create_autocmd("User", {
pattern = "AvanteInputSubmitted", pattern = "AvanteInputSubmitted",
callback = function(ev) callback = function(ev)
if ev.data and ev.data.request then handle_submit(ev.data.request) end if ev.data and ev.data.request then handle_submit(ev.data.request) end
end, end,
}) })
self:refresh_winids()
end end
function Sidebar:get_selected_code_size() function Sidebar:get_selected_code_size()
@ -1485,9 +1492,8 @@ function Sidebar:get_selected_code_size()
return selected_code_size return selected_code_size
end end
---@param opts? AskOptions ---@param opts AskOptions
function Sidebar:render(opts) function Sidebar:render(opts)
opts = opts or {}
local chat_history = Path.history.load(self.code.bufnr) local chat_history = Path.history.load(self.code.bufnr)
local get_position = function() local get_position = function()
@ -1546,7 +1552,7 @@ function Sidebar:render(opts)
self:close() self:close()
end) end)
self:create_input() self:create_input(opts)
self:update_content_with_history(chat_history) self:update_content_with_history(chat_history)
@ -1557,7 +1563,7 @@ function Sidebar:render(opts)
self:create_selected_code() self:create_selected_code()
self:on_mount() self:on_mount(opts)
return self return self
end end

View File

@ -107,6 +107,7 @@ function Suggestion:suggest()
Llm.stream({ Llm.stream({
bufnr = bufnr, bufnr = bufnr,
ask = true,
file_content = code_content, file_content = code_content,
code_lang = filetype, code_lang = filetype,
instructions = vim.json.encode(doc), instructions = vim.json.encode(doc),