chat-customizations-editor について
chat-customizations-editor は、VS Code の AI カスタマイズ管理エディターを保守するための開発スキルです。チャットカスタマイズの機能やテストを変更する開発者向けに、保存元、ハーネス別の絞り込み、拡張機能プロバイダー、フィクスチャ、レイアウト調査を扱います。
主な機能
- 01プロンプト、MCP サーバー、プラグインなどを管理
- 02ワークスペース・ユーザー・拡張機能・プラグインの保存元に対応
- 03Local、Copilot CLI、Claude のハーネスで絞り込み
- 04拡張機能のカスタマイズプロバイダー連携を説明
- 05コンポーネントフィクスチャとレイアウト調査の手引き
活用シーン
- 01カスタマイズ管理画面のセクションやリストを変更
- 02拡張機能が提供するカスタマイズ項目を統合
- 03MCP Servers タブの UI とレイアウトを確認
- 04実製品で管理画面のレイアウト問題を調査
MCP 対応
管理エディターには、ワークスペースおよびユーザーの MCP サーバーを扱う MCP Servers セクションがあります。関連するコンポーネントフィクスチャでスクリーンショット検証を行う手順も記載されています。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ microsoft/ vscode --skill chat-customizations-editorインストール後、Claude Code で/chat-customizations-editorを入力して読み込まれたか確認します。
詳細
チャットカスタマイズエディター
ワークスペース、ユーザー、拡張機能、プラグインの各ストレージにある AI カスタマイズ項目を、分割ビューの管理ペインで管理します。ハーネス(Local、Copilot CLI、Claude)によるフィルタリングに対応しています。
仕様
src/vs/sessions/AI_CUSTOMIZATIONS.md — 所有権とインターフェイスの契約については、このファイルを参照してください。契約が変更された場合にのみ更新し、動作やリグレッションは対象を絞ったテストで扱ってください。
主要なフォルダー
| フォルダー | 内容 |
|---|---|
src/vs/workbench/contrib/chat/common/ | ICustomizationHarnessService、ISectionOverride、ICustomizationItemProvider — 共通インターフェイス |
src/vs/workbench/contrib/chat/browser/aiCustomization/ | 管理エディター、リストウィジェット(プロンプト、MCP、プラグイン)、ハーネスサービスの登録 |
src/vs/sessions/contrib/chat/browser/ | セッションウィンドウのオーバーライド(ハーネスサービス、ワークスペースサービス) |
src/vs/sessions/contrib/sessions/browser/ | セッションツリービューの件数とツールバー |
ハーネス記述子インターフェイスまたはファクトリー関数を変更する場合は、コアとセッションの両方の登録がコンパイルされることを確認してください。
主要なインターフェイス
IHarnessDescriptor— ハーネスの動作を宣言的に制御します(非表示セクション、ボタンのオーバーライド、項目プロバイダー、エージェントのゲーティング)。安定した所有権の契約については仕様を参照してください。ISectionOverride— セクションごとのボタンのカスタマイズ(コマンドの呼び出し、ルートファイルの作成、種類ラベル、ファイル拡張子)。ICustomizationItemProvider/ICustomizationItem— 拡張機能が提供するプロバイダーが項目を直接供給するための内部インターフェイス(customizationHarnessService.ts内)。これらは、提案されている拡張機能 API の型に対応しています。
原則:UI ウィジェットはすべての情報を記述子から読み取ります。ウィジェットのコードにハーネス固有の条件分岐を入れてはいけません。
拡張機能 API(chatSessionCustomizationProvider)
src/vscode-dts/vscode.proposed.chatSessionCustomizationProvider.d.ts にある提案中の API により、拡張機能はカスタマイズプロバイダーを登録できます。ICustomizationItem または ICustomizationItemProvider を変更する場合は、次の全レイヤーで変更を同期してください。
| レイヤー | ファイル | 型 |
|---|---|---|
| 拡張機能 API | vscode.proposed.chatSessionCustomizationProvider.d.ts | ChatSessionCustomizationItem |
| IPC DTO | extHost.protocol.ts | IChatSessionCustomizationItemDto |
| ExtHost のマッピング | extHostChatAgents2.ts | $provideChatSessionCustomizations() |
| MainThread のマッピング | mainThreadChatAgents2.ts | provideChatSessionCustomizations コールバック |
| 内部インターフェイス | customizationHarnessService.ts | ICustomizationItem |
ICustomizationItem にフィールドを追加する場合は、5 つすべてのレイヤーを更新してください。提案中の API の .d.ts は追加のみ可能です(新しいオプションのフィールドは後方互換性があり、バージョンを上げる必要はありません)。
テスト
コンポーネントエクスプローラーのフィクスチャ(component-fixtures スキルを参照):src/vs/workbench/test/browser/componentFixtures/ にある aiCustomizationListWidget.fixture.ts と aiCustomizationManagementEditor.fixture.ts。
管理セクションでは、エディターで共有されているコンテンツパネルのサーフェスと、共通のツリー/リストのプリミティブを再利用する必要があります。レジストリから追加されたセクションは、セクション固有の近似表現を導入するのではなく、隣接するセクションと背景、枠線、インセット、タイトル/検索欄の配置、行の状態、グループヘッダーを一致させてください。
特定のタブのスクリーンショットを撮る
管理エディターのフィクスチャは、任意のタブを表示するためのselectedSectionオプションをサポートしています。各タブには、defineThemedFixtureGroupによってDark/Lightのバリエーションが自動生成されます。
利用可能なフィクスチャ ID(mcp_component-exp_screenshotで使用):
| フィクスチャ ID のパターン | 表示されるタブ |
|---|---|
chat/aiCustomizations/aiCustomizationManagementEditor/AgentsTab/{Dark,Light} | エージェント |
chat/aiCustomizations/aiCustomizationManagementEditor/SkillsTab/{Dark,Light} | スキル |
chat/aiCustomizations/aiCustomizationManagementEditor/InstructionsTab/{Dark,Light} | 指示 |
chat/aiCustomizations/aiCustomizationManagementEditor/HooksTab/{Dark,Light} | フック |
chat/aiCustomizations/aiCustomizationManagementEditor/PromptsTab/{Dark,Light} | プロンプト |
chat/aiCustomizations/aiCustomizationManagementEditor/McpServersTab/{Dark,Light} | MCP サーバー |
chat/aiCustomizations/aiCustomizationManagementEditor/PluginsTab/{Dark,Light} | プラグイン |
chat/aiCustomizations/aiCustomizationManagementEditor/CanvasesTab/{Dark,Light} | 拡張機能の親、Canvas の子、親のみの有効化を含むソースセクション |
chat/aiCustomizations/aiCustomizationManagementEditor/LocalHarness/{Dark,Light} | デフォルト(エージェント、ローカルハーネス) |
chat/aiCustomizations/aiCustomizationManagementEditor/CliHarness/{Dark,Light} | デフォルト(エージェント、CLI ハーネス) |
chat/aiCustomizations/aiCustomizationManagementEditor/ClaudeHarness/{Dark,Light} | デフォルト(エージェント、Claude ハーネス) |
chat/aiCustomizations/aiCustomizationManagementEditor/Sessions/{Dark,Light} | セッションウィンドウのバリエーション |
新しいタブのフィクスチャを追加する:aiCustomizationManagementEditor.fixture.tsのdefineThemedFixtureGroupにバリエーションを追加します:
MyNewTab: defineComponentFixture({
labels: { kind: 'screenshot' },
render: ctx => renderEditor(ctx, {
harness: CustomizationHarness.VSCode,
selectedSection: AICustomizationManagementSection.MySection,
}),
}),
selectedSectionはsetInputの後にeditor.selectSectionById()を呼び出し、指定されたタブに移動して再レイアウトします。
テストデータの設定
各カスタマイズタイプには、createMockPromptsService内にそれぞれのモックパスが必要です。
- エージェント —
getCustomAgents()がエージェントオブジェクトを返します - スキル —
findAgentSkills()がIAgentSkill[]を返します - プロンプト —
getPromptSlashCommands()がIChatPromptSlashCommand[]を返します - 指示/フック —
PromptsTypeでフィルターしたlistPromptFiles() - MCP サーバー —
IMcpWorkbenchServiceモックに渡されるmcpWorkspaceServers/mcpUserServers配列 - プラグイン —
IPluginMarketplaceService.installedPluginsとIAgentPluginService.pluginsのオブザーバブル
すべてのテストデータは、allFiles(プロンプトベースの項目)とmcpWorkspace/UserServers配列に格納されています。スクロールが発生するよう、各カテゴリに十分な数の項目(8件以上)を追加してください。
組み込みのグループ化を試す
リストウィジェットは、デフォルトのチャット拡張機能の項目を「組み込み」ヘッダーの下に再グループ化します。フィクスチャでこれを動作させるには、次の3点を設定する必要があります。
- ハーネス記述子の表示ソースに
BUILTIN_STORAGEを含める IProductService.defaultChatAgent.chatExtensionIdをモックする(例:'GitHub.copilot-chat')- モック項目に、その ID と一致する
extensionId/extensionDisplayNameで拡張機能の出所を設定する
この3点が揃っていないと、組み込みのグループ化は何も通知されずに実行されず、フィクスチャにはフラットなリストだけが表示されます。
エディターのコントリビューションサービスのモック
管理エディターには CodeEditorWidget が埋め込まれています。Electron 側のエディターコントリビューション(例:AgentFeedbackEditorWidgetContribution)は自動的にインスタンス化され、注入されるサービスが登録されていないとクラッシュします。フィクスチャでは、少なくとも以下をモックする必要があります。
IAgentFeedbackService—onDidChangeFeedback、onDidChangeNavigation、onDidAddFeedback、onDidConvertFeedback、onDidAddReply、onDidSubmitFeedbackをEvent.Noneとする必要がありますICodeReviewService—getReviewState()/getPRReviewState()がアイドル状態のオブザーバブルを返す必要がありますIChatEditingService—editingSessionsObsを空のオブザーバブルとする必要がありますIAgentSessionsService—model.sessionsを空の配列とする必要があります
これらは vs/sessions/ からのレイヤー横断インポートです。インポート行には // eslint-disable-next-line local/code-import-patterns を使用してください。
CI の回帰ゲート
重要なフィクスチャのラベルには blocksCi: true が設定されています。component-fixtures.yml GitHub Action は、main へのすべての PR でスクリーンショットを取得し、blocks-ci ラベルが付いたフィクスチャのスクリーンショットが変更された場合は、CI ステータスチェックを失敗させます。これにより、レイアウトのリグレッションを自動的に検出できます。
現在ゲートされているフィクスチャ:LocalHarness、McpServersTab、McpServersTabNarrow、AgentsTabNarrow。新しいセクションまたはレイアウト上重要なフィクスチャを追加する場合は、blocksCi: true を追加してください。
MyFixture: defineComponentFixture({
labels: { kind: 'screenshot', blocksCi: true },
render: ctx => renderEditor(ctx, { ... }),
}),
すべてのフィクスチャに blocksCi を追加しないでください。重要なレイアウト経路(デフォルトビュー、リストとフッターを含むセクション、狭いビューポート)をカバーするものだけにしてください。ゲート対象のフィクスチャが多すぎると、CI に不要なノイズが生じます。
スクリーンショットの安定性
スクロールバーのフェード遷移によって、スクリーンショットが不安定になります。プログラムによるスクロールの約 2 秒後に、スクロールバーのクラスが visible から invisible fade に変わります。revealLastItem() またはスクロール操作を呼び出した後、フィクスチャのレンダリングプロミスが解決する前に、遷移が完了するまで待機してください。
await new Promise(resolve => setTimeout(resolve, 2400));
// Then optionally poll until .scrollbar.vertical loses the 'visible' class
ユニットテストの実行
./scripts/test.sh --grep "applyStorageSourceFilter|customizationCounts"
npm run typecheck-client && npm run valid-layers-check
sessions ウィンドウ固有のガイダンスについては、sessions スキルを参照してください。
実際の製品でレイアウトをデバッグする
コンポーネントフィクスチャはモックデータと固定サイズのコンテナーを使用します。リフローのタイミング、実際のデータ形状、または狭いウィンドウサイズが原因のレイアウトバグは、フィクスチャでは再現しないことがよくあります。ユーザーからレイアウトの崩れが報告された場合は、実際に動作している Code OSS 製品でデバッグしてください。
CDP を使って Code OSS を起動し、@playwright/cli に接続する方法については、launch スキルを参照してください。別のワークツリーですでに起動しているインスタンスとの競合を避けるには、--user-data-dir /tmp/code-oss-debug を使用してください。
カスタマイズエディターへの移動
接続後、snapshot を使って(Chat パネルのヘッダーにある)「Open Customizations」ボタンを見つけ、クリックしてください。セクションを切り替えるには、サイドバー項目はインタラクティブな参照ではないため、DOM のクリックを行う eval を使用してください。
npx @playwright/cli eval "(() => { const items = [...document.querySelectorAll('.section-list-item')]; items.find(el => el.textContent?.includes('MCP'))?.click(); })()"
ウィジェットのレイアウトを調べる
@playwright/cli eval は式を () => (...) でラップします。複数のステートメントを含むコードには IIFE を使用してください。戻り値を渡す手段として document.title を使用してください。
npx @playwright/cli eval "(() => { const w = document.querySelector('.mcp-list-widget'); \
const lc = w?.querySelector('.mcp-list-container'); \
const rows = lc?.querySelectorAll('.monaco-list-row'); \
document.title = 'DBG:rows=' + (rows?.length ?? -1) \
+ ',listH=' + (lc?.offsetHeight ?? -1) \
+ ',seStH=' + (lc?.querySelector('.monaco-scrollable-element')?.style?.height ?? '') \
+ ',wH=' + (w?.offsetHeight ?? -1); })()"
npx @playwright/cli eval "document.title" 2>&1
主な診断項目:
rows— 想定より少ない場合、list.layout()に正しいビューポートの高さが渡されていません。seStH— 空の場合、リストが適切にレイアウトされていません。listHとwH— リストコンテナーの高さは、ウィジェットの高さから検索バーとフッターの高さを引いた値になるはずです。
よくあるレイアウトの問題
| 症状 | 根本原因 | 修正方法 |
|---|---|---|
| 高さのあるコンテナー内でリストに 0~1 行しか表示されない | display:none → visible の遷移中に offsetHeight が 0 を返し、layout() が処理を中断した | DOM.getWindow(this.element).requestAnimationFrame(...) でレイアウトを遅延させる |
| バッジまたは行の内容が右端で切れる | ウィジェットのコンテナーに overflow: hidden がない | ウィジェットの CSS クラスに overflow: hidden を追加する |
| フィクスチャでは項目が表示されるが、製品では表示されない | フィクスチャでは多くのモック項目を使用しているが、実際の製品では項目が少ない | 項目数を減らしたフィクスチャのバリエーション、またはより狭いサイズ(width/height オプション)を追加する |
フィクスチャと実際の製品とのギャップ
フィクスチャは固定サイズ(デフォルトでは900×600)で多数のモック項目を表示します。次の点は検出できません。
- リフローのタイミング — 実際の製品では、
display:none → visibleの切り替え後、layout()が実行される前にリフローが完了していない可能性があります - 狭いウィンドウ — 狭いサイズのフィクスチャを追加します(例:
width: 550, height: 400) - 実際のデータ件数 — MCP サーバーが1つのユーザーと、12個のフィクスチャでは、レイアウトが大きく異なります