diff --git a/doc/codecompanion.txt b/doc/codecompanion.txt index a2f8bece7..00b9620ff 100644 --- a/doc/codecompanion.txt +++ b/doc/codecompanion.txt @@ -1,4 +1,4 @@ -*codecompanion.txt* For NVIM v0.11 Last change: 2025 November 24 +*codecompanion.txt* For NVIM v0.11 Last change: 2025 November 27 ============================================================================== Table of Contents *codecompanion-table-of-contents* @@ -878,9 +878,10 @@ The configuration for both types of adapters is exactly the same, however they sit within their own tables (`adapters.http.*` and `adapters.acp.*`) and have different options available. HTTP adapters use `models` to allow users to select the specific LLM they’d like to interact with. ACP adapters use -`commands` to allow users to customize their interaction with agents (e.g.� -enabling `yolo` mode). As there is a lot of shared functionality between the -two adapters, it is recommend that you read this page alongside the ACP one. +`commands` to allow users to customize their interaction with agents +(e.g. enabling `yolo` mode). As there is a lot of shared functionality between +the two adapters, it is recommend that you read this page alongside the ACP +one. CHANGING THE DEFAULT ADAPTER ~ @@ -912,7 +913,7 @@ the adapter’s URL, headers, parameters and other fields at runtime. Supported `env` value types: - **Plain environment variable name (string)**: if the value is the name of an environment variable that has already been set -(e.g.� `"HOME"` or `"GEMINI_API_KEY"`), the plugin will read the value. - +(e.g. `"HOME"` or `"GEMINI_API_KEY"`), the plugin will read the value. - **Command (string prefixed with cmd:)**: any value that starts with `cmd:` will be executed via the shell. Example: `"cmd:op read op://personal/Gemini/credential --no-newline"`. - **Function**: you can provide @@ -2909,7 +2910,7 @@ The fastest way to copy an LLM’s code output is with `gy`. This will yank the nearest codeblock. -APPLYING AN LLM€�S EDITS TO A BUFFER OR FILE ~ +APPLYING AN LLM’S EDITS TO A BUFFER OR FILE ~ The |codecompanion-usage-chat-buffer-tools-files| tool, combined with the |codecompanion-usage-chat-buffer-variables.html-buffer| variable or @@ -4977,7 +4978,7 @@ These handlers manage tool/function calling: as a great reference to understand how they’re working with the output of the API -OPENAI€�S API OUTPUT +OPENAI’S API OUTPUT If we reference the OpenAI documentation @@ -6884,7 +6885,7 @@ tool to function. In the case of Anthropic, we insert additional headers. < Some adapter tools can be a `hybrid` in terms of their implementation. That is, -they’re an adapter tool that requires a client-side component (i.e.� a +they’re an adapter tool that requires a client-side component (i.e. a built-in tool). This is the case for the |codecompanion-usage-chat-buffer-tools-memory| tool from Anthropic. To allow for this, ensure that the tool definition in `available_tools` has diff --git a/lua/codecompanion/strategies/chat/init.lua b/lua/codecompanion/strategies/chat/init.lua index c934a2e7e..b7597087e 100644 --- a/lua/codecompanion/strategies/chat/init.lua +++ b/lua/codecompanion/strategies/chat/init.lua @@ -1398,6 +1398,7 @@ function Chat:check_context() -- Clear any tool's schemas local schemas_to_keep = {} local tools_in_use_to_keep = {} + local groups_in_use_to_keep = {} for id, tool_schema in pairs(self.tool_registry.schemas) do if not vim.tbl_contains(to_remove, id) then schemas_to_keep[id] = tool_schema @@ -1405,12 +1406,17 @@ function Chat:check_context() if tool_name and self.tool_registry.in_use[tool_name] then tools_in_use_to_keep[tool_name] = true end + local group_name = id:match("(.*)") + if group_name and self.tool_registry.groups_in_use[group_name] then + groups_in_use_to_keep[group_name] = true + end else log:debug("Removing tool schema and usage flag for ID: %s", id) -- Optional logging end end self.tool_registry.schemas = schemas_to_keep self.tool_registry.in_use = tools_in_use_to_keep + self.tool_registry.groups_in_use = groups_in_use_to_keep end ---Refresh the chat context by syncing to message-linked context IDs and re-rendering diff --git a/lua/codecompanion/strategies/chat/tool_registry.lua b/lua/codecompanion/strategies/chat/tool_registry.lua index dc60eb336..976699e3a 100644 --- a/lua/codecompanion/strategies/chat/tool_registry.lua +++ b/lua/codecompanion/strategies/chat/tool_registry.lua @@ -6,6 +6,7 @@ Methods for handling interactions between the chat buffer and tools ---@field chat CodeCompanion.Chat ---@field flags table Flags that external functions can update and subscribers can interact with ---@field in_use table Tools that are in use on the chat buffer +---@field groups_in_use table Tool groups that are in use on the chat buffer ---@field schemas table The config for the tools in use ---@class CodeCompanion.Chat.ToolRegistry @@ -23,6 +24,7 @@ function ToolRegistry.new(args) chat = args.chat, flags = {}, in_use = {}, + groups_in_use = {}, schemas = {}, }, { __index = ToolRegistry }) @@ -122,6 +124,10 @@ function ToolRegistry:add_group(group, tools_config) return end + if self.groups_in_use[group] then + return + end + local opts = vim.tbl_deep_extend("force", { collapse_tools = true }, group_config.opts or {}) local collapse_tools = opts.collapse_tools @@ -144,6 +150,8 @@ function ToolRegistry:add_group(group, tools_config) for _, tool in ipairs(group_config.tools) do self:add(tool, tools_config[tool], { visible = not collapse_tools }) end + + self.groups_in_use[group] = true end ---Add a tool system prompt to the chat buffer, updated for every tool addition @@ -179,6 +187,7 @@ end function ToolRegistry:clear() self.flags = {} self.in_use = {} + self.groups_in_use = {} self.schemas = {} end diff --git a/lua/codecompanion/strategies/init.lua b/lua/codecompanion/strategies/init.lua index 5c7367bba..7583b980f 100644 --- a/lua/codecompanion/strategies/init.lua +++ b/lua/codecompanion/strategies/init.lua @@ -209,6 +209,12 @@ function Strategies:workflow() messages = messages, }) + for _, msg in ipairs(chat.messages) do + if msg.content then + chat:replace_vars_and_tools(msg) + end + end + ---TODO: Remove workflow.references in v18.0.0 if workflow.references or workflow.context then self.add_context(workflow, chat) @@ -228,7 +234,11 @@ function Strategies:workflow() if type(val.content) == "function" then val.content = val.content(self.buffer_context) end - chat:add_buf_message(val) + chat:replace_vars_and_tools(val) + chat:add_message(val, val.opts) + if not (val.opts and val.opts.visible == false) then + chat:add_buf_message(val, val.opts) + end if val.opts and val.opts.adapter and val.opts.adapter.name then chat:change_adapter(val.opts.adapter.name, val.opts.adapter.model) end