Skip to content

Commit 60fb910

Browse files
authored
refactor(core): split tool and function resolution logic (#1376)
Separate tool resolution from function/resource resolution in core logic. This improves code clarity and maintainability by decoupling concerns. Signed-off-by: Tomas Slusny <slusnucky@gmail.com>
1 parent 1ad9e7a commit 60fb910

3 files changed

Lines changed: 44 additions & 25 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ local chat = require("CopilotChat")
395395
chat.ask(prompt, config) -- Ask a question with optional config
396396
chat.response() -- Get the last response text
397397
chat.resolve_prompt() -- Resolve prompt references
398-
chat.resolve_functions() -- Resolve functions that are available for automatic use by LLM (WARN: async, requires plenary.async.run)
398+
chat.resolve_tools() -- Resolve tools that are available for automatic use by LLM
399399
chat.resolve_model() -- Resolve model from prompt (WARN: async, requires plenary.async.run)
400400

401401
-- Window Management

lua/CopilotChat/config/mappings.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,10 @@ return {
457457

458458
async.run(function()
459459
local infos = client:info()
460+
local selected_tools = copilot.resolve_tools(prompt, config)
460461
local selected_model = copilot.resolve_model(prompt, config)
461-
local selected_tools, resolved_resources = copilot.resolve_functions(prompt, config)
462+
local resolved_resources = copilot.resolve_functions(prompt, config)
463+
462464
selected_tools = vim.tbl_map(function(tool)
463465
return tool.name
464466
end, selected_tools)

lua/CopilotChat/init.lua

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -294,10 +294,46 @@ local function update_source()
294294
M.set_source(use_prev_window and vim.fn.win_getid(vim.fn.winnr('#')) or vim.api.nvim_get_current_win())
295295
end
296296

297+
--- Resolve enabled tools from the prompt.
298+
---@param prompt string?
299+
---@param config CopilotChat.config.Shared?
300+
---@return table<CopilotChat.client.Tool>, string
301+
function M.resolve_tools(prompt, config)
302+
config, prompt = M.resolve_prompt(prompt, config)
303+
304+
local tools = {}
305+
for _, tool in ipairs(functions.parse_tools(M.config.functions)) do
306+
tools[tool.name] = tool
307+
end
308+
309+
local enabled_tools = {}
310+
local tool_matches = utils.to_table(config.tools)
311+
312+
-- Check for @tool pattern to find enabled tools
313+
prompt = prompt:gsub('@' .. WORD, function(match)
314+
for name, tool in pairs(M.config.functions) do
315+
if name == match or tool.group == match then
316+
table.insert(tool_matches, match)
317+
return ''
318+
end
319+
end
320+
return '@' .. match
321+
end)
322+
for _, match in ipairs(tool_matches) do
323+
for name, tool in pairs(M.config.functions) do
324+
if name == match or tool.group == match then
325+
table.insert(enabled_tools, tools[name])
326+
end
327+
end
328+
end
329+
330+
return enabled_tools, prompt
331+
end
332+
297333
--- Call and resolve function calls from the prompt.
298334
---@param prompt string?
299335
---@param config CopilotChat.config.Shared?
300-
---@return table<CopilotChat.client.Tool>, table<CopilotChat.client.Resource>, table, string
336+
---@return table<CopilotChat.client.Resource>, table, string
301337
---@async
302338
function M.resolve_functions(prompt, config)
303339
config, prompt = M.resolve_prompt(prompt, config)
@@ -317,10 +353,8 @@ function M.resolve_functions(prompt, config)
317353
prompt = table.concat(lines, '\n')
318354
end
319355

320-
local enabled_tools = {}
321356
local resolved_resources = {}
322357
local resolved_tools = {}
323-
local tool_matches = utils.to_table(config.tools)
324358
local tool_calls = {}
325359
for _, message in ipairs(M.chat.messages) do
326360
if message.tool_calls then
@@ -330,24 +364,6 @@ function M.resolve_functions(prompt, config)
330364
end
331365
end
332366

333-
-- Check for @tool pattern to find enabled tools
334-
prompt = prompt:gsub('@' .. WORD, function(match)
335-
for name, tool in pairs(M.config.functions) do
336-
if name == match or tool.group == match then
337-
table.insert(tool_matches, match)
338-
return ''
339-
end
340-
end
341-
return '@' .. match
342-
end)
343-
for _, match in ipairs(tool_matches) do
344-
for name, tool in pairs(M.config.functions) do
345-
if name == match or tool.group == match then
346-
table.insert(enabled_tools, tools[name])
347-
end
348-
end
349-
end
350-
351367
local resource_matches = {}
352368

353369
-- Check for #word:`input` pattern
@@ -483,7 +499,7 @@ function M.resolve_functions(prompt, config)
483499
end
484500
end
485501

486-
return enabled_tools, resolved_resources, resolved_tools, prompt
502+
return resolved_resources, resolved_tools, prompt
487503
end
488504

489505
--- Resolve the final prompt and config from prompt template.
@@ -795,7 +811,8 @@ function M.ask(prompt, config)
795811
)
796812

797813
async.run(handle_error(config, function()
798-
local selected_tools, resolved_resources, resolved_tools, prompt = M.resolve_functions(prompt, config)
814+
local selected_tools, prompt = M.resolve_tools(prompt, config)
815+
local resolved_resources, resolved_tools, prompt = M.resolve_functions(prompt, config)
799816
local selected_model, prompt = M.resolve_model(prompt, config)
800817

801818
prompt = vim.trim(prompt)

0 commit comments

Comments
 (0)