Continueサーバーをポートを指定して起動する

https://marketplace.visualstudio.com/items?itemName=Continue.continue

[Continue](https://continue.dev/)はVS Codeの拡張で、多様なLLMと連携する機能を提供しています。
ユーザーはコードをハイライトし、自然言語でLLMに質問をしたり、コードの編集を指示したりできます。外部サービスからコードをコピペする手間が省け、開発環境内で直接LLMを操作できるようになります。

要するに、GitHub Copilotと似たような機能を持っていますが、ContinueはOpenAI APIを用いることが特徴です。[llama.cpp](https://github.com/ggerganov/llama.cpp)などを利用して、OpenAI APIと互換性のあるサーバーをローカルに構築し、それと連携することが可能です（もちろん、オリジナルのOpenAI GPT-4/GPT-3も使用可能です）。

## Continueを試したい！→動かなかった

外部サービスに頼らずにAIを活用したプログラミング支援を受けられる点に魅力を感じて、Windows環境で試してみましたが、うまく動きませんでした。

ドキュメントの[トラブルシューティング](https://continue.dev/docs/troubleshooting)を参考にしながら調べていると、VS Codeの開発者コンソールに関連しそうなエラーを見つけました。

```
[Extension Host] ---- Starting Continue server ----
[Extension Host] Continue server started

(中略)

[Extension Host] stderr: Task exception was never retrieved
future: <Task finished name='Task-1' coro=<Server.serve() done, defined at uvicorn\server.py:61> exception=SystemExit(1)>
Traceback (most recent call last):
  File "uvicorn\server.py", line 159, in startup
  File "asyncio\base_events.py", line 1525, in create_server
PermissionError: [Errno 13] error while attempting to bind on address ('127.0.0.1', 65432): �A�N�Z�X���ŋւ���ꂽ���@�Ń\�P�b�g�ɃA�N�Z�X���悤�Ƃ��܂����B

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "server\continuedev\server\main.py", line 125, in run_server
  File "uvicorn\server.py", line 59, in run
  File "nest_asyncio.py", line 35, in run
  File "nest_asyncio.py", line 84, in run_until_complete
  File "nest_asyncio.py", line 120, in _run_once
  File "asyncio\events.py", line 80, in _run
  File "asyncio\tasks.py", line 360, in __wakeup
  File "nest_asyncio.py", line 196, in step
  File "asyncio\tasks.py", line 277, in __step
  File "uvicorn\server.py", line 76, in serve
  File "uvicorn\server.py", line 169, in startup
SystemExit: 1
```

`PermissionError: [Errno 13] error while attempting to bind on address ('127.0.0.1', 65432)`と表示されており、65432番のTCPポートにバインドしようとして失敗しているようです。

TCPポートの利用状況を確認したところ、私の環境では65432番ポートを含む一連のポートが既に予約されていることがわかりました。これが原因の可能性が高そうです。

```shell-session
C:\Users\miy4\> netsh int ipv4 show excludedportrange tcp
プロトコル tcp ポート除外範囲

開始ポート    終了ポート
----------    --------
     (中略)
     65389       65488

* - 管理されている除外ポート。
```

## Continueサーバーのポートを変更する

VS CodeにContinueをインストールすると、VS Codeを起動する度にContinueサーバーが自動的に動作するようになります。このサーバーは本拡張の主要な機能を担っており、VS CodeのGUIと連携しています。

そのため、サーバーが稼働しない場合、Continueは機能しないようです。65432番ポートが使用できないため、別のポートでContinueサーバーを動かす方法を調査しました。

私が確認したContinue 0.7.10の時点では、サーバーを手動で起動する必要があるようです。
以下はRyeを使った場合の例です:

```shell-session
C:\> rye init continuesrv
C:\> cd continuesrv
C:\continuesrv\> rye pin 3.11
```

`continuesrv`という名前でプロジェクトを作成。ここではPython 3.11をピン留めしていますが、3.8.1以上、4.0未満のものをお好みで使います。

```shell-session
C:\continuesrv\> vim pyproject.toml
```

`pyproject.toml`を編集して、`requires-python = ">=3.8.1, <4.0.0"`と変更します。  
[`continuedev`モジュール](https://pypi.org/project/continuedev/)がPython 3.8.1以上、4.0未満を求めているので、合わせています。

```shell-session
C:\continuesrv\> rye add continuedev
C:\continuesrv\> rye sync
C:\continuesrv\> rye run python -m continuedev.server.main -p 23456
```

`continuedev`と依存するモジュールを導入したら、Continueサーバーを起動。ここでは23456番ポートを指定しています。

:::note warn
ビルド済のバイナリは使えません
PyPIで提供している`continuedev`モジュールとは別に、Continueサーバーはビルド済のバイナリの形式も提供されています[^1]。こちらはコマンドラインのインターフェースが違うようで、ポートを指定するオプションがありません。導入は簡単なのですが、今回の目的では使えないようです。
:::

[^1]: https://continue.dev/docs/walkthroughs/manually-run-continue#download-the-server-binary

## ContinueサーバーのURLを変更する

無事Continueサーバーが起動したら、変更したサーバーを使うよう、VS Codeの設定も変更します。VS Codeを再起動し、Continueが利用できることを確認しました！

```json:settings.json
{
    // 中略
    "continue.serverUrl": "http://localhost:23456",
}
```