fix: wrap all ACP handlers in vim.schedule to ensure safe UI operations (#2670)

This commit is contained in:
yetone
2025-09-02 13:37:26 +08:00
committed by GitHub
parent 8794356cf4
commit a4a4c91711
2 changed files with 55 additions and 53 deletions

View File

@@ -566,7 +566,7 @@ function ACPClient:_handle_session_update(params)
end end
if self.config.handlers and self.config.handlers.on_session_update then if self.config.handlers and self.config.handlers.on_session_update then
self.config.handlers.on_session_update(update) vim.schedule(function() self.config.handlers.on_session_update(update) end)
end end
end end
@@ -581,18 +581,20 @@ function ACPClient:_handle_request_permission(message_id, params)
if not session_id or not tool_call then return end if not session_id or not tool_call then return end
if self.config.handlers and self.config.handlers.on_request_permission then if self.config.handlers and self.config.handlers.on_request_permission then
self.config.handlers.on_request_permission( vim.schedule(function()
tool_call, self.config.handlers.on_request_permission(
options, tool_call,
function(option_id) options,
self:_send_result(message_id, { function(option_id)
outcome = { self:_send_result(message_id, {
outcome = "selected", outcome = {
optionId = option_id, outcome = "selected",
}, optionId = option_id,
}) },
end })
) end
)
end)
end end
end end
@@ -606,12 +608,14 @@ function ACPClient:_handle_read_text_file(message_id, params)
if not session_id or not path then return end if not session_id or not path then return end
if self.config.handlers and self.config.handlers.on_read_file then if self.config.handlers and self.config.handlers.on_read_file then
self.config.handlers.on_read_file( vim.schedule(function()
path, self.config.handlers.on_read_file(
params.line ~= vim.NIL and params.line or nil, path,
params.limit ~= vim.NIL and params.limit or nil, params.line ~= vim.NIL and params.line or nil,
function(content) self:_send_result(message_id, { content = content }) end params.limit ~= vim.NIL and params.limit or nil,
) function(content) self:_send_result(message_id, { content = content }) end
)
end)
end end
end end
@@ -626,11 +630,13 @@ function ACPClient:_handle_write_text_file(message_id, params)
if not session_id or not path or not content then return end if not session_id or not path or not content then return end
if self.config.handlers and self.config.handlers.on_write_file then if self.config.handlers and self.config.handlers.on_write_file then
self.config.handlers.on_write_file( vim.schedule(function()
path, self.config.handlers.on_write_file(
content, path,
function(error) self:_send_result(message_id, error == nil and vim.NIL or error) end content,
) function(error) self:_send_result(message_id, error == nil and vim.NIL or error) end
)
end)
end end
end end

View File

@@ -988,40 +988,36 @@ function M._stream_acp(opts)
end, end,
}) })
vim.schedule(function() selector:open() end) selector:open()
end, end,
on_read_file = function(path, line, limit, callback) on_read_file = function(path, line, limit, callback)
vim.schedule(function() local abs_path = Utils.to_absolute_path(path)
local abs_path = Utils.to_absolute_path(path) local lines = Utils.read_file_from_buf_or_disk(abs_path)
local lines = Utils.read_file_from_buf_or_disk(abs_path) lines = lines or {}
lines = lines or {} if line ~= nil and limit ~= nil then lines = vim.list_slice(lines, line, line + limit) end
if line ~= nil and limit ~= nil then lines = vim.list_slice(lines, line, line + limit) end callback(table.concat(lines, "\n"))
callback(table.concat(lines, "\n"))
end)
end, end,
on_write_file = function(path, content, callback) on_write_file = function(path, content, callback)
vim.schedule(function() local abs_path = Utils.to_absolute_path(path)
local abs_path = Utils.to_absolute_path(path) local file = io.open(abs_path, "w")
local file = io.open(abs_path, "w") if file then
if file then file:write(content)
file:write(content) file:close()
file:close() local buffers = vim.tbl_filter(
local buffers = vim.tbl_filter( function(bufnr)
function(bufnr) return vim.api.nvim_buf_is_valid(bufnr)
return vim.api.nvim_buf_is_valid(bufnr) and vim.fn.fnamemodify(vim.api.nvim_buf_get_name(bufnr), ":p")
and vim.fn.fnamemodify(vim.api.nvim_buf_get_name(bufnr), ":p") == vim.fn.fnamemodify(abs_path, ":p")
== vim.fn.fnamemodify(abs_path, ":p") end,
end, vim.api.nvim_list_bufs()
vim.api.nvim_list_bufs() )
) for _, buf in ipairs(buffers) do
for _, buf in ipairs(buffers) do vim.api.nvim_buf_call(buf, function() vim.cmd("edit") end)
vim.api.nvim_buf_call(buf, function() vim.cmd("edit") end)
end
callback(nil)
return
end end
callback("Failed to write file: " .. abs_path) callback(nil)
end) return
end
callback("Failed to write file: " .. abs_path)
end, end,
}, },
}) })