codecompanion.nvimは、NeovimでAIチャットを実現するためのプラグインです。
デフォルトでcopilotやanthropicなどのAPIを利用してチャットする仕組みが用意されており、:CopilotChat copilotなどとして、好きなサービスと会話できます。
https://github.com/olimorris/codecompanion.nvim/tree/main/lua/codecompanion/adapters
さらに、リストにないサービスを利用する方法も提供されています。
CREATING ADAPTERS *codecompanion-extending-creating-adapters*https://github.com/olimorris/codecompanion.nvim/blob/9654cb31f10c9eda3e777d03d32b29df606ab0fe/doc/codecompanion.txt#L2442
手順としてはざっくり
- アダプタと呼ばれる、APIの利用方法の定義を作成する
require("copilotchat").setup({...})でアダプを登録する
といった感じ。
アダプタ定義に関してはAPIがOpenAI互換であれば、xai.luaを参考にして、簡単に実装できるようです。
https://github.com/olimorris/codecompanion.nvim/blob/main/lua/codecompanion/adapters/xai.lua
実際 .name, .formatted_name, .url, .env.api_key, .schema.modelを変更するだけで、OpenRouterのAPIのアダプタを作成できました。
-- 未変更部省略してるので完全版は以下を参照
-- https://github.com/atusy/dotfiles/blob/8736ff4c42ec3336e51165c2928a59bd2c9268b7/dot_config/nvim/lua/plugins/codecompanion/adapter/openrouter.lua
return {
name = "openrouter",
formatted_name = "openrouter",
url = "https://openrouter.ai/api/v1/chat/completions",
env = {
api_key = "OPENROUTER_API_KEY",
-- `"cmd: bw get password <id>"`とかでコマンド経由にもできるらしい
-- Bitwardenの場合は、アカウント認証用のパスワード入力をうまくできなくて一旦断念
},
schema = {
model = {
-- デフォルトで利用したいモデルと、その他の選択肢を定義
default = "google/gemini-2.0-flash-001",
choices = {
-- free
"openrouter/optimus-alpha",
"google/gemini-2.0-flash-exp:free",
-- paid
"google/gemini-2.0-flash-001",
"openrouter/auto",
},
},
}
}あとは定義したアダプタをsetup関数のadaptersに登録すればOK
require("copilotchat").setup({
adapters = {
openrouter = require("plugins.codecompanion.adapter.openrouter"), -- モジュール名は例
optimus = function()
return require("codecompanion.adapters").extend("openrouter", {
schema = { model = { default = "openrouter/optimus-alpha" } },
})
end,
},
})なお、require("codecompanion.adapters").extend関数を使うと利用するモデルを変更したアダプタを簡単に作成&登録できます。だったらopenaiアダプタをextendすれば、アダプタ定義をかなり楽にできるかと思いましたが、extend経由で変更できるフィールドは一部に限定されているみたいで、無理でした。
require("copilotchat").setup({
adapters = {
optimus = function()
return require("codecompanion.adapters").extend("openrouter", {
schema = { model = { default = "openrouter/optimus-alpha" } },
})
end,
},
})ENJOY!
Atusy's blog