diff --git a/config/fish/config.fish b/config/fish/config.fish index ee19e52..bae9be6 100644 --- a/config/fish/config.fish +++ b/config/fish/config.fish @@ -25,7 +25,7 @@ if status is-interactive command -qv tree && alias dtree "tree -L 3 -a -d -I '.git' --charset X " command -qv wl-copy && alias cwd "wl-copy \$(pwd)" - command -qv wl-copy && alias copy-cmd "wl-copy \$(echo \$history[1])" + command -qv wl-copy && alias cc "wl-copy \$(echo \$history[1])" command -qv fabric-ai && alias ai "fabric-ai -p \$(fabric-ai -l | fzf)" command -qv xdg-open && alias o "xdg-open" @@ -49,6 +49,10 @@ if status is-interactive command -qv jj && alias rev "jj log -G -T 'commit_id.short(8)'" + if command -qv shred + alias nuke "shred -u -n 1" + end + if command -qv wt; alias wtc "wt switch --create --execute=$EDITOR" alias wts "wt switch" @@ -84,6 +88,7 @@ if status is-interactive if test -x /usr/bin/fzf; /usr/bin/fzf --fish | source + alias zk="nvim \$(fzf --walker=file --walker-root=/home/sjb/Documents/nca-notes/ --preview 'bat --color=always -n --line-range :500 {}')" #set -gx FZF_CTRL_T_OPTS "--preview 'bat --color=always -n --line-range :500 {}'" #set -gx FZF_ALT_C_OPTS "--preview 'eza --icons=always --color=always {} | head -200'" end diff --git a/config/nvim/plugin/codecompanion.lua b/config/nvim/plugin/codecompanion.lua index 18438da..06b868f 100644 --- a/config/nvim/plugin/codecompanion.lua +++ b/config/nvim/plugin/codecompanion.lua @@ -1,12 +1,11 @@ vim.keymap.set({'n', 'v'}, 'mct', 'CodeCompanionChat Toggle', { noremap = true, silent = true, desc = "CC Toggle" }) vim.keymap.set({'n', 'v'}, 'mca', 'CodeCompanionActions', { noremap = true, silent = true, desc = "CC Action" }) -vim.keymap.set({'n'}, 'mce', 'CodeCompanion Explain', { desc = "CC Explain" }) +vim.keymap.set({'n', 'v'}, 'mce', 'CodeCompanion Explain', { desc = "CC Explain" }) vim.keymap.set({'n'}, 'mcf', 'CodeCompanion Fix code', { desc = "CC fix" }) vim.keymap.set({'v'}, 'mcc', 'CodeCompanionChat Add', { noremap = true, silent = true, desc = "CC Add" }) vim.keymap.set({'v'}, 'mcr', 'CodeCompanion Code Review', { desc = 'Code Review' }) vim.keymap.set({'v'}, 'mco', 'CodeCompanion Optimize Performance', { desc = 'Optimize Code' }) -vim.keymap.set({'v'}, 'mce', 'CodeCompanion Explain Code', { desc = 'Explain Code' }) vim.keymap.set({'v'}, 'mcg', 'CodeCompanion Generate Tests', { desc = 'Generate Tests' }) vim.keymap.set({'v'}, 'mcd', 'CodeCompanion Debug Analysis', { desc = 'Debug Analysis' }) @@ -14,20 +13,45 @@ vim.keymap.set({'v'}, 'mcd', 'CodeCompanion Debug Analysis', { -- build = "uv tool upgrade vectorcode", -- This helps keeping the CLI up-to-date vim.api.nvim_create_autocmd('PackChanged', { callback = function() - vim.system({ "uv", "tool", "upgrade", "vectorcode" }, {}):wait() + vim.fn.jobstart({ "uv", "tool", "upgrade", "vectorcode" }, { + on_exit = function(_, exit_code, _) + if exit_code == 0 then + vim.notify("vectorcode upgraded", vim.log.levels.INFO, { title = "CodeCompanion" }) + else + vim.notify("vectorcode upgrade failed (exit " .. exit_code .. ")", vim.log.levels.WARN, { title = "CodeCompanion" }) + end + end, + }) end }) local function get_abacus_key() - local handle = io.popen("pass show abacus.ai-api") - if not handle then return "" end - local result = handle:read("*a") - handle:close() - -- Remove trailing newline that 'pass' often adds - return result:gsub("%s+", "") + local ok, res = pcall(vim.fn.systemlist, "pass show abacus.ai-api") + if not ok or not res or vim.tbl_isempty(res) then + return "" + end + -- systemlist returns lines; join and trim whitespace + local key = table.concat(res, "\n") + key = key:gsub("^%s+", ""):gsub("%s+$", "") + return key end -local codecompanion = require("codecompanion") +local function copilot_supports_sampling(self) + local model = self.schema.model.default + if type(model) == "function" then + model = model(self) + end + + model = type(model) == "string" and model:lower() or "" + return not model:find("gpt%-5", 1, false) and not model:find("codex", 1, false) +end + + +local ok, codecompanion = pcall(require, "codecompanion") +if not ok or not codecompanion then + vim.notify("codecompanion not available", vim.log.levels.ERROR) + return +end codecompanion.setup({ adapters = { http = { @@ -163,13 +187,14 @@ codecompanion.setup({ }) end, ollama = function() + local ollama_url = os.getenv("OLLAMA_URL") or "http://localhost:11434" return require("codecompanion.adapters").extend("ollama", { env = { - url = "http://129.100.33.66:11434", + url = ollama_url, }, schema = { model = { - default = "qwen3.5", -- change to whatever you pulled + default = "qwen3.5", }, }, }) @@ -180,6 +205,17 @@ codecompanion.setup({ model = { default = "gpt-5-mini", -- Consistent model choice }, + -- CodeCompanion only skips schema fields when `enabled` is a + -- function that returns false. + temperature = { + enabled = copilot_supports_sampling, + }, + top_p = { + enabled = copilot_supports_sampling, + }, + n = { + enabled = copilot_supports_sampling, + }, max_tokens = { default = 16284, } @@ -254,7 +290,7 @@ codecompanion.setup({ agentskills = { opts = { paths = { - { "~/.agents/skills", recursive = true }, + { vim.fn.expand("~/.agents/skills"), recursive = true }, }, }, }, @@ -325,26 +361,15 @@ codecompanion.setup({ local max_length = options.max_length or 200000 -- 200KB default local timeout = options.timeout or 60 - -- Use curl for better control - local cmd = string.format( - 'curl -L -s --max-time %d --user-agent "CodeCompanion-Neovim" "%s"', - timeout, - url - ) + local res = vim.system({ + "curl", "-L", "-s", "--max-time", tostring(timeout), "--user-agent", "CodeCompanion-Neovim", url + }, { timeout = (timeout + 5) * 1000 }):wait() - local handle = io.popen(cmd) - if not handle then - return nil, "Failed to execute curl" + if not res or res.code ~= 0 then + return nil, "Failed to fetch URL: " .. tostring(res and res.code or "unknown") end - local result = handle:read("*a") - local success = handle:close() - - if not success then - return nil, "Curl command failed" - end - - -- Truncate if too long + local result = res.output or "" if #result > max_length then result = result:sub(1, max_length) .. "\n[... truncated at " .. max_length .. " characters ...]" end @@ -551,7 +576,7 @@ codecompanion.setup({ modes = { "v" }, adapter = { name = "copilot", - model = "chatgpt-5.1-codex", + model = "chatgpt-5.3-codex", }, }, prompts = { @@ -578,7 +603,7 @@ codecompanion.setup({ modes = { "v" }, adapter = { name = "copilot", - model = "chatgpt-5.2-codex", + model = "chatgpt-5.3-codex", }, }, prompts = { @@ -605,7 +630,7 @@ codecompanion.setup({ adapter = { name = "copilot", - model = "chatgpt-5.2-codex", + model = "chatgpt-5.3-codex", }, }, prompts = { @@ -650,7 +675,7 @@ codecompanion.setup({ adapter = { name = "copilot", - model = "chatgpt-5.2-codex", + model = "chatgpt-5.4", }, }, prompts = { @@ -661,8 +686,9 @@ codecompanion.setup({ { role = "user", content = function(context) + local code = require("codecompanion.helpers.actions").get_code(context.start_line, context.end_line) - return fmt( + return string.format( [[Please review the architecture and design of this code from buffer %d: ```%s