diff --git a/lua/CopilotChat/client.lua b/lua/CopilotChat/client.lua index abd41872..f2dba5b0 100644 --- a/lua/CopilotChat/client.lua +++ b/lua/CopilotChat/client.lua @@ -50,8 +50,9 @@ ---@field reasoning boolean? local log = require('plenary.log') -local tiktoken = require('CopilotChat.tiktoken') +local constants = require('CopilotChat.constants') local notify = require('CopilotChat.notify') +local tiktoken = require('CopilotChat.tiktoken') local utils = require('CopilotChat.utils') local class = utils.class @@ -124,7 +125,7 @@ local function generate_selection_message(selection) selection.start_line, selection.end_line ), - role = 'user', + role = constants.ROLE.USER, } end @@ -140,7 +141,7 @@ local function generate_resource_messages(resources) :map(function(resource) return { content = generate_resource_block(resource.data, resource.mimetype, resource.uri, resource.name, 1, nil), - role = 'user', + role = constants.ROLE.USER, } end) :totable() @@ -160,7 +161,7 @@ local function generate_ask_request(prompt, system_prompt, history, generated_me if not utils.empty(system_prompt) then table.insert(messages, { content = system_prompt, - role = 'system', + role = constants.ROLE.SYSTEM, }) end @@ -172,7 +173,7 @@ local function generate_ask_request(prompt, system_prompt, history, generated_me if not utils.empty(prompt) and utils.empty(history) then table.insert(messages, { content = prompt, - role = 'user', + role = constants.ROLE.USER, }) end @@ -471,7 +472,7 @@ function Client:ask(prompt, opts) if opts.on_progress then opts.on_progress({ - role = 'assistant', + role = constants.ROLE.ASSISTANT, content = out.content or '', reasoning = out.reasoning or '', }) @@ -597,7 +598,7 @@ function Client:ask(prompt, opts) return { message = { - role = 'assistant', + role = constants.ROLE.ASSISTANT, content = response_text, reasoning = response_reasoning, tool_calls = #tool_calls:values() > 0 and tool_calls:values() or nil, diff --git a/lua/CopilotChat/completion.lua b/lua/CopilotChat/completion.lua index 9874999b..a32141eb 100644 --- a/lua/CopilotChat/completion.lua +++ b/lua/CopilotChat/completion.lua @@ -1,5 +1,6 @@ local async = require('plenary.async') local client = require('CopilotChat.client') +local constants = require('CopilotChat.constants') local config = require('CopilotChat.config') local functions = require('CopilotChat.functions') local utils = require('CopilotChat.utils') @@ -33,10 +34,10 @@ function M.items() local kind = '' local info = '' if prompt.prompt then - kind = 'user' + kind = constants.ROLE.USER info = prompt.prompt elseif prompt.system_prompt then - kind = 'system' + kind = constants.ROLE.SYSTEM info = prompt.system_prompt end @@ -88,7 +89,7 @@ function M.items() items[#items + 1] = { word = '@' .. name, abbr = name, - kind = 'tool', + kind = constants.ROLE.TOOL, info = tool.description, menu = tool.group or '', icase = 1, diff --git a/lua/CopilotChat/config/mappings.lua b/lua/CopilotChat/config/mappings.lua index 5f411473..4928a876 100644 --- a/lua/CopilotChat/config/mappings.lua +++ b/lua/CopilotChat/config/mappings.lua @@ -1,6 +1,7 @@ local async = require('plenary.async') local copilot = require('CopilotChat') local client = require('CopilotChat.client') +local constants = require('CopilotChat.constants') local utils = require('CopilotChat.utils') ---@class CopilotChat.config.mappings.Diff @@ -162,7 +163,7 @@ return { normal = '', insert = '', callback = function() - local message = copilot.chat:get_message('user', true) + local message = copilot.chat:get_message(constants.ROLE.USER, true) if not message then return end @@ -174,7 +175,7 @@ return { toggle_sticky = { normal = 'grr', callback = function() - local message = copilot.chat:get_message('user') + local message = copilot.chat:get_message(constants.ROLE.USER) local section = message and message.section if not section then return @@ -205,7 +206,7 @@ return { clear_stickies = { normal = 'grx', callback = function() - local message = copilot.chat:get_message('user') + local message = copilot.chat:get_message(constants.ROLE.USER) local section = message and message.section if not section then return @@ -234,7 +235,7 @@ return { normal = '', insert = '', callback = function(source) - local diff = get_diff(copilot.chat:get_block('assistant', true)) + local diff = get_diff(copilot.chat:get_block(constants.ROLE.ASSISTANT, true)) diff = prepare_diff_buffer(diff, source) if not diff then return @@ -249,7 +250,7 @@ return { jump_to_diff = { normal = 'gj', callback = function(source) - local diff = get_diff(copilot.chat:get_block('assistant', true)) + local diff = get_diff(copilot.chat:get_block(constants.ROLE.ASSISTANT, true)) diff = prepare_diff_buffer(diff, source) if not diff then return @@ -264,7 +265,7 @@ return { callback = function() local items = {} for i, message in ipairs(copilot.chat.messages) do - if message.section and message.role == 'assistant' then + if message.section and message.role == constants.ROLE.ASSISTANT then local prev_message = copilot.chat.messages[i - 1] local text = '' if prev_message then @@ -326,7 +327,7 @@ return { normal = 'gy', register = '"', -- Default register to use for yanking callback = function() - local block = copilot.chat:get_block('assistant', true) + local block = copilot.chat:get_block(constants.ROLE.ASSISTANT, true) if not block then return end @@ -339,7 +340,7 @@ return { normal = 'gd', full_diff = false, -- Show full diff instead of unified diff when showing diff window callback = function(source) - local diff = get_diff(copilot.chat:get_block('assistant', true)) + local diff = get_diff(copilot.chat:get_block(constants.ROLE.ASSISTANT, true)) diff = prepare_diff_buffer(diff, source) if not diff then return @@ -356,7 +357,7 @@ return { -- Apply all diffs from same file if #modified > 0 then -- Find all diffs from the same file in this section - local message = copilot.chat:get_message('assistant', true) + local message = copilot.chat:get_message(constants.ROLE.ASSISTANT, true) local section = message and message.section local same_file_diffs = {} if section then @@ -429,7 +430,7 @@ return { show_info = { normal = 'gc', callback = function(source) - local message = copilot.chat:get_message('user', true) + local message = copilot.chat:get_message(constants.ROLE.USER, true) if not message then return end diff --git a/lua/CopilotChat/config/providers.lua b/lua/CopilotChat/config/providers.lua index e08f5fdf..b2a03eea 100644 --- a/lua/CopilotChat/config/providers.lua +++ b/lua/CopilotChat/config/providers.lua @@ -1,3 +1,4 @@ +local constants = require('CopilotChat.constants') local notify = require('CopilotChat.notify') local utils = require('CopilotChat.utils') local plenary_utils = require('plenary.async.util') @@ -342,8 +343,8 @@ M.copilot = { } if is_o1 then - if input.role == 'system' then - output.role = 'user' + if input.role == constants.ROLE.SYSTEM then + output.role = constants.ROLE.USER end end diff --git a/lua/CopilotChat/constants.lua b/lua/CopilotChat/constants.lua new file mode 100644 index 00000000..7c6f7561 --- /dev/null +++ b/lua/CopilotChat/constants.lua @@ -0,0 +1,10 @@ +return { + PLUGIN_NAME = 'CopilotChat', + + ROLE = { + USER = 'user', + ASSISTANT = 'assistant', + SYSTEM = 'system', + TOOL = 'tool', + }, +} diff --git a/lua/CopilotChat/init.lua b/lua/CopilotChat/init.lua index c08667af..90a4209d 100644 --- a/lua/CopilotChat/init.lua +++ b/lua/CopilotChat/init.lua @@ -2,10 +2,10 @@ local async = require('plenary.async') local log = require('plenary.log') local functions = require('CopilotChat.functions') local client = require('CopilotChat.client') +local constants = require('CopilotChat.constants') local notify = require('CopilotChat.notify') local utils = require('CopilotChat.utils') -local PLUGIN_NAME = 'CopilotChat' local WORD = '([^%s:]+)' local WORD_NO_INPUT = '([^%s]+)' local WORD_WITH_INPUT_QUOTED = WORD .. ':`([^`]+)`' @@ -44,7 +44,7 @@ local state = { ---@param prompt string ---@param config CopilotChat.config.Shared local function insert_sticky(prompt, config) - local existing_prompt = M.chat:get_message('user') + local existing_prompt = M.chat:get_message(constants.ROLE.USER) local combined_prompt = (existing_prompt and existing_prompt.content or '') .. '\n' .. (prompt or '') local lines = vim.split(prompt or '', '\n') local stickies = utils.ordered_map() @@ -207,7 +207,7 @@ local function finish(start_of_chat) end local prompt_content = '' - local assistant_message = M.chat:get_message('assistant') + local assistant_message = M.chat:get_message(constants.ROLE.ASSISTANT) local tool_calls = assistant_message and assistant_message.tool_calls or {} if not utils.empty(state.sticky) then @@ -225,7 +225,7 @@ local function finish(start_of_chat) end M.chat:add_message({ - role = 'user', + role = constants.ROLE.USER, content = prompt_content, }) @@ -253,7 +253,7 @@ local function handle_error(config, cb) out = utils.make_string(out) M.chat:add_message({ - role = 'assistant', + role = constants.ROLE.ASSISTANT, content = '\n' .. string.format(BLOCK_OUTPUT_FORMAT, 'error', out) .. '\n', }) @@ -282,7 +282,7 @@ local function map_key(name, bufnr, fn) 'n', key.normal, fn, - { buffer = bufnr, nowait = true, desc = PLUGIN_NAME .. ' ' .. name:gsub('_', ' ') } + { buffer = bufnr, nowait = true, desc = constants.PLUGIN_NAME .. ' ' .. name:gsub('_', ' ') } ) end if key.insert and key.insert ~= '' then @@ -296,7 +296,7 @@ local function map_key(name, bufnr, fn) else fn() end - end, { buffer = bufnr, desc = PLUGIN_NAME .. ' ' .. name:gsub('_', ' ') }) + end, { buffer = bufnr, desc = constants.PLUGIN_NAME .. ' ' .. name:gsub('_', ' ') }) end end @@ -473,7 +473,7 @@ end ---@return CopilotChat.config.prompts.Prompt, string function M.resolve_prompt(prompt, config) if not prompt then - local message = M.chat:get_message('user') + local message = M.chat:get_message(constants.ROLE.USER) if message then prompt = message.content end @@ -636,12 +636,12 @@ function M.open(config) M.chat:open(config) -- Add sticky values from provided config when opening the chat - local message = M.chat:get_message('user') + local message = M.chat:get_message(constants.ROLE.USER) if message then local prompt = insert_sticky(message.content, config) if prompt then M.chat:add_message({ - role = 'user', + role = constants.ROLE.USER, content = '\n' .. prompt, }, true) end @@ -813,7 +813,7 @@ function M.ask(prompt, config) if not config.headless then utils.schedule_main() - local assistant_message = M.chat:get_message('assistant') + local assistant_message = M.chat:get_message(constants.ROLE.ASSISTANT) if assistant_message and assistant_message.tool_calls then local handled_ids = {} for _, tool in ipairs(resolved_tools) do @@ -834,11 +834,11 @@ function M.ask(prompt, config) if not utils.empty(resolved_tools) then -- If we are handling tools, replace user message with tool results - M.chat:remove_message('user') + M.chat:remove_message(constants.ROLE.USER) for _, tool in ipairs(resolved_tools) do M.chat:add_message({ id = tool.id, - role = 'tool', + role = constants.ROLE.TOOL, tool_call_id = tool.id, content = '\n' .. tool.result .. '\n', }) @@ -846,7 +846,7 @@ function M.ask(prompt, config) else -- Otherwise just replace the user message with resolved prompt M.chat:add_message({ - role = 'user', + role = constants.ROLE.USER, content = '\n' .. prompt .. '\n', }, true) end @@ -854,7 +854,7 @@ function M.ask(prompt, config) if utils.empty(prompt) and utils.empty(resolved_tools) then if not config.headless then - M.chat:remove_message('user') + M.chat:remove_message(constants.ROLE.USER) finish() end return @@ -1008,7 +1008,7 @@ function M.log_level(level) M.config.debug = level == 'debug' log.new({ - plugin = PLUGIN_NAME, + plugin = constants.PLUGIN_NAME, level = level, outfile = M.config.log_path, fmt_msg = function(is_console, mode_name, src_path, src_line, msg) @@ -1110,13 +1110,13 @@ function M.setup(config) nargs = '*', force = true, range = true, - desc = prompt.description or (PLUGIN_NAME .. ' ' .. name), + desc = prompt.description or (constants.PLUGIN_NAME .. ' ' .. name), }) if prompt.mapping then vim.keymap.set({ 'n', 'v' }, prompt.mapping, function() M.ask(prompt.prompt, prompt) - end, { desc = prompt.description or (PLUGIN_NAME .. ' ' .. name) }) + end, { desc = prompt.description or (constants.PLUGIN_NAME .. ' ' .. name) }) end end end diff --git a/lua/CopilotChat/ui/chat.lua b/lua/CopilotChat/ui/chat.lua index 4a549c6c..2e784d33 100644 --- a/lua/CopilotChat/ui/chat.lua +++ b/lua/CopilotChat/ui/chat.lua @@ -1,5 +1,6 @@ local Overlay = require('CopilotChat.ui.overlay') local Spinner = require('CopilotChat.ui.spinner') +local constants = require('CopilotChat.constants') local notify = require('CopilotChat.notify') local utils = require('CopilotChat.utils') local class = utils.class @@ -204,7 +205,7 @@ function Chat:add_sticky(sticky) return end - local prompt = self:get_message('user') + local prompt = self:get_message(constants.ROLE.USER) if not prompt or not prompt.section then return end @@ -667,7 +668,7 @@ function Chat:render() end -- Code blocks - if current_message and current_message.role == 'assistant' then + if current_message and current_message.role == constants.ROLE.ASSISTANT then local filetype, filename, start_line, end_line = match_header(line) if filetype and filename and not current_block then current_block = { @@ -767,7 +768,7 @@ function Chat:render() -- Show reasoning as virtual text above assistant messages if - message.role == 'assistant' + message.role == constants.ROLE.ASSISTANT and not utils.empty(message.reasoning) and message.section and message.section.start_line @@ -787,7 +788,7 @@ function Chat:render() -- Show help as before, using last user message local last_message = self.messages[#self.messages] - if last_message and last_message.role == 'user' then + if last_message and last_message.role == constants.ROLE.USER then local msg = self.config.show_help and self.help or '' if self.token_count and self.token_max_count then if msg ~= '' then