feat: Implement lightweight UDP interactive UI for Neovim
- Rewrote gemini-ui.lua to send native Neovim prompt selections, Ghost Text diff accept/reject actions, and smart context highlighting directly to the backend via zero-latency UDP port 3002, entirely replacing the old xecute_agent terminal subprocesses. - Added prompt_user and preview_diff extmark lua functions for non-destructive diff review. - Updated the Rust backend mcp-memory-server UDP listener to ingest the new gent_ask and interactive schema payloads and route them to the EventBus. - Updated README.md and instructions.md with UDP documentation.
This commit is contained in:
1 parent
b3c64c1ad8
commit
4e23043f5d
5 files changed
+147
-27
No files matched your search
+117
-25
@@ -55,35 +55,118 @@ function M.close_progress()
|
||||
end
|
||||
end
|
||||
|
||||
local function execute_agent(prompt)
|
||||
local cmd = { "agy", "--new-project", "-i", prompt }
|
||||
|
||||
M.show_progress("Starting Antigravity...")
|
||||
|
||||
-- termopen requires an empty and unmodified buffer
|
||||
vim.api.nvim_buf_set_lines(progress_buf, 0, -1, false, {})
|
||||
vim.bo[progress_buf].modified = false
|
||||
|
||||
-- termopen will attach to the current buffer (which show_progress just focused)
|
||||
job_id = vim.fn.termopen(cmd, {
|
||||
on_exit = function(_, code)
|
||||
job_id = nil
|
||||
local function send_udp(payload)
|
||||
local uv = vim.uv or vim.loop
|
||||
local client = uv.new_udp()
|
||||
if client then
|
||||
local ok, data = pcall(vim.fn.json_encode, payload)
|
||||
if ok then
|
||||
client:send(data, "127.0.0.1", 3002, function(err)
|
||||
client:close()
|
||||
end)
|
||||
else
|
||||
client:close()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.prompt_user(prompt_text, options, request_id)
|
||||
if options and #options > 0 then
|
||||
vim.ui.select(options, { prompt = prompt_text }, function(choice, idx)
|
||||
send_udp({
|
||||
event = "agent_prompt_response",
|
||||
request_id = request_id,
|
||||
response = choice,
|
||||
index = idx,
|
||||
session_id = vim.v.servername
|
||||
})
|
||||
end)
|
||||
else
|
||||
vim.ui.input({ prompt = prompt_text }, function(input)
|
||||
send_udp({
|
||||
event = "agent_prompt_response",
|
||||
request_id = request_id,
|
||||
response = input,
|
||||
session_id = vim.v.servername
|
||||
})
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
local ns_id = vim.api.nvim_create_namespace("gemini_ghost_text")
|
||||
local active_diffs = {}
|
||||
|
||||
function M.preview_diff(diff_id, bufnr, start_row, end_row, new_lines)
|
||||
bufnr = (bufnr == 0 or bufnr == nil) and vim.api.nvim_get_current_buf() or bufnr
|
||||
local virt_lines = {}
|
||||
for _, line in ipairs(new_lines) do
|
||||
table.insert(virt_lines, {{line, "DiffAdd"}})
|
||||
end
|
||||
|
||||
local extmark_id = vim.api.nvim_buf_set_extmark(bufnr, ns_id, start_row, 0, {
|
||||
virt_lines = virt_lines,
|
||||
virt_lines_above = true,
|
||||
})
|
||||
vim.cmd('startinsert')
|
||||
|
||||
active_diffs[diff_id] = {
|
||||
bufnr = bufnr,
|
||||
start_row = start_row,
|
||||
end_row = end_row,
|
||||
new_lines = new_lines,
|
||||
extmark_id = extmark_id
|
||||
}
|
||||
|
||||
if pcall(require, "notify") then
|
||||
require("notify")("Ghost text diff added. Use <leader>aa to accept or <leader>ar to reject.", "info", { title = "Antigravity" })
|
||||
else
|
||||
print("Ghost text diff added. Use <leader>aa to accept or <leader>ar to reject.")
|
||||
end
|
||||
end
|
||||
|
||||
function M.accept_diff()
|
||||
local diff_id, diff = next(active_diffs)
|
||||
if not diff then
|
||||
print("No active diffs to accept.")
|
||||
return
|
||||
end
|
||||
|
||||
vim.api.nvim_buf_set_lines(diff.bufnr, diff.start_row, diff.end_row, false, diff.new_lines)
|
||||
vim.api.nvim_buf_del_extmark(diff.bufnr, ns_id, diff.extmark_id)
|
||||
active_diffs[diff_id] = nil
|
||||
|
||||
send_udp({ event = "agent_diff_accepted", diff_id = diff_id, session_id = vim.v.servername })
|
||||
print("Diff accepted.")
|
||||
end
|
||||
|
||||
function M.reject_diff()
|
||||
local diff_id, diff = next(active_diffs)
|
||||
if not diff then
|
||||
print("No active diffs to reject.")
|
||||
return
|
||||
end
|
||||
|
||||
vim.api.nvim_buf_del_extmark(diff.bufnr, ns_id, diff.extmark_id)
|
||||
active_diffs[diff_id] = nil
|
||||
|
||||
send_udp({ event = "agent_diff_rejected", diff_id = diff_id, session_id = vim.v.servername })
|
||||
print("Diff rejected.")
|
||||
end
|
||||
|
||||
function M.ask_agent()
|
||||
local file = vim.api.nvim_buf_get_name(0)
|
||||
vim.ui.input({ prompt = 'Ask Agent: ' }, function(input)
|
||||
if not input or input == '' then return end
|
||||
|
||||
local final_input = input
|
||||
if file and file ~= "" then
|
||||
final_input = input .. string.format(" [Context file: %s]", file)
|
||||
end
|
||||
|
||||
execute_agent(final_input)
|
||||
local cursor = vim.api.nvim_win_get_cursor(0)
|
||||
send_udp({
|
||||
event = "agent_ask",
|
||||
prompt = input,
|
||||
file = file,
|
||||
line = cursor[1],
|
||||
col = cursor[2],
|
||||
session_id = vim.v.servername
|
||||
})
|
||||
M.show_progress("Sent to Antigravity via UDP...")
|
||||
vim.defer_fn(M.close_progress, 1500)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -97,12 +180,21 @@ function M.setup()
|
||||
if not input or input == '' then return end
|
||||
|
||||
local file = vim.api.nvim_buf_get_name(0)
|
||||
local context = string.format(" [Context: %s lines %d-%d]", file, csrow, cerow)
|
||||
local final_input = input .. context
|
||||
|
||||
execute_agent(final_input)
|
||||
send_udp({
|
||||
event = "agent_ask_selection",
|
||||
prompt = input,
|
||||
file = file,
|
||||
start_row = csrow,
|
||||
end_row = cerow,
|
||||
session_id = vim.v.servername
|
||||
})
|
||||
M.show_progress("Sent selection to Antigravity via UDP...")
|
||||
vim.defer_fn(M.close_progress, 1500)
|
||||
end)
|
||||
end, { desc = "Ask Antigravity Agent about selection", noremap = true, silent = true })
|
||||
|
||||
vim.keymap.set('n', '<leader>aa', M.accept_diff, { desc = "Accept Agent Diff", noremap = true, silent = true })
|
||||
vim.keymap.set('n', '<leader>ar', M.reject_diff, { desc = "Reject Agent Diff", noremap = true, silent = true })
|
||||
end
|
||||
|
||||
return M
|
||||
Reference in new issue
Block a user