Skip to content

Commit

Permalink
feat: add support for Github Marketplace models
Browse files Browse the repository at this point in the history
Adds integration with Github Marketplace models available through Azure ML API.
The models are fetched from the Azure catalog and exposed through the same
interface as regular Copilot models. This provides users with access to
additional experimental models while maintaining consistent UX.

The docs are updated to point to official Copilot model documentation and
marketplace models page rather than listing models inline.

Signed-off-by: Tomas Slusny <[email protected]>
  • Loading branch information
deathbeam committed Feb 11, 2025
1 parent dbce8a2 commit d3e638a
Show file tree
Hide file tree
Showing 7 changed files with 453 additions and 374 deletions.
12 changes: 2 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,16 +239,8 @@ You can also set default sticky prompts in the configuration:

You can list available models with `:CopilotChatModels` command. Model determines the AI model used for the chat.
You can set the model in the prompt by using `$` followed by the model name or default model via config using `model` key.
Default models are:

- `gpt-4o` - This is the default Copilot Chat model. It is a versatile, multimodal model that excels in both text and image processing and is designed to provide fast, reliable responses. It also has superior performance in non-English languages.
- `claude-3.5-sonnet` - This model excels at coding tasks across the entire software development lifecycle, from initial design to bug fixes, maintenance to optimizations. Claude is **not available everywhere** so if you do not see it, try github codespaces or VPN.
- `gemini-2.0-flash-001` - This model has strong coding, math, and reasoning capabilities that makes it well suited to assist with software development.
- `o1` - This model is focused on advanced reasoning and solving complex problems, in particular in math and science. It responds more slowly than the GPT 4o model. You can make 10 requests to this model per day.
- `o3-mini` - This model is the next generation of reasoning models, following from o1 and o1-mini. The o3-mini model outperforms o1 on coding benchmarks with response times that are comparable to o1-mini, providing improved quality at nearly the same latency. It is best suited for code generation and small context operations. You can make 50 requests to this model every 12 hours.

For more information about models, see [here](https://docs.github.com/en/copilot/using-github-copilot/asking-github-copilot-questions-in-your-ide#ai-models-for-copilot-chat)
You can use more models from [here](https://github.com/marketplace/models) by using `@models` agent from [here](https://github.com/marketplace/models-github) (example: `@models Using Mistral-small, what is 1 + 11`)
For list of models supported by Copilot Chat see [here](https://docs.github.com/en/copilot/using-github-copilot/ai-models/changing-the-ai-model-for-copilot-chat#ai-models-for-copilot-chat).
This plugin also supports Github Marketplace Models. These have fairly low limits but are useful for experimentation. For more information see [here](https://github.com/marketplace/models).

## Agents

Expand Down
308 changes: 5 additions & 303 deletions lua/CopilotChat/config.lua
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
local prompts = require('CopilotChat.prompts')
local context = require('CopilotChat.context')
local prompts = require('CopilotChat.config.prompts')
local select = require('CopilotChat.select')
local utils = require('CopilotChat.utils')

---@class CopilotChat.config.context
---@field description string?
---@field input fun(callback: fun(input: string?), source: CopilotChat.source)?
---@field resolve fun(input: string?, source: CopilotChat.source):table<CopilotChat.context.embed>

---@class CopilotChat.config.prompt : CopilotChat.config.shared
---@field prompt string?
---@field description string?
---@field mapping string?

---@class CopilotChat.config.window
---@field layout string?
Expand All @@ -25,32 +13,6 @@ local utils = require('CopilotChat.utils')
---@field footer string?
---@field zindex number?

---@class CopilotChat.config.mapping
---@field normal string?
---@field insert string?
---@field detail string?

---@class CopilotChat.config.mapping.yank_diff : CopilotChat.config.mapping
---@field register string?

---@class CopilotChat.config.mapping.show_diff : CopilotChat.config.mapping
---@field full_diff boolean?

---@class CopilotChat.config.mappings
---@field complete CopilotChat.config.mapping?
---@field close CopilotChat.config.mapping?
---@field reset CopilotChat.config.mapping?
---@field submit_prompt CopilotChat.config.mapping?
---@field toggle_sticky CopilotChat.config.mapping?
---@field accept_diff CopilotChat.config.mapping?
---@field jump_to_diff CopilotChat.config.mapping?
---@field quickfix_diffs CopilotChat.config.mapping?
---@field yank_diff CopilotChat.config.mapping.yank_diff?
---@field show_diff CopilotChat.config.mapping.show_diff?
---@field show_info CopilotChat.config.mapping?
---@field show_context CopilotChat.config.mapping?
---@field show_help CopilotChat.config.mapping?

---@class CopilotChat.config.shared
---@field system_prompt string?
---@field model string?
Expand Down Expand Up @@ -90,7 +52,7 @@ return {

-- Shared config starts here (can be passed to functions at runtime and configured via setup function)

system_prompt = prompts.COPILOT_INSTRUCTIONS, -- System prompt to use (can be specified manually in prompt via /).
system_prompt = prompts.COPILOT_INSTRUCTIONS.system_prompt, -- System prompt to use (can be specified manually in prompt via /).

model = 'gpt-4o', -- Default model to use, see ':CopilotChatModels' for available models (can be specified manually in prompt via $).
agent = 'copilot', -- Default agent to use, see ':CopilotChatAgents' for available agents (can be specified manually in prompt via @).
Expand Down Expand Up @@ -146,271 +108,11 @@ return {
separator = '───', -- Separator to use in chat

-- default contexts
contexts = {
buffer = {
description = 'Includes specified buffer in chat context. Supports input (default current).',
input = function(callback)
vim.ui.select(
vim.tbl_map(
function(buf)
return { id = buf, name = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(buf), ':p:.') }
end,
vim.tbl_filter(function(buf)
return utils.buf_valid(buf) and vim.fn.buflisted(buf) == 1
end, vim.api.nvim_list_bufs())
),
{
prompt = 'Select a buffer> ',
format_item = function(item)
return item.name
end,
},
function(choice)
callback(choice and choice.id)
end
)
end,
resolve = function(input, source)
input = input and tonumber(input) or source.bufnr
return {
context.buffer(input),
}
end,
},
buffers = {
description = 'Includes all buffers in chat context. Supports input (default listed).',
input = function(callback)
vim.ui.select({ 'listed', 'visible' }, {
prompt = 'Select buffer scope> ',
}, callback)
end,
resolve = function(input)
input = input or 'listed'
return context.buffers(input)
end,
},
file = {
description = 'Includes content of provided file in chat context. Supports input.',
input = function(callback, source)
local cwd = utils.win_cwd(source.winnr)
local files = vim.tbl_filter(function(file)
return vim.fn.isdirectory(file) == 0
end, vim.fn.glob(cwd .. '/**/*', false, true))

vim.ui.select(files, {
prompt = 'Select a file> ',
}, callback)
end,
resolve = function(input)
return {
context.file(input),
}
end,
},
files = {
description = 'Includes all non-hidden files in the current workspace in chat context. Supports input (default list).',
input = function(callback)
local choices = utils.kv_list({
list = 'Only lists file names',
full = 'Includes file content for each file found. Can be slow on large workspaces, use with care.',
})

vim.ui.select(choices, {
prompt = 'Select files content> ',
format_item = function(choice)
return choice.key .. ' - ' .. choice.value
end,
}, function(choice)
callback(choice and choice.key)
end)
end,
resolve = function(input, source)
return context.files(source.winnr, input == 'full')
end,
},
git = {
description = 'Requires `git`. Includes current git diff in chat context. Supports input (default unstaged, also accepts commit number).',
input = function(callback)
vim.ui.select({ 'unstaged', 'staged' }, {
prompt = 'Select diff type> ',
}, callback)
end,
resolve = function(input, source)
input = input or 'unstaged'
return {
context.gitdiff(input, source.winnr),
}
end,
},
url = {
description = 'Includes content of provided URL in chat context. Supports input.',
input = function(callback)
vim.ui.input({
prompt = 'Enter URL> ',
default = 'https://',
}, callback)
end,
resolve = function(input)
return {
context.url(input),
}
end,
},
register = {
description = 'Includes contents of register in chat context. Supports input (default +, e.g clipboard).',
input = function(callback)
local choices = utils.kv_list({
['+'] = 'synchronized with the system clipboard',
['*'] = 'synchronized with the selection clipboard',
['"'] = 'last deleted, changed, or yanked content',
['0'] = 'last yank',
['-'] = 'deleted or changed content smaller than one line',
['.'] = 'last inserted text',
['%'] = 'name of the current file',
[':'] = 'most recent executed command',
['#'] = 'alternate buffer',
['='] = 'result of an expression',
['/'] = 'last search pattern',
})

vim.ui.select(choices, {
prompt = 'Select a register> ',
format_item = function(choice)
return choice.key .. ' - ' .. choice.value
end,
}, function(choice)
callback(choice and choice.key)
end)
end,
resolve = function(input)
input = input or '+'
return {
context.register(input),
}
end,
},
quickfix = {
description = 'Includes quickfix list file contents in chat context.',
resolve = function()
return context.quickfix()
end,
},
},
contexts = require('CopilotChat.config.contexts'),

-- default prompts
prompts = {
Explain = {
prompt = '> /COPILOT_EXPLAIN\n\nWrite an explanation for the selected code as paragraphs of text.',
},
Review = {
prompt = '> /COPILOT_REVIEW\n\nReview the selected code.',
callback = function(response, source)
local diagnostics = {}
for line in response:gmatch('[^\r\n]+') do
if line:find('^line=') then
local start_line = nil
local end_line = nil
local message = nil
local single_match, message_match = line:match('^line=(%d+): (.*)$')
if not single_match then
local start_match, end_match, m_message_match = line:match('^line=(%d+)-(%d+): (.*)$')
if start_match and end_match then
start_line = tonumber(start_match)
end_line = tonumber(end_match)
message = m_message_match
end
else
start_line = tonumber(single_match)
end_line = start_line
message = message_match
end

if start_line and end_line then
table.insert(diagnostics, {
lnum = start_line - 1,
end_lnum = end_line - 1,
col = 0,
message = message,
severity = vim.diagnostic.severity.WARN,
source = 'Copilot Review',
})
end
end
end
vim.diagnostic.set(
vim.api.nvim_create_namespace('copilot_diagnostics'),
source.bufnr,
diagnostics
)
end,
},
Fix = {
prompt = '> /COPILOT_GENERATE\n\nThere is a problem in this code. Rewrite the code to show it with the bug fixed.',
},
Optimize = {
prompt = '> /COPILOT_GENERATE\n\nOptimize the selected code to improve performance and readability.',
},
Docs = {
prompt = '> /COPILOT_GENERATE\n\nPlease add documentation comments to the selected code.',
},
Tests = {
prompt = '> /COPILOT_GENERATE\n\nPlease generate tests for my code.',
},
Commit = {
prompt = '> #git:staged\n\nWrite commit message for the change with commitizen convention. Make sure the title has maximum 50 characters and message is wrapped at 72 characters. Wrap the whole message in code block with language gitcommit.',
},
},
prompts = prompts,

-- default mappings
mappings = {
complete = {
insert = '<Tab>',
},
close = {
normal = 'q',
insert = '<C-c>',
},
reset = {
normal = '<C-l>',
insert = '<C-l>',
},
submit_prompt = {
normal = '<CR>',
insert = '<C-s>',
},
toggle_sticky = {
detail = 'Makes line under cursor sticky or deletes sticky line.',
normal = 'gr',
},
accept_diff = {
normal = '<C-y>',
insert = '<C-y>',
},
jump_to_diff = {
normal = 'gj',
},
quickfix_answers = {
normal = 'gqa',
},
quickfix_diffs = {
normal = 'gqd',
},
yank_diff = {
normal = 'gy',
register = '"', -- Default register to use for yanking
},
show_diff = {
normal = 'gd',
full_diff = false, -- Show full diff instead of unified diff when showing diff window
},
show_info = {
normal = 'gi',
},
show_context = {
normal = 'gc',
},
show_help = {
normal = 'gh',
},
},
mappings = require('CopilotChat.config.mappings'),
}
Loading

0 comments on commit d3e638a

Please sign in to comment.