return { { "Davidyz/VectorCode", version = "*", build = "uv tool upgrade vectorcode", -- This helps keeping the CLI up-to-date -- build = "pipx upgrade vectorcode", -- If you used pipx to install the CLI dependencies = { "nvim-lua/plenary.nvim" }, }, { "olimorris/codecompanion.nvim", version = "^18.0.0", opts = {}, dependencies = { "nvim-lua/plenary.nvim", "franco-ruggeri/codecompanion-spinner.nvim", "ravitemer/codecompanion-history.nvim", "cairijun/codecompanion-agentskills.nvim", "ttgrules/cc-adapter-copilot-cli-acp", }, event = "VeryLazy", keys = { { "rct", "CodeCompanionChat Toggle", mode = {'n', 'v'}, { noremap = true, silent = true }, desc = "CC Toggle" }, { "rca", "CodeCompanionActions", mode = { 'n', 'v' }, { noremap = true, silent = true }, desc = "CC Action" }, { "rce", "CodeCompanion Explain", mode = { 'n' }, desc = "CC Explain" }, { "rcf", "CodeCompanion Fix code", mode = { 'n' }, desc = "CC fix" }, { "rcc", "CodeCompanionChat Add", mode = { 'v' }, { noremap = true, silent = true }, desc = "CC Add" }, { 'rcr', 'CodeCompanion Code Review', mode = { 'v' }, desc = 'Code Review' }, { 'rco', 'CodeCompanion Optimize Performance', mode = { 'v' }, desc = 'Optimize Code' }, { 'rce', 'CodeCompanion Explain Code', mode = { 'v' }, desc = 'Explain Code' }, { 'rcg', 'CodeCompanion Generate Tests', mode = { 'v' }, desc = 'Generate Tests' }, { 'rcd', 'CodeCompanion Debug Analysis', mode = { 'v' }, desc = 'Debug Analysis' }, }, config = function() 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+", "") end local codecompanion = require("codecompanion") codecompanion.setup({ adapters = { http = { opts = { show_presets = true, show_model_choices = true, }, -- openai = function() -- return require("codecompanion.adapters").extend("openai", { -- env = { api_key = "cmd:pass show api.openai.com" } -- }) -- end, openrouter = function() return require("codecompanion.adapters").extend("openai_compatible", { env = { url = "https://openrouter.ai/api", api_key = "OPENROUTER_API_KEY", chat_url = "/v1/chat/completions", }, schema = { model = { default = "anthropic/claude-3.7-sonnet", }, }, }) end, abacus = function() return require("codecompanion.adapters").extend("openai_compatible", { name = "abacus", formatted_name = "Abacus.AI", env = { url = "https://routellm.abacus.ai/v1", -- IMPORTANT: include /v1 in the base url api_key = get_abacus_key(), chat_url = "/chat/completions" }, headers = { ["Content-Type"] = "application/json", ["Authorization"] = "Bearer ${api_key}", }, 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, }, }, }) end, ollama = function() return require("codecompanion.adapters").extend("ollama", { env = { url = "http://129.100.33.66:11434", }, schema = { model = { default = "qwen3.5", -- change to whatever you pulled }, }, }) end, copilot = function() return require("codecompanion.adapters").extend("copilot", { schema = { model = { default = "gpt-5-mini", -- Consistent model choice }, max_tokens = { default = 16284, } } }) end, }, acp = { opts = { show_presets = true, }, copilot_cli = function() return require("codecompanion.adapters").extend("copilot_cli", {}) end, codex = function() return require("codecompanion.adapters").extend("codex", { commands = { default = { "codex-acp" }, }, schema = { model = { default = "github-copilot/gpt-5.2-codex", }, }, defaults = { timeout = 20000, auth_method = "chatgpt", -- "openai-api-key"|"codex-api-key"|"chatgpt" }, }) end, opencode = function() return require("codecompanion.adapters").extend("codex", { commands = { default = { "opencode", "acp" }, }, schema = { model = { default = "github-copilot/gpt-5.2-codex", }, }, defaults = { timeout = 20000, auth_method = "chatgpt", -- "openai-api-key"|"codex-api-key"|"chatgpt" }, }) end, }, }, rules = { opts = { chat = { enabled = true, autoload = { "default" } }, }, }, opts = { send_code = true, log_level = "WARN", -- Change to DEBUG for troubleshooting language = "English", -- NEW: Performance improvements job_start_delay = 500, -- Reduced from default 1500ms submit_delay = 1000, -- Reduced from default 2000ms }, extensions = { spinner = {}, -- ddgr_search = { -- opts = { -- require_approval_before = false, -- }, -- }, agentskills = { opts = { { "~/Documents/ai-skills", recursive = true }, }, }, -- vectorcode = { lazy = true }, history = { lazy = true, enabled = true, opts = { keymap = "ghf", save_chat_keymap = "ghs", picker = "snacks", dir_to_save = vim.env.HOME .. "/Documents/ai-history", title_generation_opts = { adapter = "copilot", model = "gpt-5-mini", }, summary = { create_summary_keymap = "ghc", browse_summaries_keymap = "ghb", }, }, }, -- mcphub = { -- callback = "mcphub.extensions.codecompanion", -- opts = { -- make_vars = true, -- make_slash_commands = true, -- show_result_in_chat = true, -- }, -- }, }, interactions = { chat = { variables = { project = { callback = function() -- Get project files structure local files = vim.fn.systemlist("fd . -type f") return table.concat(files, "\n") end, description = "Share project structure" } }, tools = { opts = { auto_submit_errors = true, -- Send any errors to the LLM automatically? auto_submit_success = true, -- Send any successful output to the LLM automatically? system_prompt = { enabled = true, replace_main_system_prompt = false, }, default_tools = { "file_search", "read_file", "cmd_runner", -- "ddgr_search", }, }, ["fetch_enhanced"] = { callback = function(url, options) options = options or {} 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 handle = io.popen(cmd) if not handle then return nil, "Failed to execute curl" end local result = handle:read("*a") local success = handle:close() if not success then return nil, "Curl command failed" end -- Truncate if too long if #result > max_length then result = result:sub(1, max_length) .. "\n[... truncated at " .. max_length .. " characters ...]" end return result end, opts = { requires_approval = false, } }, ["fetch_unlimited"] = { description = "Fetch a data from the web", callback = function(url, options) options = options or {} -- Use a local proxy service or direct system calls local temp_file = vim.fn.tempname() local cmd = string.format( 'wget --timeout=60 --tries=3 --output-document="%s" "%s" 2>/dev/null && cat "%s" && rm "%s"', temp_file, url, temp_file, temp_file ) local handle = io.popen(cmd) if not handle then return nil, "Failed to fetch URL" end local result = handle:read("*a") handle:close() -- Optional: Process and clean the content -- Remove excessive whitespace, clean HTML if needed -- result = result:gsub("%s+", " "):gsub("^\s+", ""):gsub("%s+$", "") return result end, opts = { requires_approval = false, description = "Fetch web content with unlimited size" } }, ["fetch"] = { description = "Fetch a webpage in a markdown format", callback = function(url, options) local cmd = string.format( 'reader -o -i none %s 2>/dev/null', url ) local handle = io.popen(cmd) if not handle then return nil, "Failed to fetch URL" end local result = handle:read("*a") handle:close() return result end, }, -- ["mcp"] = { -- Name this tool whatever you like -- -- Callback provides the necessary functions to CodeCompanion -- callback = function() -- return require("mcphub.extensions.codecompanion") -- end, -- opts = { -- -- If true, CodeCompanion will ask for approval before executing the MCP tool call -- requires_approval = true, -- -- Optional: Pass parameters like temperature to the underlying LLM if the chat strategy supports it -- temperature = 0.7 -- } -- }, groups = { ['plan'] = { description = "Planning my project and codes with enhanced web access", prompt = "Using all the ${tools} at your disposal including enhanced web fetching. Analyze the codes and use it to help me with my query. You have access to unlimited web content fetching.", tools = { "fetch", -- Backup unlimited fetch "file_search", "grep_search", "list_code_usages", "next_edit_suggestion", "read_file", "cmd_runner", }, opts = { collapse_tools = true, -- Override default fetch behavior for this group tool_config = { fetch_enhanced = { max_length = 500000, -- 500KB for planning tasks chunk_processing = true, }, }, }, }, ['research'] = { description = "Deep research with unlimited web access", prompt = "You are a research assistant with unlimited web access. Using the ${tools} fetch and analyze large documents, research papers, and comprehensive web content.", tools = { "fetch", "fetch_enhanced", "file_search", "read_file", }, opts = { collapse_tools = false, }, }, -- NEW: Add development group for coding tasks ['dev'] = { description = "Full-stack development with all necessary tools", prompt = "You are an expert full-stack developer. Use ${tools} to understand, modify, and test code. Always gather context before making changes.", tools = { "file_search", "grep_search", "fetch", "list_code_usages", "read_file", "insert_edit_into_file", "cmd_runner", "next_edit_suggestion", }, opts = { collapse_tools = true, }, }, }, }, slash_commands = { ["buffer"] = { opts = { provider = "snacks" } }, -- snacks ["file"] = { opts = { provider = "snacks" } }, -- snackes ['git_files'] = { description = 'List git files', ---@param chat CodeCompanion.Chat callback = function(chat) local handle = io.popen 'git ls-files' if handle ~= nil then local result = handle:read '*a' handle:close() chat:add_reference({ content = result }, 'git', '') return vim.notify('Git files added to the chat.') else return vim.notify('No git files available', vim.log.levels.INFO, { title = 'CodeCompanion' }) end end, opts = { contains_code = false, }, }, -- NEW: Add helpful workspace command ["workspace"] = { description = "Add workspace context", callback = function(chat) local cwd = vim.fn.getcwd() local workspace_info = string.format("Working directory: %s", cwd) -- Get project type local files = vim.fn.glob(cwd .. "/*", false, true) for _, file in ipairs(files) do local basename = vim.fn.fnamemodify(file, ":t") if basename == "package.json" then workspace_info = workspace_info .. "\nProject type: Node.js/JavaScript" break elseif basename == "Cargo.toml" then workspace_info = workspace_info .. "\nProject type: Rust" break elseif basename == "go.mod" then workspace_info = workspace_info .. "\nProject type: Go" break end end chat:add_reference({ content = workspace_info }, 'workspace', '') return vim.notify('Workspace context added.') end, opts = { contains_code = false, }, }, }, -- adapter = { name = "abacus", model = "route-llm" }, -- adapter = { name = "opencode", model = "github-copilot/gpt-5.2-codex" }, adapter = { name = "copilot", model = "gpt-5-mini" }, }, inline = { -- adapter = { name = "abacus", model = "route-llm" }, adapter = { name = "copilot", model = "gpt-5.1-codex-mini" }, }, cmd = { adapter = { name = "copilot", model = "gpt-5-mini" }, }, background = { adapter = { name = "copilot", model = "gpt-5-mini" }, }, }, prompt_library = { markdown = { dirs = { vim.fn.getcwd() .. "/.prompts", "~/.agents/prompts", }, }, ["Code Review"] = { interaction = "chat", description = "Review the selected code for improvements", opts = { mapping = "rpc", modes = { "v" }, adapter = { name = "copilot", model = "chatgpt-5.1-codex", }, }, prompts = { { role = "system", content = "You are an expert code reviewer. Analyze the code for: 1) Logic errors 2) Performance issues 3) Security vulnerabilities 4) Best practices 5) Code clarity and maintainability. Provide specific, actionable feedback.", }, { role = "user", content = function(context) local code = require("codecompanion.helpers.actions").get_code(context.start_line, context.end_line) return "Please review this code:\n\n```" .. context.filetype .. "\n" .. code .. "\n```" end, }, }, cc_keywords = { "review", "critique", "smell", "security", "vulnerability", "best practice", "maintainab" }, cc_threshold = 2, }, ["Optimize Performance"] = { interaction = "chat", description = "Get performance optimization suggestions", opts = { mapping = "rpo", modes = { "v" }, adapter = { name = "copilot", model = "chatgpt-5.2-codex", }, }, prompts = { { role = "system", content = "You are a performance optimization expert. Focus on: 1) Time complexity improvements 2) Space efficiency 3) Algorithm optimization 4) Framework-specific optimizations 5) Caching strategies.", }, { role = "user", content = function(context) local code = require("codecompanion.helpers.actions").get_code(context.start_line, context.end_line) return "How can I optimize the performance of this code?\n\n```" .. context.filetype .. "\n" .. code .. "\n```" end, }, }, cc_keywords = { "optimize", "performance", "slow", "latency", "throughput", "memory", "alloc" }, }, ["Debug Analysis"] = { interaction = "chat", description = "Analyze and debug problematic code", opts = { mapping = "rpd", modes = { "v" }, adapter = { name = "copilot", model = "chatgpt-5.2-codex", }, }, prompts = { { role = "system", content = [[You are a debugging expert. Analyze code for: 1. Potential bugs and issues 2. Logic errors 3. Runtime errors 4. Common pitfalls 5. Debugging strategies. 6. Provide specific solutions.]], }, { role = "user", content = function(context) local code = require("codecompanion.helpers.actions").get_code(context.start_line, context.end_line) return fmt( [[Help me debug this code from buffer %d and identify potential issues: ```%s %s ```]], context.bufnr, context.filetype, code ) end, opts = { contains_code = true, } }, }, cc_keyword = { "bug", "debug", "error", "exception", "crash", "stacktrace", "broken", "issue" }, }, ["Architecture Review"] = { interaction = "chat", description = "Review architectural patterns and design", opts = { mapping = "rpa", modes = { "v" }, adapter = { name = "copilot", model = "chatgpt-5.2-codex", }, }, prompts = { { role = "system", content = "You are a software architect. Review code for: 1) Design patterns usage 2) SOLID principles 3) Separation of concerns 4) Scalability considerations 5) Maintainability. Suggest architectural improvements.", }, { role = "user", content = function(context) local code = require("codecompanion.helpers.actions").get_code(context.start_line, context.end_line) return fmt( [[Please review the architecture and design of this code from buffer %d: ```%s %s ```]], context.bufnr, context.filetype, code ) end, opts = { contains_code = true, } }, }, cc_keywords = { "architecture", "design", "pattern", "solid", "scalab", "maintainab", "refactor" }, }, }, display = { action_palette = { provider = "snacks", opts = { show_default_actions = true, show_default_prompt_library = true, } }, chat = { show_settings = false, render_headers = false, icons = { chat_context = "📎️", }, fold_context = true, -- NEW: Better chat window configuration window = { layout = "vertical", width = 0.45, height = 0.8, border = "rounded", -- Better visual }, auto_scroll = false, start_in_insert_mode = false, -- More convenient } } }) end }, { "carlos-algms/agentic.nvim", opts = { -- Available by default: "claude-agent-acp" | "gemini-acp" | "codex-acp" | "opencode-acp" | "cursor-acp" | "auggie-acp" | "mistral-vibe-acp" provider = "opencode-acp", -- setting the name here is all you need to get started keymaps = { -- Keybindings for ALL buffers in the widget (chat, prompt, code, files) widget = { close = "q", -- String for a single keybinding change_mode = { { "", mode = { "i", "n", "v" }, -- Specify modes for this keybinding }, }, switch_provider = "ras", -- Switch ACP provider switch_model = "ram", -- Switch model }, -- Keybindings for the prompt buffer only prompt = { submit = { "", -- Normal mode, just Enter { "", mode = { "n", "v", "i" }, }, }, paste_image = { { "p", mode = { "n" }, }, { "", -- Same as Claude-code in insert mode mode = { "i" }, } }, }, -- Keybindings for diff preview navigation diff_preview = { next_hunk = "]c", prev_hunk = "[c", }, }, }, -- these are just suggested keymaps; customize as desired keys = { { "rat", function() require("agentic").toggle() end, mode = { "n", "v", "i" }, desc = "Toggle Agentic Chat" }, { "", function() require("agentic").add_selection_or_file_to_context() end, mode = { "n", "v" }, desc = "Add file or selection to Agentic to Context" }, { "ran", function() require("agentic").new_session() end, mode = { "n", "v", "i" }, desc = "New Agentic Session" }, { "r", -- ai Restore function() require("agentic").restore_session() end, desc = "Agentic Restore session", silent = true, mode = { "n", "v", "i" }, }, { "rad", -- ai Diagnostics function() require("agentic").add_current_line_diagnostics() end, desc = "Add current line diagnostic to Agentic", mode = { "n" }, }, { "raD", -- ai all Diagnostics function() require("agentic").add_buffer_diagnostics() end, desc = "Add all buffer diagnostics to Agentic", mode = { "n" }, }, }, }, { "zbirenbaum/copilot.lua", dependencies = { "copilotlsp-nvim/copilot-lsp", config = function() vim.g.copilot_nes_debounce = 500 end, }, cmd = "Copilot", event = "InsertEnter", config = function() require('copilot').setup({ nes = { enabled = false, keymap = { accept_and_goto = "", accept = false, dismiss = "", }, }, panel = { enabled = false, }, }) end, }, { "PhantomYdn/fabric-ai.nvim", cmd = { "Fabric" }, opts = { -- Default configuration (all optional) fabric_path = "fabric-ai", -- Path to Fabric CLI patterns_path = nil, -- Custom patterns dir (auto-detect if nil) timeout = 300000, -- Command timeout in ms (5 minutes) window = { width = 0.8, -- 80% of editor width height = 0.8, -- 80% of editor height border = "rounded", }, }, keys = { -- fabric-ai.nvim doesn't have default keymappings { "fa", ":'<,'>Fabric", mode = "v", desc = "Fabric AI" }, { "fa", ":Fabric", mode = "n", desc = "Fabric AI" }, { "fu", ":Fabric url", mode = "n", desc = "Fabric URL" }, }, }, }