「Recline」で使われている VSCode Extension API の「Language Model API」の公式情報： API の使い方など

## はじめに
Cline の派生版の 1つである以下の「Recline」で使われている、という話を見かけた『VS Code Extension API の「Language Model API」』の話です。

●julesmons/recline: Recline: The autonomous AI assistant that seamlessly integrates with your CLI and editor to create, edit and run; redefining how you code.
 https://github.com/julesmons/recline

![2025-01-14_23-12-20.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/50303011-0c04-ba04-ba14-4189f441c30c.jpeg)

X の以下のポストで少し書いていたものです。

https://x.com/youtoy/status/1879137075934716188

※ レートリミットの部分の話、例えば「for simulation testing」という記載がありつつ内部で呼び出してる言語モデルについて書いてるところ（Internally, VS Code uses a dedicated non-production language model のところ）が、API絡みの話になるのかよく読み取れない...（この API の仕様理解・英語力とかが足りてない感じが...）

## 情報を見ていく
今回、主にこの API の使い方に関する部分を見ていきます。

### Language Model API に関する公式ページ
まずは Language Model API について、公式のページを掲載してみます。

●Language Model API | Visual Studio Code Extension API
 https://code.visualstudio.com/api/extension-guides/language-model

![2025-01-14_23-12-20.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/74ac37ae-e3de-2c35-a710-774a30519610.jpeg)

### 【少し寄り道】「Recline」で使われているか確認してみる
API の使い方を見ていく前に、少し寄り道です。

「Recline」で使われているという情報を見かけた件について、実際に Recline の GitHub のリポジトリを見て確認してみました。

https://x.com/youtoy/status/1879171000304337216

ここで検索キーにしていたのは、VSCode Extension API の「Language Model API」の公式ページで、以下に書かれている「`vscode.LanguageModelChatMessage.User()`」です。

![2025-01-14_23-20-10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/6bf6329d-4bde-fadf-e591-d42b7bb9e95f.jpeg)

リポジトリに対して検索をかけた際の結果では、こんな感じでした。

![2025-01-14_23-19-03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/54774956-fdb0-5a46-8d73-37006ecfd28b.jpeg)

### Language Model API の情報をさらに見ていく
Language Model API の仕様を、少し見てみます。

#### プロンプトまわり
現時点でシステムメッセージは未対応で、「ユーザー」と「アシスタント」のみに対応しているようです。

![スクリーンショット 2025-01-14 233316.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/9e901587-bee2-d6e3-e25c-4b783ea7177d.png)

そして、以下の2種類のアプローチについて書かれています。

![スクリーンショット 2025-01-14 233607.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/a251a6a8-2db9-a0f9-7395-420c04478fa5.png)

1つ目のほうは、上でも書いた「vscode.LanguageModelChatMessage.User()」でも使われている「LanguageModelChatMessage」です。コードサンプルでは、以下のような使われ方になっています。

```javascript
const craftedPrompt = [
  vscode.LanguageModelChatMessage.User(
    'You are a cat! Think carefully and step by step like a cat would. Your job is to explain computer science concepts in the funny manner of a cat, using cat metaphors. Always start your response by stating what concept you are explaining. Always include code samples.'
  ),
  vscode.LanguageModelChatMessage.User('I want to understand recursion')
];
```

#### モデル関連
以下の部分では、モデルに関する内容が書いてあります。

![スクリーンショット 2025-01-14 233948.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/e761805f-8ca3-c166-bbd3-b7cdfb86a31c.jpeg)

記事執筆時点では、指定できるモデルとして以下が列挙されていました。

- gpt-4o
- gpt-4o-mini
- o1
- o1-mini
- claude-3.5-sonnet

また、以下のような指定もできるようです（）。

```javascript
const models = await vscode.lm.selectChatModels({
  vendor: 'copilot'
});

// No models available
if (models.length === 0) {
  // TODO: handle the case when no models are available
}
```

この後に出てくるサンプルコードだと、モデルまで指定した使い方も出てきていました。

```javascript
vscode.commands.registerTextEditorCommand(
  'cat.namesInEditor',
  async (textEditor: vscode.TextEditor) => {
    // Replace all variables in active editor with cat names and words

    const [model] = await vscode.lm.selectChatModels({
      vendor: 'copilot',
      family: 'gpt-4o'
    });
    let chatResponse: vscode.LanguageModelChatResponse | undefined;

    ...
```

細かなところは 以下の API仕様も見てみると良さそう、という感じでした。

- https://code.visualstudio.com/api/references/vscode-api#lm.selectChatModels
- https://code.visualstudio.com/api/references/vscode-api#lm.selectChatModels

#### エラー関連
その後のところでは、エラー周りの話も出てきていました。

以下のサンプルが掲載されていますが、コメントの部分でエラーの原因になりうるものが例示されていたりもします。

```javascript
try {
  const [model] = await vscode.lm.selectChatModels({ vendor: 'copilot', family: 'gpt-4o' });
  const request = model.sendRequest(craftedPrompt, {}, token);
} catch (err) {
  // Making the chat request might fail because
  // - model does not exist
  // - user consent not given
  // - quota limits were exceeded
  if (err instanceof vscode.LanguageModelError) {
    console.log(err.message, err.code, err.cause);
    if (err.cause instanceof Error && err.cause.message.includes('off_topic')) {
      stream.markdown(
        vscode.l10n.t("I'm sorry, I can only explain computer science concepts.")
      );
    }
  } else {
    // add other error handling logic
    throw err;
  }
}
```

### 別ページの記載
先ほどは、以下の赤線を引いた「Language Model」というページを見ていました。

![スクリーンショット 2025-01-15 000255.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/ba33deb7-6a3c-5302-b88f-bb6c42ab8171.png)

さらに上記の赤矢印で示したチュートリアルや Tools（LanguageModelTool API）に関するページもあるようです。

●Tutorial: Generate AI-powered code annotations by using the Language Model API | Visual Studio Code Extension API
 https://code.visualstudio.com/api/extension-guides/language-model-tutorial

●LanguageModelTool API | Visual Studio Code Extension API
 https://code.visualstudio.com/api/extension-guides/tools

#### Tools（LanguageModelTool API）のほうを少しだけ見てみる
Tools（LanguageModelTool API）に関するページのほうを少しだけ見てみます。

使い方の最初の部分は以下のとおりです。

![スクリーンショット 2025-01-15 000717.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/0812f1f0-d881-6624-8365-d160dd438334.png)

上記の中の「`tool.tags.includes('chat-tools-sample')`」に関わる部分は、この後に例が出てきます。

具体的には以下の部分です。

```json
"contributes": {
    "languageModelTools": [
        {
            "name": "chat-tools-sample_tabCount",
            "tags": [
                "editors",
                "chat-tools-sample"
            ],
            "toolReferenceName": "tabCount",
            "displayName": "Tab Count",
            "modelDescription": "The number of active tabs in a tab group",
            "icon": "$(files)",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "tabGroup": {
                        "type": "number",
                        "description": "The index of the tab group to check. This is optional- if not specified, the active tab group will be checked.",
                        "default": 0
                    }
                }
            }
        }
    ]
}
```

このように出力形式を指定する仕組みも、OpenAI・Claude の API のように扱うことができるようです。

## 【追記】「Language Model API」を雑に試してみた

今まで VS Code の拡張機能作成はやったことがなかったのですが、以下の公式手順で超シンプルなサンプルを作ってみて、その後、「Language Model API」を使った拡張機能からの GitHub Copilot のレスポンス取得をやってみました。

### 公式の手順

●Your First Extension | Visual Studio Code Extension API
　https://code.visualstudio.com/api/get-started/your-first-extension

### API のレスポンスが取得できたもの

https://x.com/youtoy/status/1879571585235132804