From 70d2eb2e65cfa22917190b156b3b2366b62dfd78 Mon Sep 17 00:00:00 2001 From: Steve Beaulac Date: Sat, 6 Jun 2026 17:09:17 -0400 Subject: [PATCH] fix: removing dependency on copilot too expensive --- config/foot/foot.ini | 4 +- config/hypr/hyprland.lua | 95 ++++++----- config/nvim/init.lua | 3 +- config/nvim/plugin/blink.lua | 13 +- config/nvim/plugin/codecompanion.lua | 244 ++++++++++++++------------- config/nvim/plugin/copilot.lua | 26 +-- 6 files changed, 206 insertions(+), 179 deletions(-) diff --git a/config/foot/foot.ini b/config/foot/foot.ini index 3bc9367..3bd1f40 100644 --- a/config/foot/foot.ini +++ b/config/foot/foot.ini @@ -1,10 +1,10 @@ [main] -include=~/.local/share/themes/current/theme/foot.ini -font=TX\-02:size=13 +font=MonaspiceNeNerdFontMono:size=13 term=xterm-256color pad=6x6 initial-window-mode=windowed workers=0 +include=~/.local/share/themes/current/theme/foot.ini [scrollback] lines=10000 diff --git a/config/hypr/hyprland.lua b/config/hypr/hyprland.lua index f2c7bba..d50ba46 100644 --- a/config/hypr/hyprland.lua +++ b/config/hypr/hyprland.lua @@ -193,36 +193,40 @@ function sysinfo() hl.notification.create({ text = mesg, icon = "hint", duration = 5000 }) end -function focus_or_launch(opts) +function dispatch_focus_or_launch(opts) return function() - local match = opts.match - local cmd = opts.cmd - local field = opts.field or "class" -- class, title, initialClass, initialTitle - local use_workspace = opts.use_workspace ~= false - - local clients = hl.get_windows() - - for _, client in ipairs(clients) do - local value = client[field] - if value and string.find(string.lower(value), string.lower(match), 1, true) then - if use_workspace and client.workspace and client.workspace.id then - hl.dispatch(hl.dsp.focus({ - workspace = client.workspace.id, - on_current_monitor = true, - })) - end - - hl.dispatch(hl.dsp.focus({ - window = "address:" .. client.address - })) - return - end - end - - hl.exec_cmd(cmd) + focus_or_launch(opts) end end +function focus_or_launch(opts) + local match = opts.match + local cmd = opts.cmd + local field = opts.field or "class" -- class, title, initialClass, initialTitle + local use_workspace = opts.use_workspace ~= false + + local clients = hl.get_windows() + + for _, client in ipairs(clients) do + local value = client[field] + if value and string.find(string.lower(value), string.lower(match), 1, true) then + if use_workspace and client.workspace and client.workspace.id then + hl.dispatch(hl.dsp.focus({ + workspace = client.workspace.id, + on_current_monitor = true, + })) + end + + hl.dispatch(hl.dsp.focus({ + window = "address:" .. client.address + })) + return + end + end + + hl.exec_cmd(cmd) +end + function toggle_master() local ws = hl.get_active_workspace() if not ws then @@ -247,14 +251,25 @@ function toggle_master() hl.dispatch(hl.dsp.layout("mfact exact " .. mfact)) end -hl.bind(LEADER .. "return", +hl.bind(LEADER .. "return", function() focus_or_launch({ match = terminal, field = "class", cmd = terminal .. " tmux new -A -s main" - }), { description = "Open terminal" }) + }) +end, { description = "Open terminal" }) + +--hl.bind(LEADER .. "SHIFT + return", hl.dsp.exec_raw(terminal .. "tmux attach-session -t $(tmux list-windows -a -F '#S:#I' | rofi -dmenu -P Session)")) +hl.bind(LEADER .. "SHIFT + return", function() + local session = io.popen("tmux list-sessions -F '#S:#I' | rofi -dmenu -P Session"):read("*a") + hl.notification.create({ text = "Attaching to tmux session: " .. session, icon = "hint", duration = 2000 }) + focus_or_launch({ + match = "session", + field = "title", + cmd = terminal .. " -e tmux attach-session -t " .. session + }) +end, { description = "Attach to tmux session" }) -hl.bind(LEADER .. "SHIFT + return", hl.dsp.exec_raw(terminal .. " nvim")) hl.bind(LEADER .. "B", hl.dsp.exec_raw(browser), { description = "Open browser" }) hl.bind(LEADER .. "T", hl.dsp.exec_raw(terminal .. " -e btop"), { description = "Open system monitor" }) hl.bind(LEADER .. "S", hl.dsp.exec_raw("rofi -show recursivebrowser"), { description = "Open finder" }) @@ -278,58 +293,58 @@ hl.bind(HYPR .. "B", hl.dsp.exec_cmd("blueberry"), { description = "Bluetooth ma hl.bind(HYPR .. "semicolon", hl.dsp.exec_cmd("~/.local/bin/bing-wallpaper"), { description = "get new wallpaper" }) -hl.bind(HYPR .. "A", focus_or_launch({ +hl.bind(HYPR .. "A", dispatch_focus_or_launch({ match = "Goose", field = "class", cmd = "gtk-launch goose-desktop.desktop" }), { description = "Goose Desktop" }) -hl.bind(HYPR .. "C", focus_or_launch({ +hl.bind(HYPR .. "C", dispatch_focus_or_launch({ match = "chrome-chatgpt.com", cmd = "gtk-launch ChatGPT.desktop", }), { description = "ChatGPT" }) -hl.bind(HYPR .. "O", focus_or_launch({ +hl.bind(HYPR .. "O", dispatch_focus_or_launch({ match = "chrome-outlook.office.com", cmd = "gtk-launch Outlook.desktop", }), { description = "Email" }) -hl.bind(HYPR .. "T", focus_or_launch({ +hl.bind(HYPR .. "T", dispatch_focus_or_launch({ match = "chrome-teams.microsoft.com", cmd = "gtk-launch Team.desktop", }), { description = "UWO Team" }) -hl.bind(HYPR .. "Y", focus_or_launch({ +hl.bind(HYPR .. "Y", dispatch_focus_or_launch({ match = "chrome-youtube.com", cmd = "gtk-launch YouTube.desktop", }), { description = "YouTube" }) -hl.bind(HYPR .. "W", focus_or_launch({ +hl.bind(HYPR .. "W", dispatch_focus_or_launch({ match = "chrome-web.whatsapp.com", cmd = "gtk-launch WhatsApp.desktop", }), { description = "WhatsApp" }) -hl.bind(HYPR .. "G", focus_or_launch({ +hl.bind(HYPR .. "G", dispatch_focus_or_launch({ match = "chrome-www.gmail.com", cmd = webapp .. "https://www.gmail.com/", }), { description = "Google" }) -hl.bind(HYPR .. "D", focus_or_launch({ +hl.bind(HYPR .. "D", dispatch_focus_or_launch({ match = "chrome-discord.com", cmd = "gtk-launch Discord.desktop" }), { description = "Discord" }) -hl.bind(HYPR .. "M", focus_or_launch({ +hl.bind(HYPR .. "M", dispatch_focus_or_launch({ match = "chrome-messages.google.com", cmd = "gtk-launch \"Google Messages.desktop\"", }), { description = "Google Messages" }) -hl.bind(HYPR .. "S", focus_or_launch({ +hl.bind(HYPR .. "S", dispatch_focus_or_launch({ match = "Spotify", cmd = music, }), { description = "Music" }) -hl.bind(HYPR .. "F", focus_or_launch({ +hl.bind(HYPR .. "F", dispatch_focus_or_launch({ match = "pcmanfm", cmd = "pcmanfm", }), { description = "File Manager" }) diff --git a/config/nvim/init.lua b/config/nvim/init.lua index b4e6aa8..ef43ac1 100644 --- a/config/nvim/init.lua +++ b/config/nvim/init.lua @@ -141,7 +141,7 @@ vim.pack.add({ { src = 'https://github.com/carlos-algms/agentic.nvim' }, { src = 'https://github.com/chipsenkbeil/org-roam.nvim' }, { src = 'https://github.com/christoomey/vim-tmux-navigator' }, - { src = 'https://github.com/copilotlsp-nvim/copilot-lsp' }, +-- { src = 'https://github.com/copilotlsp-nvim/copilot-lsp' }, { src = 'https://github.com/esmuellert/codediff.nvim' }, { src = 'https://github.com/fang2hou/blink-copilot' }, { src = 'https://github.com/folke/flash.nvim' }, @@ -201,7 +201,6 @@ vim.pack.add({ { src = 'https://github.com/ten3roberts/window-picker.nvim' }, { src = 'https://github.com/thunder-coding/zincoxide' }, { src = 'https://github.com/ttgrules/cc-adapter-copilot-cli-acp' }, - { src = 'https://github.com/ttgrules/cc-adapter-copilot-cli-acp' }, { src = 'https://github.com/uhs-robert/sshfs.nvim' }, { src = 'https://github.com/utilyre/barbecue.nvim' }, { src = 'https://github.com/williamboman/mason-lspconfig.nvim' }, diff --git a/config/nvim/plugin/blink.lua b/config/nvim/plugin/blink.lua index 9583e5b..28b75a1 100644 --- a/config/nvim/plugin/blink.lua +++ b/config/nvim/plugin/blink.lua @@ -14,6 +14,10 @@ require('blink.cmp').setup({ -- -- example: 'foo_|_bar' will match 'foo_' for 'prefix' and 'foo__bar' for 'full' -- range = "full", -- }, + -- keymap = { + -- -- Change "" to "" if you prefer the arrow key + -- ["C-y"] = { "select_and_accept", "fallback" }, + -- }, menu = { draw = { treesitter = { 'lsp' } @@ -33,8 +37,11 @@ require('blink.cmp').setup({ -- border = "single", -- }, }, - ghost_text = { enabled = false }, + -- ghost_text = { enabled = true }, }, + -- completion = { + -- ghost_text = { enabled = true }, + -- }, cmdline = { enabled = true, }, @@ -44,11 +51,14 @@ require('blink.cmp').setup({ org = {'orgmode'} }, default = { 'orgmode', 'lsp', 'copilot', 'snippets', 'path', 'omni', 'buffer', 'codecompanion', 'markdown' }, + -- default = { 'orgmode', 'lsp', 'snippets', 'path', 'omni', 'buffer', 'codecompanion', 'markdown' }, providers = { codecompanion = { name = "CodeCompanion" , module = "codecompanion.providers.completion.blink", enabled = true, + score_offset = 100, + async = true, }, orgmode = { name = 'Orgmode', @@ -115,6 +125,7 @@ require('blink.cmp').setup({ -- Blink does not expose its default kind icons so you must copy them all (or set your custom ones) and add Copilot kind_icons = { Copilot = "", + CodeCompanion = "", Text = '󰉿', Method = '󰊕', Function = '󰊕', diff --git a/config/nvim/plugin/codecompanion.lua b/config/nvim/plugin/codecompanion.lua index 2542d65..ba28ff7 100644 --- a/config/nvim/plugin/codecompanion.lua +++ b/config/nvim/plugin/codecompanion.lua @@ -1,5 +1,4 @@ - 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', 'v'}, 'mce', 'CodeCompanion Explain', { desc = "CC Explain" }) @@ -37,6 +36,17 @@ local function get_abacus_key() return key end +local function get_opencode_key() + local ok, res = pcall(vim.fn.systemlist, "pass show opencode-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 function copilot_supports_sampling(self) local model = self.schema.model.default if type(model) == "function" then @@ -79,15 +89,14 @@ codecompanion.setup({ }, }) end, - abacus = function() + opencode_zen = function() return require("codecompanion.adapters").extend("openai_compatible", { - name = "abacus", - formatted_name = "Abacus.AI", + name = "opencode-zen", + formatted_name = "OpenCode Zen", env = { - url = "https://routellm.abacus.ai/v1", - -- IMPORTANT: include /v1 in the base url - api_key = get_abacus_key(), - chat_url = "/chat/completions" + url = "https://opencode.ai/zen", + api_key = get_opencode_key(), + chat_url = "/v1/chat/completions", }, headers = { ["Content-Type"] = "application/json", @@ -95,107 +104,98 @@ codecompanion.setup({ }, schema = { model = { - order = 1, - mapping = "parameters", - type = "enum", - desc = "The model to use for chat completions.", - default = "route-llm", - choices = { - -- Routing Model - ["route-llm"] = { opts = { desc = "Intelligent routing to best model" } }, - - -- OpenAI Models - ["gpt-5.2"] = { opts = { has_vision = true } }, - ["gpt-5.1"] = { opts = { has_vision = true } }, - ["gpt-5.1-chat-latest"] = { opts = { has_vision = true } }, - ["gpt-5"] = { opts = { has_vision = true } }, - ["gpt-5-mini"] = { opts = { has_vision = true } }, - ["gpt-5-nano"] = { opts = { has_vision = true } }, - ["gpt-4o"] = { opts = { has_vision = true } }, - ["gpt-4o-mini"] = { opts = { has_vision = true } }, - ["o4-mini"] = { opts = { can_reason = true } }, - ["o3"] = { opts = { can_reason = true } }, - ["o3-pro"] = { opts = { can_reason = true } }, - - -- Anthropic Models - ["claude-4-5-sonnet"] = { opts = { has_vision = true } }, - ["claude-4-5-haiku"] = { opts = { has_vision = true } }, - ["claude-4-5-opus"] = { opts = { has_vision = true } }, - ["claude-3-opus"] = { opts = { has_vision = true } }, - - -- Google Models - ["gemini-3-pro"] = { opts = { has_vision = true } }, - ["gemini-3-flash"] = { opts = { has_vision = true } }, - ["gemini-2.5-pro"] = { opts = { has_vision = true } }, - ["gemini-2.5-flash"] = { opts = { has_vision = true } }, - - -- xAI Models - ["grok-4-1-fast"] = {}, - ["grok-4"] = {}, - ["grok-code-fast-1"] = {}, - - -- Meta Models - ["llama-4-Maverick-17B"] = {}, - ["llama-3.1-405B"] = {}, - ["llama-3.1-70B"] = {}, - - -- DeepSeek Models - ["deepseek-v3.2"] = {}, - ["deepseek-v3.1-Terminus"] = {}, - ["deepseek-R1"] = { opts = { can_reason = true } }, - - -- Qwen Models - ["qwen-3-Max"] = {}, - ["qwen3-coder-480b-a35b-instruct"] = {}, - ["qwen-3-32B"] = {}, - ["qwq-32B"] = { opts = { can_reason = true } }, - }, - }, - temperature = { - order = 2, - mapping = "parameters", - type = "number", - optional = true, - default = 1.0, - desc = "Controls randomness of output (0-2).", - validate = function(n) - return n >= 0 and n <= 2, "Must be between 0 and 2" - end, - }, - max_tokens = { - order = 3, - mapping = "parameters", - type = "integer", - optional = true, - default = nil, - desc = "Maximum tokens to generate.", - validate = function(n) - return n > 0, "Must be greater than 0" - end, - }, - top_p = { - order = 4, - mapping = "parameters", - type = "number", - optional = true, - default = 1.0, - desc = "Nucleus sampling parameter (0-1).", - validate = function(n) - return n >= 0 and n <= 1, "Must be between 0 and 1" - end, + default = "deepseek-v4-flash-free", + -- choices = { + -- ["minimax-m3-free"] = { opts = { has_vision = true, can_reason = true } }, + -- ["big-pickle"] = { opts = { has_vision = true, can_reason = true } }, + -- ["mini-v2.5-free"] = { opts = { has_vision = true, can_reason = true } }, + -- ["nemotron-3-super-free"] = { opts = { has_vision = true, can_reason = true } }, + -- ["nemotron-3-ultra-free"] = { opts = { has_vision = true, can_reason = true } }, + -- ["deepseek-v4-flash-free"] = { opts = { has_vision = true, can_reason = true } }, + -- ["qwen-3.6-plus-free"] = { opts = { has_vision = true, can_reason = true } }, + -- }, }, }, }) end, - ollama = function() - local ollama_url = os.getenv("OLLAMA_URL") or "http://192.168.33.74:11434" + opencode_go_anthropic = function() + return require("codecompanion.adapters").extend("anthropic", { + name = "opencode-go-anthropic", + formatted_name = "OpenCode Go Anthropic", + env = { + url = "https://opencode.ai/zen/go", + api_key = get_opencode_key(), + }, + headers = { + ["x-api-key"] = "${api_key}", + ["anthropic-version"] = "2023-06-01", + ["content-type"] = "application/json", + }, + schema = { + model = { + default = "minimax-m3", + }, + }, + }) + end, + opencode_go = function() + return require("codecompanion.adapters").extend("openai_compatible", { + name = "opencode-go", + formatted_name = "OpenCode Go", + env = { + url = "https://opencode.ai/zen/go", + api_key = get_opencode_key(), + chat_url = "/v1/chat/completions", + }, + headers = { + ["Content-Type"] = "application/json", + ["Authorization"] = "Bearer ${api_key}", + }, + schema = { + model = { + default = "mimo-v2.5-pro", + -- choices = { + -- ["minimax-m3"] = { opts = { has_vision = true, can_reason = true } }, + -- ["minimax-m2.7"] = { opts = { has_vision = true, can_reason = true } }, + -- ["mini-v2.5-pro"] = { opts = { has_vision = true, can_reason = true } }, + -- ["mini-v2.5"] = { opts = { has_vision = true, can_reason = true } }, + -- ["mimo-v2.5-pro"] = { opts = { has_vision = true, can_reason = true } }, + -- ["mimo-v2.5"] = { opts = { has_vision = true, can_reason = true } }, + -- ["kimi-k2.6"] = { opts = { has_vision = true, can_reason = true } }, + -- ["kimi-k2.5"] = { opts = { has_vision = true, can_reason = true } }, + -- ["glm-5.1"] = { opts = { has_vision = true, can_reason = true } }, + -- ["deepseek-v4-flash"] = { opts = { has_vision = true, can_reason = true } }, + -- ["deepseek-v4-pro"] = { opts = { has_vision = true, can_reason = true } }, + -- ["qwen-3.7-plus"] = { opts = { has_vision = true, can_reason = true } }, + -- ["qwen-3.7-max"] = { opts = { has_vision = true, can_reason = true } }, + -- ["hy3-preview"] = { opts = { has_vision = true, can_reason = true } }, + -- }, + }, + }, + }) + end, + allears = function() + local ollama_url = os.getenv("ALLEARS_OLLAMA_URL") or "http://192.168.33.74:11434" return require("codecompanion.adapters").extend("ollama", { env = { url = ollama_url, }, schema = { model = { - default = "qwen3.5", + default = "qwen3.6", + }, + }, + }) + end, + sagacity = function() + local ollama_url = os.getenv("SAGACITY_OLLAMA_URL") or "http://172.25.11.30" + return require("codecompanion.adapters").extend("ollama", { + env = { + url = ollama_url, + }, + schema = { + model = { + default = "qwen3.6", }, }, }) @@ -265,6 +265,7 @@ codecompanion.setup({ -- end, }, }, + ghost_text = { enabled = false }, rules = { opts = { chat = { @@ -305,8 +306,8 @@ codecompanion.setup({ picker = "snacks", dir_to_save = vim.env.HOME .. "/Documents/ai-history", title_generation_opts = { - adapter = "copilot", - model = "gpt-5-mini", + adapter = "opencode_zen", + model = "big-pickle", }, summary = { create_summary_keymap = "ghc", @@ -556,18 +557,19 @@ codecompanion.setup({ }, -- adapter = { name = "abacus", model = "route-llm" }, -- adapter = { name = "opencode", model = "github-copilot/gpt-5.2-codex" }, - adapter = { name = "copilot", model = "gpt-5-mini" }, + -- adapter = { name = "copilot", model = "gpt-5-mini" }, -- adapter = { name = "goose" }, + adapter = { name = "opencode_go", model = "mimo-v2.5-pro" }, }, inline = { -- adapter = { name = "abacus", model = "route-llm" }, - adapter = { name = "copilot", model = "gpt-5.1-codex-mini" }, + adapter = { name = "opencode_zen", model = "deepseek-v4-flash-free" }, }, cmd = { - adapter = { name = "copilot", model = "gpt-5-mini" }, + adapter = { name = "opencode_zen", model = "mimo-v2.5-free" }, }, background = { - adapter = { name = "copilot", model = "gpt-5-mini" }, + adapter = { name = "opencode_zen", model = "mimo-v2.5-free" }, }, }, prompt_library = { @@ -583,10 +585,10 @@ codecompanion.setup({ opts = { mapping = "rpc", modes = { "v" }, - adapter = { - name = "copilot", - model = "chatgpt-5.3-codex", - }, + -- adapter = { + -- name = "copilot", + -- model = "chatgpt-5.3-codex", + -- }, }, prompts = { { @@ -610,10 +612,10 @@ codecompanion.setup({ opts = { mapping = "rpo", modes = { "v" }, - adapter = { - name = "copilot", - model = "chatgpt-5.3-codex", - }, + -- adapter = { + -- name = "copilot", + -- model = "chatgpt-5.3-codex", + -- }, }, prompts = { { @@ -637,10 +639,10 @@ codecompanion.setup({ mapping = "rpd", modes = { "v" }, - adapter = { - name = "copilot", - model = "chatgpt-5.3-codex", - }, + -- adapter = { + -- name = "copilot", + -- model = "chatgpt-5.3-codex", + -- }, }, prompts = { { @@ -682,10 +684,10 @@ codecompanion.setup({ mapping = "rpa", modes = { "v" }, - adapter = { - name = "copilot", - model = "chatgpt-5.4", - }, + -- adapter = { + -- name = "copilot", + -- model = "chatgpt-5.4", + -- }, }, prompts = { { diff --git a/config/nvim/plugin/copilot.lua b/config/nvim/plugin/copilot.lua index 8b1ad31..ccb992d 100644 --- a/config/nvim/plugin/copilot.lua +++ b/config/nvim/plugin/copilot.lua @@ -1,16 +1,16 @@ vim.g.copilot_nes_debounce = 500 -require('copilot').setup({ - nes = { - enabled = false, - keymap = { - accept_and_goto = "", - accept = false, - dismiss = "", - }, - }, - panel = { - enabled = false, - }, -}) +-- require('copilot').setup({ +-- nes = { +-- enabled = false, +-- keymap = { +-- accept_and_goto = "", +-- accept = false, +-- dismiss = "", +-- }, +-- }, +-- panel = { +-- enabled = false, +-- }, +-- })