💬
GitHub Copilotの補完候補をNode.jsプログラムで取得する
CopilotForXcodeを読んでいたらやり方が分かったのでメモ
実行方法
$ git clone https://github.com/github/copilot.vim
$ echo "console.lo" > sample.ts
$ node getCompletionsCycling.mjs ./sample.ts
Completions: {
completions: [
{
uuid: '3dcce22b-5656-46a3-bbe8-d204ad1c5259',
text: 'console.log("Hello World");\n',
range: [Object],
displayText: 'g("Hello World");\n',
position: [Object],
docVersion: 0
},
{
uuid: '94015891-20a7-4e84-a3b7-6ce0a44b5285',
text: 'console.log("hello world");\n',
range: [Object],
displayText: 'g("hello world");\n',
position: [Object],
docVersion: 0
}
]
}
実装
getCompletionsCycling.mjs
解説
親プログラムからnode copilot.vim/dist/agent.js
で実行した子プロセスの標準入出力にJSON-RPC形式のデータを送ることで補完情報を取得する
const params = {
jsonrpc: "2.0",
id: 4,
method: "getCompletions",
params: {
doc: {
uri: "file:///hoge/sample.ts",
version: 1,
position: { line: 2, character: 2 },
},
},
}
const dataString = JSON.stringify(params);
const contentLength = Buffer.byteLength(dataString, "utf8");
server.stdin.write(`Content-Length: ${contentLength}\r\n\r\n${dataString}`);
標準出力を読み取り呼び出し元のプロセスで結果を受け取る
server.stdout.on("data", (data) => {
console.log(`stdout: ${data}`);
});
copilot.vimでGitHubアカウントの認証を終えている必要がある(~/.config/github-copilot/hosts.json
にアクセストークンが保存されている)
Language Server Protocolの仕様とGitHub Copilot独自の仕様がある
この実装では、以下の順に呼んでいる
- LSP: initialize
- LSP: textDocument/didOpen
- Copilot: getCompletionsCycling
他にCopilotで使えるmethodはここで分かる。内部通信の認証やエディタから使うmethodが用意されてる
sendRequest()
とawait sendRequest()
の違いはプロセス間通信の応答待ちを必要とするかどうか
参考
python - How to invoke Github Copilot programmatically? - Stack Overflowに参考コードをあげている人がいたので真似した
Discussion