From 2a305415b5cd61053d67af896999ee59212cb2c3 Mon Sep 17 00:00:00 2001 From: Roshan Bhatia Date: Sat, 13 Sep 2025 07:22:26 -0700 Subject: [PATCH 1/4] feat: adds goose as an acp-enabled adapter --- lua/codecompanion/adapters/acp/goose.lua | 57 ++++++++++++++++++++++++ lua/codecompanion/config.lua | 1 + 2 files changed, 58 insertions(+) create mode 100644 lua/codecompanion/adapters/acp/goose.lua diff --git a/lua/codecompanion/adapters/acp/goose.lua b/lua/codecompanion/adapters/acp/goose.lua new file mode 100644 index 000000000..6433a777c --- /dev/null +++ b/lua/codecompanion/adapters/acp/goose.lua @@ -0,0 +1,57 @@ +local helpers = require("codecompanion.adapters.acp.helpers") + +---@class CodeCompanion.ACPAdapter.Goose: CodeCompanion.ACPAdapter +return { + name = "goose", + formatted_name = "Goose", + type = "acp", + roles = { + llm = "assistant", + user = "user", + }, + opts = { + vision = true, + }, + commands = { + default = { + "goose", + "acp", + }, + }, + defaults = { + mcpServers = {}, + timeout = 20000, -- 20 seconds + }, + env = {}, + parameters = { + protocolVersion = 1, + clientCapabilities = { + fs = { readTextFile = true, writeTextFile = true }, + }, + clientInfo = { + name = "CodeCompanion.nvim", + version = "1.0.0", + }, + }, + handlers = { + ---@param self CodeCompanion.ACPAdapter + ---@return boolean + setup = function(self) + return true + end, + + ---@param self CodeCompanion.ACPAdapter + ---@param messages table + ---@param capabilities table + ---@return table + form_messages = function(self, messages, capabilities) + return helpers.form_messages(self, messages, capabilities) + end, + + ---Function to run when the request has completed. Useful to catch errors + ---@param self CodeCompanion.ACPAdapter + ---@param code number + ---@return nil + on_exit = function(self, code) end, + }, +} diff --git a/lua/codecompanion/config.lua b/lua/codecompanion/config.lua index d69112303..d23280d19 100644 --- a/lua/codecompanion/config.lua +++ b/lua/codecompanion/config.lua @@ -37,6 +37,7 @@ local defaults = { acp = { claude_code = "claude_code", gemini_cli = "gemini_cli", + goose = "goose", opts = { show_defaults = true, -- Show default adapters }, From 18007ec52f755158709d692aa9aacfe38514cc9c Mon Sep 17 00:00:00 2001 From: Roshan Bhatia Date: Sat, 13 Sep 2025 08:01:23 -0700 Subject: [PATCH 2/4] feat: add docs, tests for goose acp adapter --- README.md | 2 +- doc/codecompanion.txt | 36 +++++++++- doc/configuration/adapters.md | 31 +++++++++ tests/adapters/acp/test_goose.lua | 110 ++++++++++++++++++++++++++++++ tests/config.lua | 3 + 5 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 tests/adapters/acp/test_goose.lua diff --git a/README.md b/README.md index cd3739bc5..078161a81 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Thank you to the following people: - :speech_balloon: [Copilot Chat](https://github.com/features/copilot) meets [Zed AI](https://zed.dev/blog/zed-ai), in Neovim - :electric_plug: Support for LLMs from Anthropic, Copilot, GitHub Models, DeepSeek, Gemini, Mistral AI, Novita, Ollama, OpenAI, Azure OpenAI, HuggingFace and xAI (or [bring your own](https://codecompanion.olimorris.dev/extending/adapters.html)) -- :robot: Support for [Agent Client Protocol](https://agentclientprotocol.com), enabling coding with agents like [Claude Code](https://docs.anthropic.com/en/docs/claude-code/overview) and [Gemini CLI](https://github.com/google-gemini/gemini-cli) +- :robot: Support for [Agent Client Protocol](https://agentclientprotocol.com), enabling coding with agents like [Claude Code](https://docs.anthropic.com/en/docs/claude-code/overview), [Gemini CLI](https://github.com/google-gemini/gemini-cli) and [Goose](https://github.com/block/goose) - :heart_hands: User contributed and supported [adapters](https://codecompanion.olimorris.dev/configuration/adapters#community-adapters) - :rocket: [Inline transformations](https://codecompanion.olimorris.dev/usage/inline-assistant.html), code creation and refactoring - :art: [Variables](https://codecompanion.olimorris.dev/usage/chat-buffer/variables.html), [Slash Commands](https://codecompanion.olimorris.dev/usage/chat-buffer/slash-commands.html), [Tools](https://codecompanion.olimorris.dev/usage/chat-buffer/tools.html) and [Workflows](https://codecompanion.olimorris.dev/usage/workflows.html) to improve LLM output diff --git a/doc/codecompanion.txt b/doc/codecompanion.txt index 2d9ec11dd..b2c1851e9 100644 --- a/doc/codecompanion.txt +++ b/doc/codecompanion.txt @@ -1,4 +1,4 @@ -*codecompanion.txt* For NVIM v0.11 Last change: 2025 September 04 +*codecompanion.txt* For NVIM v0.11 Last change: 2025 September 13 ============================================================================== Table of Contents *codecompanion-table-of-contents* @@ -1048,6 +1048,40 @@ AN API KEY < +SETUP: GOOSE VIA ACP ~ + +Goose is an open-source developer agent that +can be used with CodeCompanion via the Agent Client Protocol (ACP). + +To use Goose within CodeCompanion: + +1. Install Goose +2. Configure the adapter in your CodeCompanion config: + +>lua + require("codecompanion").setup({ + adapters = { + acp = { + goose = function() + return require("codecompanion.adapters").extend("goose", { + -- Optional: Add MCP servers configuration if needed + defaults = { + mcpServers = {}, + timeout = 20000, -- 20 seconds + }, + }) + end, + }, + }, + }) +< + +1. Select "goose" as your adapter when using CodeCompanion + +The Goose adapter supports vision capabilities and file system operations +(read/write) through ACP. + + SETUP: USING OLLAMA REMOTELY ~ To use Ollama remotely, change the URL in the env table, set an API key and diff --git a/doc/configuration/adapters.md b/doc/configuration/adapters.md index b459aff9f..685ca0231 100644 --- a/doc/configuration/adapters.md +++ b/doc/configuration/adapters.md @@ -348,6 +348,37 @@ require("codecompanion").setup({ }) ``` +## Setup: Goose via ACP + +[Goose](https://github.com/block/goose) is an open-source developer agent that can be used with CodeCompanion via the Agent Client Protocol (ACP). + +To use Goose within CodeCompanion: + +1. [Install](https://github.com/block/goose#installation) Goose +2. Configure the adapter in your CodeCompanion config: + +```lua +require("codecompanion").setup({ + adapters = { + acp = { + goose = function() + return require("codecompanion.adapters").extend("goose", { + -- Optional: Add MCP servers configuration if needed + defaults = { + mcpServers = {}, + timeout = 20000, -- 20 seconds + }, + }) + end, + }, + }, +}) +``` + +3. Select "goose" as your adapter when using CodeCompanion + +The Goose adapter supports vision capabilities and file system operations (read/write) through ACP. + ## Setup: Using Ollama Remotely To use Ollama remotely, change the URL in the env table, set an API key and pass it via an "Authorization" header: diff --git a/tests/adapters/acp/test_goose.lua b/tests/adapters/acp/test_goose.lua new file mode 100644 index 000000000..6acbd3a56 --- /dev/null +++ b/tests/adapters/acp/test_goose.lua @@ -0,0 +1,110 @@ +local h = require("tests.helpers") + +local new_set = MiniTest.new_set +local child = MiniTest.new_child_neovim() + +T = new_set({ + hooks = { + pre_case = function() + h.child_start(child) + child.lua([[ + h = require("tests.helpers") + h.setup_plugin() + package.loaded["codecompanion.config"] = require("tests.config") + ]]) + end, + post_case = child.stop, + }, +}) + +T["Goose ACP Adapter"] = new_set() + +T["Goose ACP Adapter"]["can resolve goose adapter"] = function() + local result = child.lua([[ + local adapter = require("codecompanion.adapters").resolve("goose") + return { + name = adapter.name, + formatted_name = adapter.formatted_name, + type = adapter.type, + resolved = require("codecompanion.adapters").resolved(adapter) + } + ]]) + + h.eq({ + name = "goose", + formatted_name = "Goose", + type = "acp", + resolved = true, + }, result) +end + +T["Goose ACP Adapter"]["has correct default configuration"] = function() + local result = child.lua([[ + local adapter = require("codecompanion.adapters").resolve("goose") + return { + roles = adapter.roles, + opts = adapter.opts, + commands = adapter.commands, + defaults = adapter.defaults, + } + ]]) + + h.eq({ + roles = { llm = "assistant", user = "user" }, + opts = { vision = true }, + commands = { default = { "goose", "acp" }, selected = { "goose", "acp" } }, + defaults = { mcpServers = {}, timeout = 20000 }, + }, result) +end + +T["Goose ACP Adapter"]["has correct parameters"] = function() + local result = child.lua([[ + local adapter = require("codecompanion.adapters").resolve("goose") + return adapter.parameters + ]]) + + h.eq({ + protocolVersion = 1, + clientCapabilities = { + fs = { readTextFile = true, writeTextFile = true }, + }, + clientInfo = { + name = "CodeCompanion.nvim", + version = "1.0.0", + }, + }, result) +end + +T["Goose ACP Adapter"]["handlers setup returns true"] = function() + local result = child.lua([[ + local adapter = require("codecompanion.adapters").resolve("goose") + return adapter.handlers.setup(adapter) + ]]) + + h.eq(true, result) +end + +T["Goose ACP Adapter"]["form_messages handler works correctly"] = function() + local result = child.lua([[ + local adapter = require("codecompanion.adapters").resolve("goose") + local messages = { + { role = "user", content = "Hello", _meta = { sent = false } }, + { role = "assistant", content = "Hi there!", _meta = { sent = true } } + } + local capabilities = { promptCapabilities = {} } + local formed = adapter.handlers.form_messages(adapter, messages, capabilities) + + -- Basic check that messages are returned (only unsent user messages should be returned) + return { + count = #formed, + first_type = formed[1] and formed[1].type or "text" + } + ]]) + + h.eq({ + count = 1, + first_type = "text", + }, result) +end + +return T diff --git a/tests/config.lua b/tests/config.lua index 2c629e42f..474e75d0a 100644 --- a/tests/config.lua +++ b/tests/config.lua @@ -65,6 +65,9 @@ return { command = { "node", "test-agent.js" }, roles = { user = "user", assistant = "assistant" }, }, + goose = function() + return require("codecompanion.adapters.acp.goose") + end, }, }, strategies = { From 6ce962357a3a95584d6460c4dfeeaed86f821d13 Mon Sep 17 00:00:00 2001 From: Roshan Bhatia Date: Sat, 13 Sep 2025 08:11:27 -0700 Subject: [PATCH 3/4] fix: removes MCP servers block from goose adapter --- lua/codecompanion/adapters/acp/goose.lua | 1 - tests/adapters/acp/test_goose.lua | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lua/codecompanion/adapters/acp/goose.lua b/lua/codecompanion/adapters/acp/goose.lua index 6433a777c..1f26f1070 100644 --- a/lua/codecompanion/adapters/acp/goose.lua +++ b/lua/codecompanion/adapters/acp/goose.lua @@ -19,7 +19,6 @@ return { }, }, defaults = { - mcpServers = {}, timeout = 20000, -- 20 seconds }, env = {}, diff --git a/tests/adapters/acp/test_goose.lua b/tests/adapters/acp/test_goose.lua index 6acbd3a56..b6fd2e8dd 100644 --- a/tests/adapters/acp/test_goose.lua +++ b/tests/adapters/acp/test_goose.lua @@ -53,7 +53,7 @@ T["Goose ACP Adapter"]["has correct default configuration"] = function() roles = { llm = "assistant", user = "user" }, opts = { vision = true }, commands = { default = { "goose", "acp" }, selected = { "goose", "acp" } }, - defaults = { mcpServers = {}, timeout = 20000 }, + defaults = { timeout = 20000 }, }, result) end From 495b4c4196069f9ebbeba6538f1096a5f760818d Mon Sep 17 00:00:00 2001 From: Roshan Bhatia Date: Sat, 13 Sep 2025 08:12:48 -0700 Subject: [PATCH 4/4] docs: remove mcpservers block from goose --- doc/codecompanion.txt | 2 -- doc/configuration/adapters.md | 2 -- 2 files changed, 4 deletions(-) diff --git a/doc/codecompanion.txt b/doc/codecompanion.txt index b2c1851e9..0a85c42bb 100644 --- a/doc/codecompanion.txt +++ b/doc/codecompanion.txt @@ -1064,9 +1064,7 @@ To use Goose within CodeCompanion: acp = { goose = function() return require("codecompanion.adapters").extend("goose", { - -- Optional: Add MCP servers configuration if needed defaults = { - mcpServers = {}, timeout = 20000, -- 20 seconds }, }) diff --git a/doc/configuration/adapters.md b/doc/configuration/adapters.md index 685ca0231..acabd95fa 100644 --- a/doc/configuration/adapters.md +++ b/doc/configuration/adapters.md @@ -363,9 +363,7 @@ require("codecompanion").setup({ acp = { goose = function() return require("codecompanion.adapters").extend("goose", { - -- Optional: Add MCP servers configuration if needed defaults = { - mcpServers = {}, timeout = 20000, -- 20 seconds }, })