Skip to content

Commit 03f7a30

Browse files
authored
refactor(nvim)!: Split Codecompanion Tools for fine-grained control, and drop slash command (#192)
* refactor(nvim): create the `vectorcode_ls` tool. * refactor(nvim)!: Rename and refactor codecompanion tools for vectorcode * feat(nvim): Expose `vectorise` command to codecompanion * refactor(nvim): Refactor tool option handling for vectorcode extension * feat(nvim): show vectorise stats for the vectorise tool * feat(nvim): improve project_root checks. * feat(nvim): streamline vectorcode tool registration and group creation * feat(nvim): Allow adding custom tools to the vectorcode tool group * docs(nvim): Update codecompanion chat image * chore(nvim): Update Vectorise tool stats message * fix(nvim): Normalise and absolute project root for codecompanion tools * refactor(nvim): Update query tool schema and remove system prompt * chore(nvim): Remove include_stderr option and log tool options
1 parent 91d0d8d commit 03f7a30

12 files changed

Lines changed: 568 additions & 398 deletions

File tree

images/codecompanion_chat.png

329 KB
Loading

lua/codecompanion/_extensions/vectorcode/init.lua

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,81 @@
11
---@module "codecompanion"
22

3+
---@alias sub_cmd "ls"|"query"|"vectorise"
4+
35
---@class VectorCode.CodeCompanion.ExtensionOpts
4-
---@field add_tools boolean|string|nil
5-
---@field tool_opts VectorCode.CodeCompanion.ToolOpts
6-
---@field add_slash_command boolean
6+
--- A table where the keys are the subcommand name (`ls`, `query`, `vectorise`)
7+
--- and the values are their config options.
8+
---@field tool_opts table<sub_cmd, VectorCode.CodeCompanion.ToolOpts>
9+
--- Whether to add a tool group that contains all vectorcode tools.
10+
---@field tool_group VectorCode.CodeCompanion.ToolGroupOpts
711

812
local vc_config = require("vectorcode.config")
913
local logger = vc_config.logger
1014

15+
---@type VectorCode.CodeCompanion.ExtensionOpts|{}
16+
local default_extension_opts = {
17+
tool_opts = { ls = {}, query = {}, vectorise = {} },
18+
tool_group = { enabled = true, collapse = true, extras = {} },
19+
}
20+
21+
---@type sub_cmd[]
22+
local valid_tools = { "ls", "query", "vectorise" }
23+
1124
---@type CodeCompanion.Extension
1225
local M = {
1326
---@param opts VectorCode.CodeCompanion.ExtensionOpts
1427
setup = vc_config.check_cli_wrap(function(opts)
15-
opts = vim.tbl_deep_extend(
16-
"force",
17-
{ add_tool = true, add_slash_command = false },
18-
opts or {}
19-
)
28+
opts = vim.tbl_deep_extend("force", default_extension_opts, opts or {})
2029
logger.info("Received codecompanion extension opts:\n", opts)
2130
local cc_config = require("codecompanion.config").config
2231
local cc_integration = require("vectorcode.integrations").codecompanion.chat
23-
if opts.add_tool then
24-
local tool_name = "vectorcode"
25-
if type(opts.add_tool) == "string" then
26-
tool_name = tostring(opts.add_tool)
27-
end
32+
for _, sub_cmd in pairs(valid_tools) do
33+
local tool_name = string.format("vectorcode_%s", sub_cmd)
2834
if cc_config.strategies.chat.tools[tool_name] ~= nil then
2935
vim.notify(
30-
"There's an existing tool named `vectorcode`. Please either remove it or rename it.",
36+
string.format(
37+
"There's an existing tool named `%s`. Please either remove it or rename it.",
38+
tool_name
39+
),
3140
vim.log.levels.ERROR,
3241
vc_config.notify_opts
3342
)
3443
logger.warn(
3544
string.format(
36-
"Not creating a tool because there is an existing tool named %s.",
45+
"Not creating this tool because there is an existing tool named %s.",
3746
tool_name
3847
)
3948
)
4049
else
4150
cc_config.strategies.chat.tools[tool_name] = {
42-
description = "Run VectorCode to retrieve the project context.",
43-
callback = cc_integration.make_tool(opts.tool_opts),
51+
description = string.format("Run VectorCode %s tool", sub_cmd),
52+
callback = cc_integration.make_tool(sub_cmd, opts.tool_opts[sub_cmd]),
4453
}
4554
logger.info(string.format("%s tool has been created.", tool_name))
4655
end
4756
end
48-
if opts.add_slash_command then
49-
local command_name = "vectorcode"
50-
if type(opts.add_slash_command) == "string" then
51-
command_name = tostring(opts.add_slash_command)
57+
58+
if opts.tool_group.enabled then
59+
local included_tools = vim
60+
.iter(valid_tools)
61+
:map(function(s)
62+
return "vectorcode_" .. s
63+
end)
64+
:totable()
65+
if opts.tool_group.extras and not vim.tbl_isempty(opts.tool_group.extras) then
66+
vim.list_extend(included_tools, opts.tool_group.extras)
5267
end
53-
if cc_config.strategies.chat.slash_commands[command_name] ~= nil then
54-
vim.notify(
55-
"There's an existing slash command named `vectorcode`. Please either remove it or rename it.",
56-
vim.log.levels.ERROR,
57-
vc_config.notify_opts
58-
)
59-
logger.warn(
60-
string.format(
61-
"Not creating a command because there is an existing slash command named %s.",
62-
command_name
63-
)
68+
logger.info(
69+
string.format(
70+
"Loading the following tools into `vectorcode_toolbox` tool group:\n%s",
71+
vim.inspect(included_tools)
6472
)
65-
else
66-
cc_config.strategies.chat.slash_commands[command_name] =
67-
cc_integration.make_slash_command()
68-
logger.info(string.format("%s command has been created.", command_name))
69-
end
73+
)
74+
cc_config.strategies.chat.tools.groups["vectorcode_toolbox"] = {
75+
opts = { collapse_tools = opts.tool_group.collapse },
76+
description = "Use VectorCode to automatically build and retrieve repository-level context.",
77+
tools = included_tools,
78+
}
7079
end
7180
end),
7281
}

lua/vectorcode/cacher/default.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ M.query_from_cache = vc_config.check_cli_wrap(
257257
---of the array is in the format of `{path="path/to/your/code.lua", document="document content"}`.
258258
---@param bufnr integer?
259259
---@param opts {notify: boolean}?
260-
---@return VectorCode.Result[]
260+
---@return VectorCode.QueryResult[]
261261
function(bufnr, opts)
262262
local result = {}
263263
if bufnr == 0 or bufnr == nil then
@@ -282,7 +282,7 @@ M.query_from_cache = vc_config.check_cli_wrap(
282282
end
283283
)
284284

285-
---@alias ComponentCallback fun(result:VectorCode.Result):string
285+
---@alias ComponentCallback fun(result:VectorCode.QueryResult):string
286286

287287
---Compile the retrieval results into a string.
288288
---@param bufnr integer
@@ -296,7 +296,7 @@ function M.make_prompt_component(bufnr, component_cb)
296296
return { content = "", count = 0 }
297297
end
298298
if component_cb == nil then
299-
---@type fun(result:VectorCode.Result):string
299+
---@type fun(result:VectorCode.QueryResult):string
300300
component_cb = function(result)
301301
return "<|file_sep|>" .. result.path .. "\n" .. result.document
302302
end

lua/vectorcode/cacher/lsp.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ M.query_from_cache = vc_config.check_cli_wrap(
292292
---of the array is in the format of `{path="path/to/your/code.lua", document="document content"}`.
293293
---@param bufnr integer?
294294
---@param opts {notify: boolean}?
295-
---@return VectorCode.Result[]
295+
---@return VectorCode.QueryResult[]
296296
function(bufnr, opts)
297297
local result = {}
298298
if bufnr == 0 or bufnr == nil then
@@ -329,7 +329,7 @@ function M.make_prompt_component(bufnr, component_cb)
329329
return { content = "", count = 0 }
330330
end
331331
if component_cb == nil then
332-
---@type fun(result:VectorCode.Result):string
332+
---@type fun(result:VectorCode.QueryResult):string
333333
component_cb = function(result)
334334
return "<|file_sep|>" .. result.path .. "\n" .. result.document
335335
end

lua/vectorcode/init.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ M.query = vc_config.check_cli_wrap(
1414
---callback).
1515
---@param query_message string|string[] Query message(s) to send to the `vecctorcode query` command
1616
---@param opts VectorCode.QueryOpts? A table of config options. If nil, the default config or `setup` config will be used.
17-
---@param callback fun(result:VectorCode.Result[])? Use the result async style.
18-
---@return VectorCode.Result[]? An array of results.
17+
---@param callback fun(result:VectorCode.QueryResult[])? Use the result async style.
18+
---@return VectorCode.QueryResult[]? An array of results.
1919
function(query_message, opts, callback)
2020
logger.info("vectorcode.query: ", query_message, opts, callback)
2121
opts = vim.tbl_deep_extend("force", vc_config.get_query_opts(), opts or {})

lua/vectorcode/integrations/codecompanion/common.lua

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,22 @@ local vc_config = require("vectorcode.config")
33
local notify_opts = vc_config.notify_opts
44
local logger = vc_config.logger
55

6-
---@type VectorCode.CodeCompanion.ToolOpts
7-
local default_options = {
6+
---@type VectorCode.CodeCompanion.QueryToolOpts
7+
local default_query_options = {
88
max_num = { chunk = -1, document = -1 },
99
default_num = { chunk = 50, document = 10 },
10-
include_stderr = false,
1110
use_lsp = false,
1211
ls_on_start = false,
1312
no_duplicate = true,
1413
chunk_mode = false,
1514
}
1615

16+
---@type VectorCode.CodeCompanion.LsToolOpts
17+
local default_ls_options = { use_lsp = false }
18+
19+
---@type VectorCode.CodeCompanion.VectoriseToolOpts
20+
local default_vectorise_options = { use_lsp = false }
21+
1722
return {
1823
tool_result_source = "VectorCodeToolResult",
1924
---@param t table|string
@@ -25,17 +30,43 @@ return {
2530
return table.concat(vim.iter(t):flatten(math.huge):totable(), "\n")
2631
end,
2732

28-
---@param opts VectorCode.CodeCompanion.ToolOpts|{}|nil
29-
---@return VectorCode.CodeCompanion.ToolOpts
30-
get_tool_opts = function(opts)
33+
---@param opts VectorCode.CodeCompanion.LsToolOpts|{}|nil
34+
---@return VectorCode.CodeCompanion.LsToolOpts
35+
get_ls_tool_opts = function(opts)
36+
opts = vim.tbl_deep_extend("force", default_ls_options, opts or {})
37+
logger.info(
38+
string.format(
39+
"Loading `vectorcode_ls` with the following opts:\n%s",
40+
vim.inspect(opts)
41+
)
42+
)
43+
return opts
44+
end,
45+
46+
---@param opts VectorCode.CodeCompanion.VectoriseToolOpts|{}|nil
47+
---@return VectorCode.CodeCompanion.VectoriseToolOpts
48+
get_vectorise_tool_opts = function(opts)
49+
opts = vim.tbl_deep_extend("force", default_vectorise_options, opts or {})
50+
logger.info(
51+
string.format(
52+
"Loading `vectorcode_vectorise` with the following opts:\n%s",
53+
vim.inspect(opts)
54+
)
55+
)
56+
return opts
57+
end,
58+
59+
---@param opts VectorCode.CodeCompanion.QueryToolOpts|{}|nil
60+
---@return VectorCode.CodeCompanion.QueryToolOpts
61+
get_query_tool_opts = function(opts)
3162
if opts == nil or opts.use_lsp == nil then
3263
opts = vim.tbl_deep_extend(
3364
"force",
3465
opts or {},
3566
{ use_lsp = vc_config.get_user_config().async_backend == "lsp" }
3667
)
3768
end
38-
opts = vim.tbl_deep_extend("force", default_options, opts)
69+
opts = vim.tbl_deep_extend("force", default_query_options, opts)
3970
if type(opts.default_num) == "table" then
4071
if opts.chunk_mode then
4172
opts.default_num = opts.default_num.chunk
@@ -48,7 +79,7 @@ return {
4879
)
4980
end
5081
if type(opts.max_num) == "table" then
51-
if opts.chunk_mode then
82+
if opts._ then
5283
opts.max_num = opts.max_num.chunk
5384
else
5485
opts.max_num = opts.max_num.document
@@ -58,10 +89,16 @@ return {
5889
"max_num should be an integer or a table: {chunk: integer, document: integer}"
5990
)
6091
end
92+
logger.info(
93+
string.format(
94+
"Loading `vectorcode_query` with the following opts:\n%s",
95+
vim.inspect(opts)
96+
)
97+
)
6198
return opts
6299
end,
63100

64-
---@param result VectorCode.Result
101+
---@param result VectorCode.QueryResult
65102
---@return string
66103
process_result = function(result)
67104
local llm_message

0 commit comments

Comments
 (0)