diff --git a/.omp/tools/nvim_buffers.mjs b/.omp/tools/nvim_buffers.mjs deleted file mode 100644 index 82e9ce6..0000000 --- a/.omp/tools/nvim_buffers.mjs +++ /dev/null @@ -1,185 +0,0 @@ -// omp custom tool: read this machine's running Neovim buffers over its RPC -// socket. Read-only and on-demand — the model calls it when it needs buffer -// content; nothing is injected into prompts automatically. -// -// Install options -// 1. Project scope (this project): keep the file in .omp/tools/ — omp picks it -// up when a session's cwd is inside this repository. -// 2. All projects: mkdir -p ~/.omp/agent/tools -// ln -s "$PWD/.omp/tools/nvim_buffers.mjs" ~/.omp/agent/tools/ -// then restart `omp` (custom tools are loaded at session bootstrap). -// -// Socket contract (must match lua/nvim_omp/init.lua): -// path = $NVIM_OMP_SOCKET or /nvim/omp.sock -// The nvim instance running this config starts the listener at startup. -// Only one instance can own the socket; a second instance never replaces a -// live owner. Remove a stale socket manually only after confirming no nvim -// process owns it. - -import os from "node:os"; -import path from "node:path"; - -// Safe default cap so a large buffer cannot flood the conversation. -const DEFAULT_MAX_LINES = 2000; - -export default function (pi) { - // Resolve socket path with the same rule as lua/nvim_omp/init.lua. - const socketPath = () => { - const env = process.env.NVIM_OMP_SOCKET; - if (env) return env; - const state = - process.env.XDG_STATE_HOME || - path.join(os.homedir(), ".local", "state"); - return path.join(state, "nvim", "omp.sock"); - }; - - // Evaluate expr in the remote nvim via `nvim --server`; returns parsed JSON. - const rpc = async (expr, signal) => { - const bin = process.env.NVIM_BIN || "nvim"; - const { code, stdout, stderr, killed } = await pi.exec( - bin, - ["--server", socketPath(), "--remote-expr", expr], - { signal }, - ); - if (killed) throw new Error("cancelled"); - if (code !== 0) { - const why = String(stderr || "").trim(); - throw new Error( - why.includes("E247") - ? `No Neovim RPC socket at ${socketPath()}. ` + - "Start nvim (or vv) first — the 31_nvim_omp.lua plugin binds the socket at startup." - : `nvim RPC failed (${code}): ${why}`, - ); - } - const text = String(stdout ?? "").trim(); - if (!text) throw new Error("empty response from nvim RPC"); - return JSON.parse(text); - }; - - // Resolve a buffer argument (number, string, or partial path) to a buffer - // number. Returns null when nothing matches. - const resolveBuf = async (buffer, signal) => { - if (buffer === undefined || buffer === null || buffer === "") { - return rpc("json_encode(nvim_get_current_buf())", signal); - } - if (typeof buffer === "number") return buffer; - const bufnum = Number(buffer); - if (Number.isInteger(bufnum) && bufnum > 0) return bufnum; - const list = await rpc( - "json_encode(map(nvim_list_bufs(), {i, v -> " + - "{'bufnr': v, 'name': nvim_buf_get_name(v)}}))", - signal, - ); - const q = String(buffer); - const hit = - list.find( - (b) => b.name === q || b.name.endsWith("/" + q) || b.name.endsWith(q), - ) || - list.find((b) => b.name.includes(q)); - return hit ? hit.bufnr : null; - }; - - const tools = []; - - // List open buffers ----------------------------------------------- - tools.push({ - name: "nvim_buffers", - label: "Neovim Buffers", - description: - "List the buffers currently open in the user's running Neovim " + - "(number, name, current/loaded state, modified). Use before " + - "nvim_buffer to pick a buffer.", - parameters: pi.arktype({}), - async execute(_id, _params, _onUpdate, _ctx, _signal) { - const list = await rpc( - "json_encode(map(nvim_list_bufs(), {i, v -> {'nr': v, " + - "'name': nvim_buf_get_name(v), " + - "'current': v == nvim_get_current_buf(), " + - "'loaded': nvim_buf_is_loaded(v), " + - "'modified': getbufvar(v, '&modified')}}))", - ); - if (!list.length) { - return { content: [{ type: "text", text: "No buffers open." }] }; - } - const lines = list.map( - (b) => - `${b.nr}\t${b.name || "[no name]"}\t` + - `${b.current ? "current " : ""}` + - `${b.loaded ? "" : "unloaded "}` + - `${b.modified ? "modified" : ""}`.trim(), - ); - return { - content: [ - { - type: "text", - text: `Open buffers (${list.length}):\n` + lines.join("\n"), - }, - ], - }; - }, - }); - - // Read a single buffer, line-capped ------------------------------- - tools.push({ - name: "nvim_buffer", - label: "Neovim Buffer", - description: - "Read lines of a Neovim buffer. `buffer` accepts the current buffer " + - "(default), a buffer number from nvim_buffers, or a file name/path " + - "open in Neovim. `maxLines` caps the returned lines (default 2000); " + - "pass a larger value explicitly to read more of a long buffer.", - parameters: pi.arktype({ - buffer: "string? | number?", - maxLines: "number?", - }), - async execute(_id, params, _onUpdate, _ctx, signal) { - const buf = await resolveBuf(params.buffer, signal); - if (buf === null) { - return { - content: [ - { - type: "text", - text: `No buffer matches '${params.buffer}'. List open buffers with nvim_buffers.`, - }, - ], - }; - } - const maxLines = - Number.isInteger(params.maxLines) && params.maxLines > 0 - ? Math.min(params.maxLines, 100000) - : DEFAULT_MAX_LINES; - - const expr = - `json_encode({'name': nvim_buf_get_name(${buf}), ` + - `'total': nvim_buf_line_count(${buf}), ` + - `'lines': nvim_buf_get_lines(${buf}, 0, ${maxLines}, 0)})`; - const { name, total, lines } = await rpc(expr, signal); - if (!total) { - return { - content: [ - { type: "text", text: `Buffer ${buf} (${name}) is empty.` }, - ], - }; - } - const truncated = - total > lines.length - ? `\n... ${total - lines.length} more lines ` + - `(raise maxLines to read them)` - : ""; - const numbered = lines.map((l, i) => `${i + 1}: ${l}`).join("\n"); - return { - content: [ - { - type: "text", - text: - `Buffer ${buf} (${name}), ${total} lines:\n` + - numbered + - truncated, - }, - ], - }; - }, - }); - - return tools; -} \ No newline at end of file diff --git a/lua/nvim_omp/init.lua b/lua/nvim_omp/init.lua deleted file mode 100644 index 4400d49..0000000 --- a/lua/nvim_omp/init.lua +++ /dev/null @@ -1,55 +0,0 @@ --- omp bridge: expose an RPC socket so the omp harness can read this Neovim --- instance's buffers on demand. Read-only on the agent side; this module only --- owns the socket lifecycle. --- --- Contract --- * Socket path: $NVIM_OMP_SOCKET if set, else /omp.sock --- (~/.local/state/nvim/omp.sock on macOS, ~/.local/state/nvim/omp.sock --- elsewhere). The omp-side tool in .omp/tools/nvim_buffers.mjs resolves the --- *same* path, so the two sides agree without configuration. --- * The agent reads buffers by evaluating read-only nvim API expressions over --- the socket with `nvim --server --remote-expr 'json_encode(...)'`. --- Nothing here writes buffers or executes model-supplied commands. -local M = {} - -local SOCKET_NAME = "omp.sock" - --- Resolve the deterministic socket path. Copies the rule on the omp side; keep --- the two files in sync when changing the fallback or env override. -function M.socket_path() - local env = vim.env.NVIM_OMP_SOCKET - if env and env ~= "" then - return env - end - return vim.fn.stdpath("state") .. "/" .. SOCKET_NAME -end - --- Start the RPC listener. Returns the live socket path, or nil. --- A second instance cannot bind the same address. This function deliberately --- never removes an existing socket file: a failed liveness probe must not --- disconnect another live Neovim instance. --- If a crash leaves a stale socket, remove it manually only after confirming --- that no Neovim process owns the path, then restart vv. -function M.start() - if vim.v.headless == 1 then - -- Headless runs (tests, CI) get no socket; nothing should depend on one. - return nil - end - - local path = M.socket_path() - local ok, res = pcall(vim.fn.serverstart, path) - if ok and type(res) == "string" and res ~= "" then - -- serverstart returns the bound address string (e.g. "/tmp/omp.sock"). - vim.notify("nvim_omp: RPC socket ready at " .. path, vim.log.levels.INFO) - return path - end - - vim.notify( - "nvim_omp: could not bind RPC socket at " .. path - .. "; another instance may own it or a stale socket needs manual cleanup.", - vim.log.levels.WARN - ) - return nil -end - -return M diff --git a/plugin/30_dooing.lua b/plugin/30_dooing.lua index f47ecc2..0ec1a09 100644 --- a/plugin/30_dooing.lua +++ b/plugin/30_dooing.lua @@ -13,32 +13,16 @@ end local nix = require('config.nix') local later = MiniDeps.later -local now = MiniDeps.now + later(function() if not nix.get_cat('general', false) then return end - local dooing = require('dooing') - require("dooing").setup({ + require('dooing').setup({ keymaps = { - toggle_window = "cd", - open_project_todo = "cD", - show_due_notification = "cN", - create_nested_task = "cn", -- Create nested subtask under current todo - toggle_priority = "a", - }, - calendar = { - week_start_day = "monday", + toggle_window = 'cd', + open_project_todo = 'cD', + show_due_notification = 'cN', }, }) - -- Remove Dooing's old defaults. - vim.keymap.del("n", "td") - vim.keymap.del("n", "tD") - vim.keymap.del("n", "tN") - - -- Restore mappings overwritten by Dooing. - local helpers = require('keymap.helpers') - local nmap_leader = helpers.nmap_leader - -- t is for 'terminal' - nmap_leader("td", 'lua Config.terminal.open_duckdb();Config.terminal.toggle_bracket()', 'Open DuckDB') -end) +end) \ No newline at end of file diff --git a/plugin/31_nvim_omp.lua b/plugin/31_nvim_omp.lua deleted file mode 100644 index 44076cf..0000000 --- a/plugin/31_nvim_omp.lua +++ /dev/null @@ -1,8 +0,0 @@ --- omp bridge entrypoint: start the RPC socket as early as possible so the omp --- harness can read this instance's buffers on demand (see lua/nvim_omp/init.lua --- and .omp/tools/nvim_buffers.mjs). Safe to fail silently — the socket is a --- convenience, not a dependency of the editor. -local ok, nvim_omp = pcall(require, "nvim_omp") -if ok then - nvim_omp.start() -end \ No newline at end of file