diff --git a/lua/keymap.lua b/lua/keymap.lua index b9c66c8..2bec8f4 100644 --- a/lua/keymap.lua +++ b/lua/keymap.lua @@ -123,24 +123,23 @@ vim.api.nvim_create_autocmd('BufEnter', { end, }) - -- AI mappings vim.keymap.set('v', 'ae', 'CodeCompanion', { desc = 'Edit selection with AI' }) vim.keymap.set('n', 'ac', 'CodeCompanionCmd', { desc = 'Run Neovim commands with AI' }) vim.api.nvim_create_autocmd('FileType', { pattern = 'codecompanion', callback = function() - vim.keymap.set('i', '', function () + vim.keymap.set('i', '', function() require('codecompanion').last_chat():submit() - end, { buffer = true, desc = 'Use shift enter to start a new line' }) + end, { buffer = true, desc = 'Use enter to send the message' }) vim.keymap.set('i', '', '', { buffer = true, desc = 'Use shift enter to start a new line' }) vim.keymap.set('n', '', 'G', { buffer = true, desc = 'Use enter in normal mode to go to the end of the chat' }) - local models = { 'gpt-4o', 'gemini-2.5-pro', 'gemini-2.0-flash', 'claude-3.7-sonnet-thinking', 'o3-mini' } + local models = { 'gpt-4.1', 'gemini-2.5-pro', 'gemini-2.0-flash-001', 'claude-3.7-sonnet-thought', 'o3-mini' } -- Loop through models and create keymaps for each for i, model in ipairs(models) do - vim.keymap.set('n', '', 'mzggj0WC' .. model .. '`z', { desc = 'Switch to ' .. model }) - vim.keymap.set('i', '', 'mzggj0WC' .. model .. '`za', { desc = 'Switch to ' .. model }) + vim.keymap.set('n', '', 'mzggj0WC' .. model .. '`z', { buffer = true, desc = 'Switch to ' .. model }) + vim.keymap.set('i', '', 'mzggj0WC' .. model .. '`za', { buffer = true, desc = 'Switch to ' .. model }) end end, }) diff --git a/lua/plugins/codecompanion.lua b/lua/plugins/codecompanion.lua index c621425..1498330 100644 --- a/lua/plugins/codecompanion.lua +++ b/lua/plugins/codecompanion.lua @@ -10,7 +10,7 @@ return { return require('codecompanion.adapters').extend('copilot', { schema = { model = { - default = 'gpt-4o', + default = 'gpt-4.1', }, max_tokens = { default = 1000000, @@ -59,6 +59,7 @@ return { opts.display = { chat = { show_settings = true, + start_in_insert_mode = true, }, } @@ -73,16 +74,190 @@ return { description = 'Run VectorCode to retrieve the project context.', callback = require('vectorcode.integrations').codecompanion.chat.make_tool(), }, + ['cmd_runner'] = { + opts = { + requires_approval = false, + }, + }, + }, + roles = { + ---@type string|fun(adapter: CodeCompanion.Adapter): string + llm = function(adapter) + return 'CodeCompanion (' .. adapter.formatted_name .. ': ' .. adapter.parameters.model .. ')' + end, + }, + keymaps = { + send = { + modes = { n = '', i = '' }, + }, + close = { + modes = { n = '', i = '' }, + }, }, }, inline = { adapter = 'flash', }, } + + opts.extensions = { + mcphub = { + callback = 'mcphub.extensions.codecompanion', + opts = { + show_result_in_chat = true, + make_vars = true, + make_slash_commands = true, + }, + }, + } + + opts.system_prompt = function(opts) + local language = opts.language or 'English' + return string.format( + [[You are an AI programming assistant named "CodeCompanion". You are currently plugged into the Neovim text editor on a user's machine. + +Your core tasks include: +- Answering general programming questions. +- Explaining how the code in a Neovim buffer works. +- Reviewing the selected code from a Neovim buffer. +- Generating unit tests for the selected code. +- Proposing fixes for problems in the selected code. +- Scaffolding code for a new workspace. +- Finding relevant code to the user's query. +- Proposing fixes for test failures. +- Answering questions about Neovim. +- Running tools. + +You must: +- Follow the user's requirements carefully and to the letter. +- Keep your answers short and impersonal, especially if the user's context is outside your core tasks. +- Minimize additional prose unless clarification is needed. +- Use Markdown formatting in your answers. +- Include the programming language name at the start of each Markdown code block. +- Avoid including line numbers in code blocks. +- Avoid wrapping the whole response in triple backticks. +- Only return code that's directly relevant to the task at hand. You may omit code that isn’t necessary for the solution. +- Avoid using H1, H2 or H3 headers in your responses as these are reserved for the user. +- Use actual line breaks in your responses; only use "\n" when you want a literal backslash followed by 'n'. +- All non-code text responses must be written in the %s language indicated. +- Multiple, different tools can be called as part of the same response. + +When given a task: +1. Think step-by-step and, unless the user requests otherwise or the task is very simple, describe your plan in detailed pseudocode. +2. Output the final code in a single code block, ensuring that only relevant code is included. +3. End your response with a short suggestion for the next user turn that directly supports continuing the conversation. +4. Provide exactly one complete reply per conversation turn. +5. If necessary, execute multiple tools in a single turn.]], + language + ) + end + + opts.prompt_library = { + ['Code Expert'] = { + strategy = 'chat', + description = 'Get some special adcvice from an LLM.', + opts = { + mapping = 'ce', + modes = { 'v' }, + short_name = 'expert', + auto_submit = true, + stop_context_insertion = true, + user_prompt = true, + }, + prompts = { + { + role = 'system', + content = function(context) + return 'I want you to act as a senior' + .. context.filetype + .. 'developer I will ask you specific questions and I want you to return concise explanations and codeblock examples.' + end, + }, + { + role = 'user', + content = function(context) + local text = require('codecompanion.helpers.actions').get_code(context.start_line, context.end_line) + + return 'I have the following code:\n\n```' .. context.filetype .. '\n' .. text .. '\n```\n\n' + end, + opts = { + contains_code = true, + }, + }, + }, + }, + ['Games Master'] = { + strategy = 'chat', + description = 'A personal Games Master Assistant.', + opts = { + mapping = 'cd', + modes = { 'n' }, + short_name = 'gm', + auto_submit = false, + stop_context_insertion = false, + user_prompt = false, + is_default = true, + adapter + { + temperature = 1, + }, + }, + prompts = { + { + role = 'system', + content = function(context) + return [[ +You are a personal Games Master Assistant. You are currently plugged in to the Neovim text editor on a user's machine. + +Your core tasks include: +- Crafting engaging role playing sessions +- Building immersive and authentic worlds +- Creating compelling characters for the players to interact with and drive the story +- Reviewing session summaries and building on them +- Providing advice on how to bring sessions to life +- Create exciting encounters to challenge the players + - Encounters can be combat, social, or exploration based + - There should always be a story reason for the encounter +- Combine player character backgrounds and motivations into the world +- Build tension and drama into the game +- Ensure each session provides opportunities for the players to engage with and drive the story + +You must: +- Follow the user's requirements carefully and to the letter. +- Keep answers focused on the task at hand. +- Provide original ideas and suggestions. +- Use Markdown formatting in your answers. +- Use actual line breaks instead of '\n' in your response to begin new lines. +- Use '\n' only when you want a literal backslash followed by a character 'n'. +- All responses must be written in English. +- Multiple, different tools can be called as part of the same response. +- Help sessions be fast paced and fun. +- Ensure there are multiple soltuions to each problem. +- Avoid railroading the players. + +When given a task: +1. Consider the existing world and characters. Use tools to gather information that may be relevant. +2. Provide exactly one complete reply per conversation turn. +3. If necessary, execute multiple tools in a single turn. +]] + end, + }, + { + role = 'user', + content = function(context) + return '' + end, + opts = { + contains_code = false, + }, + }, + }, + }, + } end, dependencies = { 'nvim-lua/plenary.nvim', 'nvim-treesitter/nvim-treesitter', 'Davidyz/VectorCode', + 'ravitemer/mcphub.nvim', }, } diff --git a/lua/plugins/mcp.lua b/lua/plugins/mcp.lua new file mode 100644 index 0000000..7a52c75 --- /dev/null +++ b/lua/plugins/mcp.lua @@ -0,0 +1,16 @@ +return { + 'ravitemer/mcphub.nvim', + dependencies = { + 'nvim-lua/plenary.nvim', -- Required for Job and HTTP requests + }, + -- uncomment the following line to load hub lazily + cmd = 'MCPHub', -- lazy load + build = 'npm install -g mcp-hub@latest', -- Installs required mcp-hub npm module + -- uncomment this if you don't want mcp-hub to be available globally or can't use -g + -- build = "bundled_build.lua", -- Use this and set use_bundled_binary = true in opts (see Advanced configuration) + config = function() + require('mcphub').setup({ + auto_approve = true, + }) + end, +} diff --git a/lua/plugins/telescope.lua b/lua/plugins/telescope.lua index de1834b..c5adb34 100644 --- a/lua/plugins/telescope.lua +++ b/lua/plugins/telescope.lua @@ -73,6 +73,9 @@ return { [''] = 'move_selection_previous', }, }, + file_ignore_patterns = { + '.obsidian', + }, }, }