Skip to content

Commit ad38132

Browse files
committed
chore: merge main
2 parents d8ba252 + b6cde06 commit ad38132

File tree

6 files changed

+132
-14
lines changed

6 files changed

+132
-14
lines changed

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ require("gp").setup(conf)
109109
```
110110
## 2. OpenAI API key
111111

112-
Make sure you have OpenAI API key. [Get one here](https://platform.openai.com/account/api-keys) and use it in the [4. Configuration](#4-configuration). Also consider setting up [usage limits](https://platform.openai.com/account/billing/limits) so you won't get suprised at the end of the month.
112+
Make sure you have OpenAI API key. [Get one here](https://platform.openai.com/account/api-keys) and use it in the [5. Configuration](#5-configuration). Also consider setting up [usage limits](https://platform.openai.com/account/billing/limits) so you won't get suprised at the end of the month.
113113

114114
The OpenAI API key can be passed to the plugin in multiple ways:
115115

@@ -149,7 +149,7 @@ Below is an example of the relevant configuration part enabling some of these. T
149149
secret = {
150150
"bash",
151151
"-c",
152-
"cat ~/.config/github-copilot/hosts.json | sed -e 's/.*oauth_token...//;s/\".*//'",
152+
"cat ~/.config/github-copilot/apps.json | sed -e 's/.*oauth_token...//;s/\".*//'",
153153
},
154154
},
155155

@@ -369,6 +369,10 @@ Displays currently used agents for chat and command instructions.
369369

370370
Choose a new agent based on its name, listing options based on the current buffer (chat agents if current buffer is a chat and command agents otherwise). The agent setting is persisted on disk across Neovim instances.
371371

372+
#### `:GpSelectAgent` <!-- {doc=:GpSelectAgent} -->
373+
374+
Opens a selection interface using `vim.ui.select` to choose from all available agents, allowing you to directly select the desired agent from a list. Works seamlessly with telescope if available.
375+
372376
## Image commands
373377

374378
#### `:GpImage` <!-- {doc=:GpImage} -->
@@ -530,6 +534,7 @@ vim.keymap.set("v", "<C-g>x", ":<C-u>'<,'>GpContext<cr>", keymapOptions("Visual
530534

531535
vim.keymap.set({"n", "i", "v", "x"}, "<C-g>s", "<cmd>GpStop<cr>", keymapOptions("Stop"))
532536
vim.keymap.set({"n", "i", "v", "x"}, "<C-g>n", "<cmd>GpNextAgent<cr>", keymapOptions("Next Agent"))
537+
vim.keymap.set({"n", "i", "v", "x"}, "<C-g>l", "<cmd>GpSelectAgent<cr>", keymapOptions("Select Agent"))
533538

534539
-- optional Whisper commands with prefix <C-g>w
535540
vim.keymap.set({"n", "i"}, "<C-g>ww", "<cmd>GpWhisper<cr>", keymapOptions("Whisper"))
@@ -582,6 +587,7 @@ require("which-key").add({
582587
{ "<C-g>gv", ":<C-u>'<,'>GpVnew<cr>", desc = "Visual GpVnew" },
583588
{ "<C-g>i", ":<C-u>'<,'>GpImplement<cr>", desc = "Implement selection" },
584589
{ "<C-g>n", "<cmd>GpNextAgent<cr>", desc = "Next Agent" },
590+
{ "<C-g>l", "<cmd>GpSelectAgent<cr>", desc = "Select Agent" },
585591
{ "<C-g>p", ":<C-u>'<,'>GpChatPaste<cr>", desc = "Visual Chat Paste" },
586592
{ "<C-g>r", ":<C-u>'<,'>GpRewrite<cr>", desc = "Visual Rewrite" },
587593
{ "<C-g>s", "<cmd>GpStop<cr>", desc = "GpStop" },
@@ -618,6 +624,7 @@ require("which-key").add({
618624
{ "<C-g>gt", "<cmd>GpTabnew<cr>", desc = "GpTabnew" },
619625
{ "<C-g>gv", "<cmd>GpVnew<cr>", desc = "GpVnew" },
620626
{ "<C-g>n", "<cmd>GpNextAgent<cr>", desc = "Next Agent" },
627+
{ "<C-g>l", "<cmd>GpSelectAgent<cr>", desc = "Select Agent" },
621628
{ "<C-g>r", "<cmd>GpRewrite<cr>", desc = "Inline Rewrite" },
622629
{ "<C-g>s", "<cmd>GpStop<cr>", desc = "GpStop" },
623630
{ "<C-g>t", "<cmd>GpChatToggle<cr>", desc = "Toggle Chat" },
@@ -653,6 +660,7 @@ require("which-key").add({
653660
{ "<C-g>gt", "<cmd>GpTabnew<cr>", desc = "GpTabnew" },
654661
{ "<C-g>gv", "<cmd>GpVnew<cr>", desc = "GpVnew" },
655662
{ "<C-g>n", "<cmd>GpNextAgent<cr>", desc = "Next Agent" },
663+
{ "<C-g>l", "<cmd>GpSelectAgent<cr>", desc = "Select Agent" },
656664
{ "<C-g>r", "<cmd>GpRewrite<cr>", desc = "Inline Rewrite" },
657665
{ "<C-g>s", "<cmd>GpStop<cr>", desc = "GpStop" },
658666
{ "<C-g>t", "<cmd>GpChatToggle<cr>", desc = "Toggle Chat" },

doc/gp.nvim.txt

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*gp.nvim.txt* For Neovim Last change: 2025 April 08
1+
*gp.nvim.txt* For Neovim Last change: 2025 August 08
22

33
==============================================================================
44
Table of Contents *gp.nvim-table-of-contents*
@@ -128,7 +128,7 @@ Snippets for your preferred package manager:
128128

129129
Make sure you have OpenAI API key. Get one here
130130
<https://platform.openai.com/account/api-keys> and use it in the
131-
|gp.nvim-4.-configuration|. Also consider setting up usage limits
131+
|gp.nvim-5.-configuration|. Also consider setting up usage limits
132132
<https://platform.openai.com/account/billing/limits> so you won’t get
133133
suprised at the end of the month.
134134

@@ -181,7 +181,7 @@ still supported for compatibility).
181181
secret = {
182182
"bash",
183183
"-c",
184-
"cat ~/.config/github-copilot/hosts.json | sed -e 's/.*oauth_token...//;s/\".*//'",
184+
"cat ~/.config/github-copilot/apps.json | sed -e 's/.*oauth_token...//;s/\".*//'",
185185
},
186186
},
187187

@@ -483,6 +483,13 @@ buffer (chat agents if current buffer is a chat and command agents otherwise).
483483
The agent setting is persisted on disk across Neovim instances.
484484

485485

486+
:GpSelectAgent *:GpSelectAgent*
487+
488+
Opens a selection interface using `vim.ui.select` to choose from all available
489+
agents, allowing you to directly select the desired agent from a list. Works
490+
seamlessly with telescope if available.
491+
492+
486493
IMAGE COMMANDS *gp.nvim-image-commands*
487494

488495

@@ -668,6 +675,7 @@ them at one place).
668675

669676
vim.keymap.set({"n", "i", "v", "x"}, "<C-g>s", "<cmd>GpStop<cr>", keymapOptions("Stop"))
670677
vim.keymap.set({"n", "i", "v", "x"}, "<C-g>n", "<cmd>GpNextAgent<cr>", keymapOptions("Next Agent"))
678+
vim.keymap.set({"n", "i", "v", "x"}, "<C-g>l", "<cmd>GpSelectAgent<cr>", keymapOptions("Select Agent"))
671679

672680
-- optional Whisper commands with prefix <C-g>w
673681
vim.keymap.set({"n", "i"}, "<C-g>ww", "<cmd>GpWhisper<cr>", keymapOptions("Whisper"))
@@ -722,6 +730,7 @@ Or go more fancy by using which-key.nvim
722730
{ "<C-g>gv", ":<C-u>'<,'>GpVnew<cr>", desc = "Visual GpVnew" },
723731
{ "<C-g>i", ":<C-u>'<,'>GpImplement<cr>", desc = "Implement selection" },
724732
{ "<C-g>n", "<cmd>GpNextAgent<cr>", desc = "Next Agent" },
733+
{ "<C-g>l", "<cmd>GpSelectAgent<cr>", desc = "Select Agent" },
725734
{ "<C-g>p", ":<C-u>'<,'>GpChatPaste<cr>", desc = "Visual Chat Paste" },
726735
{ "<C-g>r", ":<C-u>'<,'>GpRewrite<cr>", desc = "Visual Rewrite" },
727736
{ "<C-g>s", "<cmd>GpStop<cr>", desc = "GpStop" },
@@ -758,6 +767,7 @@ Or go more fancy by using which-key.nvim
758767
{ "<C-g>gt", "<cmd>GpTabnew<cr>", desc = "GpTabnew" },
759768
{ "<C-g>gv", "<cmd>GpVnew<cr>", desc = "GpVnew" },
760769
{ "<C-g>n", "<cmd>GpNextAgent<cr>", desc = "Next Agent" },
770+
{ "<C-g>l", "<cmd>GpSelectAgent<cr>", desc = "Select Agent" },
761771
{ "<C-g>r", "<cmd>GpRewrite<cr>", desc = "Inline Rewrite" },
762772
{ "<C-g>s", "<cmd>GpStop<cr>", desc = "GpStop" },
763773
{ "<C-g>t", "<cmd>GpChatToggle<cr>", desc = "Toggle Chat" },
@@ -793,6 +803,7 @@ Or go more fancy by using which-key.nvim
793803
{ "<C-g>gt", "<cmd>GpTabnew<cr>", desc = "GpTabnew" },
794804
{ "<C-g>gv", "<cmd>GpVnew<cr>", desc = "GpVnew" },
795805
{ "<C-g>n", "<cmd>GpNextAgent<cr>", desc = "Next Agent" },
806+
{ "<C-g>l", "<cmd>GpSelectAgent<cr>", desc = "Select Agent" },
796807
{ "<C-g>r", "<cmd>GpRewrite<cr>", desc = "Inline Rewrite" },
797808
{ "<C-g>s", "<cmd>GpStop<cr>", desc = "GpStop" },
798809
{ "<C-g>t", "<cmd>GpChatToggle<cr>", desc = "Toggle Chat" },

lua/gp/config.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ local config = {
4444
secret = {
4545
"bash",
4646
"-c",
47-
"cat ~/.config/github-copilot/hosts.json | sed -e 's/.*oauth_token...//;s/\".*//'",
47+
"cat ~/.config/github-copilot/apps.json | sed -e 's/.*oauth_token...//;s/\".*//'",
4848
},
4949
},
5050
ollama = {

lua/gp/dispatcher.lua

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,15 +180,11 @@ D.prepare_payload = function(messages, model, provider)
180180
return payload
181181
end
182182

183-
if provider == "copilot" and model.model == "gpt-4o" then
184-
model.model = "gpt-4o-2024-05-13"
185-
end
186-
187183
local output = {
188184
model = model.model,
189185
stream = true,
190186
messages = messages,
191-
max_tokens = model.max_tokens or 4096,
187+
max_completion_tokens = model.max_completion_tokens or 4096,
192188
temperature = math.max(0, math.min(2, model.temperature or 1)),
193189
top_p = math.max(0, math.min(1, model.top_p or 1)),
194190
}
@@ -204,6 +200,13 @@ D.prepare_payload = function(messages, model, provider)
204200
end
205201
end
206202
-- remove max_tokens, top_p, temperature for o1 models. https://platform.openai.com/docs/guides/reasoning/beta-limitations
203+
output.max_completion_tokens = nil
204+
output.temperature = nil
205+
output.top_p = nil
206+
end
207+
208+
if model.model == "gpt-5" or model.model == "gpt-5-mini" then
209+
-- remove max_tokens, top_p, temperature for gpt-5 models (duh)
207210
output.max_tokens = nil
208211
output.temperature = nil
209212
output.top_p = nil

lua/gp/init.lua

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ M.setup = function(opts)
247247
ChatNew = { "popup", "split", "vsplit", "tabnew" },
248248
ChatPaste = { "popup", "split", "vsplit", "tabnew" },
249249
ChatToggle = { "popup", "split", "vsplit", "tabnew" },
250+
ChatLast = { "popup", "split", "vsplit", "tabnew" },
250251
Context = { "popup", "split", "vsplit", "tabnew" },
251252
Agent = agent_completion,
252253
Do = do_completion,
@@ -632,7 +633,7 @@ end
632633

633634
---@param file_name string
634635
---@param target number | nil # buf target
635-
---@param kind number # nil or a toggle kind
636+
---@param kind number | nil # nil or a toggle kind, must be toggle kind when toggle is true
636637
---@param toggle boolean # whether to toggle
637638
---@return number # buffer number
638639
M.open_buf = function(file_name, target, kind, toggle)
@@ -642,6 +643,7 @@ M.open_buf = function(file_name, target, kind, toggle)
642643
M._toggle_close(M._toggle_kind.popup)
643644

644645
if toggle then
646+
---@cast kind number
645647
M._toggle_close(kind)
646648
end
647649

@@ -866,6 +868,46 @@ M.cmd.ChatToggle = function(params, system_prompt, agent)
866868
M.new_chat(params, true, system_prompt, agent)
867869
end
868870

871+
---@param params table
872+
---@return number | nil # buffer number or nil if no last chat
873+
M.cmd.ChatLast = function(params)
874+
local toggle = false
875+
-- if the range is 2, we want to create a new chat file with the selection
876+
if M._toggle_close(M._toggle_kind.chat) then
877+
params.args = params.args or ""
878+
if params.args == "" then
879+
params.args = M.config.toggle_target
880+
end
881+
toggle = true
882+
end
883+
local last = M._state.last_chat
884+
if last and vim.fn.filereadable(last) == 1 then
885+
last = vim.fn.resolve(last)
886+
-- get current buffer, for pasting selection if necessary
887+
local cbuf = vim.api.nvim_get_current_buf()
888+
local buf = M.helpers.get_buffer(last)
889+
local win_found = false
890+
if buf then
891+
for _, w in ipairs(vim.api.nvim_list_wins()) do
892+
if vim.api.nvim_win_get_buf(w) == buf then
893+
vim.api.nvim_set_current_win(w)
894+
vim.api.nvim_set_current_buf(buf)
895+
win_found = true
896+
break
897+
end
898+
end
899+
end
900+
buf = win_found and buf or M.open_buf(last, M.resolve_buf_target(params), toggle and M._toggle_kind.chat or nil, toggle)
901+
-- if there is a selection, paste it
902+
if params.range == 2 then
903+
M.render.append_selection(params, cbuf, buf, M.config.template_selection)
904+
M.helpers.feedkeys("G", "xn")
905+
end
906+
return buf
907+
end
908+
return nil
909+
end
910+
869911
M.cmd.ChatPaste = function(params)
870912
-- if there is no selection, do nothing
871913
if params.range ~= 2 then
@@ -1628,6 +1670,58 @@ M.cmd.NextAgent = function()
16281670
set_agent(agent_list[1])
16291671
end
16301672

1673+
M.cmd.SelectAgent = function()
1674+
local buf = vim.api.nvim_get_current_buf()
1675+
local file_name = vim.api.nvim_buf_get_name(buf)
1676+
local is_chat = M.not_chat(buf, file_name) == nil
1677+
local current_agent, agent_list
1678+
1679+
if is_chat then
1680+
current_agent = M._state.chat_agent
1681+
agent_list = M._chat_agents
1682+
else
1683+
current_agent = M._state.command_agent
1684+
agent_list = M._command_agents
1685+
end
1686+
1687+
if #agent_list == 0 then
1688+
M.logger.warning("No agents available")
1689+
return
1690+
end
1691+
1692+
-- Create options with current agent highlighted
1693+
local options = {}
1694+
for _, agent_name in ipairs(agent_list) do
1695+
if agent_name == current_agent then
1696+
table.insert(options, agent_name .. " (current)")
1697+
else
1698+
table.insert(options, agent_name)
1699+
end
1700+
end
1701+
1702+
vim.ui.select(options, {
1703+
prompt = is_chat and "Select chat agent:" or "Select command agent:",
1704+
format_item = function(item)
1705+
return item
1706+
end,
1707+
}, function(choice)
1708+
if not choice then
1709+
return
1710+
end
1711+
1712+
-- Remove " (current)" suffix if present
1713+
local agent_name = choice:gsub(" %(current%)$", "")
1714+
1715+
if is_chat then
1716+
M.refresh_state({ chat_agent = agent_name })
1717+
M.logger.info("Chat agent: " .. M._state.chat_agent)
1718+
else
1719+
M.refresh_state({ command_agent = agent_name })
1720+
M.logger.info("Command agent: " .. M._state.command_agent)
1721+
end
1722+
end)
1723+
end
1724+
16311725
---@param name string | nil
16321726
---@return table | nil # { cmd_prefix, name, model, system_prompt, provider}
16331727
M.get_command_agent = function(name)
@@ -1897,7 +1991,9 @@ M.Prompt = function(params, target, agent, template, prompt, whisper, callback)
18971991
-- mode specific logic
18981992
if target == M.Target.rewrite then
18991993
-- delete selection
1900-
vim.api.nvim_buf_set_lines(buf, start_line - 1, end_line - 1, false, {})
1994+
if not (start_line - 1 == 0 and end_line - 1 == 0 and vim.api.nvim_buf_get_lines(buf, 0, 1, false)[1] == "") then
1995+
vim.api.nvim_buf_set_lines(buf, start_line - 1, end_line - 1, false, {})
1996+
end
19011997
-- prepare handler
19021998
handler = M.dispatcher.create_handler(buf, win, start_line - 1, true, prefix, cursor)
19031999
elseif target == M.Target.append then

lua/gp/whisper.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ local whisper = function(callback, language)
205205
.. '" -H "Content-Type: multipart/form-data" '
206206
.. '-F model="whisper-1" -F language="'
207207
.. language
208-
.. '" -F file="@final.mp3" '
208+
.. '" -F file="@final.mp3;type=audio/mpeg" '
209209
.. '-F response_format="json"'
210210

211211
tasker.run(nil, "bash", { "-c", cmd }, function(code, signal, stdout, _)

0 commit comments

Comments
 (0)