プロローグ
Neovimでは、olimorris/codecompanion.nvimというプラグインによってAIと連携したコーディングを行うことができます。
筆者はこれまでは、直接GoogleのGeminiのAPIを叩くことでAI Chatを開き、指定したバッファの内容を与えてコーディングを行う設定は行っていました。
しかし、この設定では、コーディングエージェントとしてソースコードを生成させたりするようなことはできません。
エディタやIDEとコーディングエージェントのようなAIエージェントとはACP(Agent Client Protocol)というプロトコルによってデータのやりとりをすることが可能で、 有名どころでは、ZedやJetbrainsの各種IDEが対応しています。 NeovimでもCodeCompanion.nvimとによってACPに対応したAIエージェントと連携することが可能です。
筆者はCodeCompanion.nvimで使うAIのサービスとしては、GoogleのGeminiを使用していたので、 Geminiのエージェントである、Gemini CLIをNeovimから使えるように設定を行うことにしました。
とりあえず設定してみたものの…
CodeCompanionの公式のドキュメントを参考にして、とりあえず設定してみました。
今回追加した設定は、acp = {...}の部分です。
|
|
しかし、この設定下でチャットを開き、対話を初めようとすると以下のエラーが出てチャットができませんでした。
|
|
CodeCompanionのログである、$HOME/.local/state/nvim/codecompanion.logを見ても同じメッセージしかなくて問題の特定ができませんでした。
ログのレベルをopts.log_level = 'TRACE'に設定して、より詳細なデバッグ情報を取得するようにしても結果は同じでした。
コードを手探る
どのへんを見れば原因が特定できそうか?
まず、ソースに対してgrepしてエラーメッセージを出している場所の当りをつけてみます。
|
|
lua/codecompanion/interactions/chat/acp/handler.lua:303が怪しく見えますね。
そこで、この行に対応する関数ACPHandler:handle_error()にブレークポイントを貼って実行してみると
、確かにその関数が呼ばれることでエラーメッセージが出力されることが分かりました。
その関数を呼び出す関数をデバッガやLSPによる定義ジャンプで探索したところ、
lua/codecompanion/acp/init.luaに実装されている関数Connection:handle_rpc_message()が
鍵となると考えました。その関数の実装を以下に示します。
|
|
この関数では、サーバー(ここではAIエージェントであるGemini CLI)からのレスポンスをLuaのテーブルにデシリアライズしてstore_rpc_response()に渡しています。
さらにこのstore_rpc_response()はレスポンスのうちエラー部分のみPromptBuilder:handle_error()に渡して結果エラーが出力がされています。
このことから、デシリアライズされたテーブルを全て見ればログに表われないメッセージを見れそうに考えました。
当りは付いたので、ロガーを入れて確かめてみる
ここまでで当りはついたので、ロガーを入れてメッセージを見てみました。
パッチを当てる時はプラグインマネージャーlazy.nvimの設定を
|
|
のように適当な場所に置いたパッチを当てる前提のコードへのパスをdir = <path>で与えると作業がしやすいです。
CodeCompanion.nvimのv18.5.0(e0780fa9fda504ffb89307cabcb6cbe1ce8eb60c) に以下のようなパッチを当ててログを見てみました。
|
|
保存されたログを見てみると、Internal errorと出力される時のレスポンスが以下のようになっていることが分りました。
|
|
このレスポンスからは、レート制限に引っかかったことが原因のように見えますが、
Google AI Studioの画面を見ても、gemini-2.5-flashでレート制限は確認されませんでした。
そのため、原因としてはうまくモデルの選択ができていないことであると考えられます。
commands.default = {}で明示的にモデル名を与える => 動く
モデル選択がうまくできないなら、Gemini CLIのコマンドラインオプションのレベルで指定すれば動くのではと考え、 以下のように設定しました。
|
|
モデル名をハードコードした柔軟性に欠けるコードですが、無事正常に動作しました。
モデル選択をスマートに
流石にモデル名のハードコードは嫌なので、最終的にチャットを開く時に選択できるように設定しました。
|
|
ここで、model_selector()の実装は以下で、vim.ui.select()によってインタラクティブにモデル選択ができるようにしました。
|
|
感想
エラーが発生した時に一部しか出力&ロギングされないため、原因が特定できなくて大変でした。 ロギングは大切さが身に染みるような気がします。
怪しい箇所の特定には前に行なったデバッガの設定がとても約に立ちました。