Skip to content

Buffer not reloaded after eca applies a file change #70

Description

@tamercuba

Problem

When I accept a tool call that edits a file I have open in a buffer, the buffer keeps showing the old content so I have to manually run :e/:checktime to see ecas change reflected.

This is different from external tools that write to disk out-of-process (claude cli running in a separate terminal for example): switching focus back to nvim there fires FocusGained, which triggers checktime via a normal autoread-style autocmd, so the buffer reloads automatically. With eca-nvim, since the edit is applied from within the same nvim session, theres no equivalent focus/refocus event to trigger a reload, so the buffer silently goes stale.

Looking at the source, chat/toolCallApprove:

eca-nvim/lua/eca/sidebar.lua

Lines 1455 to 1465 in 0e0dbe9

if tool_content.type == "toolCallRun" and tool_content.manualApproval then
-- Mark as shown to prevent duplicate approval dialogs from implicit flow
if self._current_tool_call then
self._current_tool_call.approval_shown = true
end
return require("eca.approve").approve_tool_call(tool_content, function()
self.mediator:send("chat/toolCallApprove", { chatId = chat_id, toolCallId = tool_content.id }, nil)
end, function()
self.mediator:send("chat/toolCallReject", { chatId = chat_id, toolCallId = tool_content.id }, nil)
end)
end

eca-nvim/lua/eca/sidebar.lua

Lines 1491 to 1495 in 0e0dbe9

return require("eca.approve").approve_tool_call(prepared_tool_call, function()
self.mediator:send("chat/toolCallApprove", { chatId = chat_id, toolCallId = tool_call_id }, nil)
end, function()
self.mediator:send("chat/toolCallReject", { chatId = chat_id, toolCallId = tool_call_id }, nil)
end)

only notifies the eca server which changes the file. On the client side, when the server later confirms completion via toolCalled with details.type == "fileChange":

eca-nvim/lua/eca/sidebar.lua

Lines 1295 to 1316 in 0e0dbe9

elseif content.type == "toolCalled" then
local tool_text = self:_tool_call_text(content)
-- If this tool call reports a file change, append the basename of the
-- path to the summary shown in the chat so users can immediately see
-- which file was touched.
local details = content.details
if details and type(details) == "table" and details.type == "fileChange" then
local path = details.path
if path and path ~= "" then
local filename = vim.fn.fnamemodify(path, ":t")
if filename and filename ~= "" then
-- Avoid duplicating the filename if it is already present
if tool_text and tool_text ~= "" then
if not string.find(tool_text, filename, 1, true) then
tool_text = string.format("%s %s", tool_text, filename)
end
else
tool_text = filename
end
end
end

the plugin uses details.path only to prettify the chat summary text, it never touches the corresponding nvim buffer.

I couldnt find a checktime call, or any FileChangedShell/reload-triggering autocmd, anywhere in the plugin.

Possible solution

At the point where toolCalled/fileChange is handled (sidebar.lua:1295-1314), the path is already available. Resolving it to a loaded buffer and calling checktime on it there would sync the buffer right when the server confirms the write:

local bufnr = vim.fn.bufnr(vim.fn.fnamemodify(path, ":p"))
if bufnr ~= -1 and vim.api.nvim_buf_is_loaded(bufnr) then
  vim.api.nvim_buf_call(bufnr, function()
    vim.cmd("checktime")
  end)
end

checktime respects autoread/local unsaved changes.

Questions

  1. Do you agree this is a real gap, or is there already a recommended workaround/config Im missing?
  2. If it is a gap, do you already have a preferred approach in mind (maybe reloading all affected buffers after every apply, rather than per tool call)?
  3. Would a PR implementing the snippet above (or something close to it) be welcome?
  4. If yes, do you think this should be backed by a config flag to keep the current eca-nvim behavior as the default?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions