
2026/10/27 3:14
タイプサーバープロトコル
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
元のサマリーは簡潔であるが、Key Points に記載されているいくつかの具体的な技術詳細を欠いている。以下に、それらを組み入れながら明瞭性を維持した改善版を示す:
改善されたサマリー:
Type Server Protocol(TSP)は、Python アナリシスデータを効率的に取得するための専用の JSON-RPC スタンダードを確立し、Position、Range、URI の表現について Language Server Protocol(LSP)の慣習に従うとともに、
typeServer/ 接頭辞付きの方法を用いる。権威ある定義は typeServerProtocol.ts などのファイルに記述されており、TSP はプロトコルバージョン、スナップショット、検索パス、インポート解決、および 3 つの特定の型アナリシス(computed、declared、expected)を含む多様なクエリを支援する。アーキテクチャ上の重要な革新として、バージョン 0.4.1 で導入されたマルチ接続サポートがある;このオプションモードでは、クライアントが高負荷な同時クエリ(getComputedType または resolveImport など)に対してメイン接続をブロックせずに追加の読み取り専用接続を開くことが可能であり、メイン接続は状態変更操作と LSP ライフサイクルメッセージの独占的な所有権を保持する。接続はメインチャンネル上の JSON 制御メッセージ(open / close)を通じて管理される。TSP はマイナーな 0.x の変化であっても破壊的変更になり得る点において厳密なセマンティックバージョニングを強制し、破棄されたスナップショットには -32802、無効なパラメータには -32602 とする標準的な JSON-RPC エラーコードを利用する。結果はスナップショットのコンテキスト内でのみ有効であり、権威ある定義は tsp.json に記述されているため、TSP は高パフォーマンスと後方互換性の期待をバランスさせた堅牢な Python ツーリングの基盤を提供しており、現在は Pylance 2026.4.1 と整合している。本文
Type Server プロトコル(TSP)仕様書
Type Server プロトコル(TSP)は、型サーバーに対して Python の分析データを照会するための JSON-RPC プロトコル です。
概要とアーキテクチャ
型サーバーはワークスペースの型分析状態を保持し、以下の情報をクライアントに返答します。
- プロトコルのバージョン情報
- スナップショット(分析状態の識別子)
- Python の検索パス
- インポート解決結果
- 型クエリ結果(計算された型、宣言された型、想定される型)
データ形状と慣習
やPosition
などは、**言語サーバープロトコル(LSP)**のデータ形状と慣習を採用します。Range- URI は文字列として表現し、LSP と同等の形式を使用します。
- メソッド名はすべて
プレフィックスで始まります。typeServer/
プロトコルアティファクト
以下のファイルが権限のある定義です。
: TypeScript インターフェースとリクエストタイプを定義。typeServerProtocol.ts
: 機械可読なプロトコルモデル。tsp.json
: プロトコルモデルの JSON スキーマ。tsp.schema.json
バージョン履歴
クライアントとサーバー間の互換性チェックには、**セマンティックバージョニング(SemVer)**文字列を使用します。
- 0.x ライン: マイナー版の変更でも破壊的変更が生じる可能性があります。
- パッチ版: 同じマイナーライン内で後方互換性を維持します。
バージョン一覧
| バージョン | 変更点 |
|---|---|
| 初期のプロトコルバージョン。 |
| リクエストタイプとフィールドを追加。 |
| より複雑な型形状への変更。 |
| Type union およびスタブベースの型ペイロードへの変更。 |
| 複数接続間のネゴシエーションと コントロールリクエストの追加。 |
接続モデル
クライアントは型サーバーを起動し、以下のトランспортを通じてメイン JSON-RPC 接続で通信します。
(出力標準をプロトコルメッセージに予約)stdio- Node IPC
状態の同期フロー
型サーバーには十分なワークスペースおよびドキュメント状態を受け取る必要があります。通常は以下のような手順で行われます。
- 通常の LSP 初期化とドキュメント同期を行う。
- 同じ JSON-RPC 接続上で
リクエストを送信する。typeServer/*
オプション:追加読み取り専用接続
TSP は、メイン接続(初期化・状態管理など)とは別に、追加の読み取り専用接続をサポートします。
- 両者がネゴシエーションした場合のみ開かれます。
- メイン接続が変更可能な状態を管理し続け、追加接続で読み取り専用クエリを実行できます。
起動シーケンス
典型的なセッションは以下の順序で進みます。
- クライアントが型サーバーを起動または接続します。
- LSP の
/initialize
メッセージで共有ワークスペース状態を初期化します。initialized - クライアントは
を呼び出し、互換性を検証します。typeServer/getSupportedProtocolVersion - クライアントは
を呼び出して、最初のスナップショット識別子を入手します。typeServer/getSnapshot - 現在のスナップショットを添えて、型クエリなどを送信します。
- 型結果が無効になった場合(ファイル変更など)、サーバーは
を送信します。typeServer/snapshotChanged
マルチ接続モード
大量の型クエリやバックグラウンドワーカーなどの同時実行を最適化するためのオプション機能です。
- メイン接続:ワークスペース状態の変更を管理(書可能)。
- 追加接続:読み取り専用の TSP リクエストを実行。
- 注意: マルチ接続サポートはプロトコルの必須条件ではありませんが、大量処理時に推奨されます。
キャパビリティハンドシェイク
マルチ接続サポートは LSP
initialize のネゴシエーションで決定されます。
クライアント側の広告(Advertisement)
実験機能領域に以下の構造を返します:
{ "capabilities": { "experimental": { "typeServerMultiConnection": { "supportedTransports": ["ipc"] } } } }
サーバー側の広告
サーバーも同様の構造を
initialize レスポンスで返すことで、両方がサポートしていることを示します。
有効になる条件:
- 両側が
を広告すること。typeServerMultiConnection - 共有するトランспорт(例:
)が少なくとも 1 つ存在すること。ipc - どちらかが能力を省略したり、共通するトランспортがなければ、セッションは単一接続のままになります。
現在標準的にサポートされている追加接続トランポート種別は
です。ipc
追加接続の開通と閉鎖
ネゴシエーション後、メイン接続上で
typeServer/connection を使用してチャンネルを管理します。
チャンネル開通(Open)
クライアントが送信するリクエスト:
{ "type": "open", "kind": "ipc", "args": ["<ipc-endpoint>"] }
- 成功時:
を含む結果を返す。success: true - 失敗時:
とエラーメッセージを返す。success: false
IPC エンドポイント引数
プラットフォーム依存の形式があります。
フルダプлекс(双方向)ストリームの場合:
{ "type": "open", "kind": "ipc", "args": ["<full-duplex-ipc-endpoint>"] }
片方向エンドポイントのみ公開する場合(入力/出力ペア):
{ "type": "open", "kind": "ipc", "args": ["<input-ipc-endpoint>", "<output-ipc-endpoint>"] }
チャンネル閉鎖(Close)
クライアントが送信するリクエスト:
{ "type": "close", "kind": "ipc", "args": ["<ipc-endpoint>"] }
は開通時の形式と同じです(双方向なら 1 つ、片方向なら 2 つ)。args- サーバーは対応するチャンネルの提供を停止し、トランポートを閉じます。
許可されたトラフィック
メイン接続
すべての状態変更トラフィックを管理します。以下のメッセージのみ許されます:
- LSP の初期化およびライフサイクルメッセージ。
- ワークスペース、設定、ファイルウォッチャー、ドキュメント同期通知。
- サーバーからクライアントへのスナップショット通知。
コントロールリクエスト。typeServer/connection
追加接続(読み取り専用)
TSP 専用です。以下の制限があります。
- サーバーの状態を変更しません。
- クライアントが提供したスナップショットの結果が無効になっているようなリクエストにのみ使用できます。
- ネゴシエされた TSP バージョンに基づき、特定のリクエストのみ許可されます(後述の表参照)。
サーバー側の拒否処理: 追加接続で受け取った場合、以下のいずれかを拒否すべきです:
- LSP のトラフィック
- 状態変更通知
リクエストtypeServer/connection- ネゴシエされたバージョンに許可されていないあらゆる TSP メッセージ
バージョン別の追加接続メッセージ(TSP 0.4.1)
| メッセージ名 | 機能 |
|---|---|
| プロトコルバージョン照会 |
| スナップショット取得 |
| Python 検索パス取得 |
| インポート解決 |
| 計算された型取得 |
| 宣言された型取得 |
| 想定される型取得 |
スナップショット
スナップショットは、型サーバーの分析状態の時点ごとのビューを識別するための非負整数です。
- 型ハンドルやオブジェクトは、明示的に別のことを述べない限り、そのスナップショットで有効です。
- 分析結果が無効化されるたびに(ファイル変更、設定変更など)、サーバーはスナップショットを進める必要があります。
スナップショットルール
| 項目 | 動作 |
|---|---|
| 現在のスナップショット識別子を返します。 |
| 識別子の順序 | セッション中は減少してはいけません。 |
| 以前と新しいスナップショット識別子を報告します。 |
| 古いスナップショットの要求 | JSON-RPC エラーで失敗し、クライアントは再試行(新スナップショット取得)する必要があります。推奨エラーコード: 。 |
位置と範囲
TSP は LSP の位置慣習に従います。
- ライン番号: 0 ベース
- 文字オフセット: 0 ベースの UTF-16 コードユニット
- 範囲: 開始位置と終了位置を使用してソーススパンを識別
型サーバーが異なるエンコーディング(例:Byte Offset)で位置を保持する場合、プロトコル境界で LSP 形式への変換が必要です。不適切な変換は構文ノード情報の誤りを引き起こします。
ノード、宣言、およびハンドル
型クエリリクエスト(
getComputedType など)は、以下のいずれかでソース構造を識別します:
- ノード: URI + ソース範囲
- 宣言: シンボル定義場所と方法(AST ノードを持つ通常のもの、または合成宣言)。
特殊値 InvalidHandle
InvalidHandle- 値: -1
- 意味: 無効または利用できないハンドル。
- 扱い: クライアントとサーバーはこれを有効なオブジェクト ID ではなく、Sentinel 値として扱う必要があります。
型結果(Type Objects)
型結果は JSON シリアライズ可能なタグ付きオブジェクトです。
Discriminator(数値種別)により解釈方法が区別されます。
種別一覧
| 種別 (Discriminator) | タイプ名 | 説明 |
|---|---|---|
| BuiltIn | unknown, any, unbound, ellipsis, never など不確かな型 |
| Declared | ソースで宣言された型のベース(直接使用稀) |
| Function | def ステートメントからの関数とメソッド |
| Class | クラスとそのインスタンス |
| Union | ユニオン型 (例:) |
| Module | モジュールオブジェクト (例: の場合) |
| TypeVar | 型変数 (T, P, Ts など) |
| Overloaded | 複数の サインチャを持つ関数 |
| Synthesized | 型チェックャーによって合成された型 |
| TypeReference | 別の型の参照(重複排除、循環処理用) |
型 ID とスナップショットの関係
- 返される型オブジェクトは、そのリクエストで使用されたスナップショットのみ有効です。
- 型 ID はシリアライズされたグラフ内で
を介して参照されますが、別のレスポンス間で比較してはなりません(グローバル ID でありません)。TypeReference - 大きなまたは再帰的なグラフを避けるために
を使用します。TypeReference
プロトコル表面:メッセージ一覧
現在のプロトコルは意図的に小さく設定されています。下表にすべての TSP メッセージ、方向、パラメータ形状を示します。
| メッセージ | 方向 | パラメータ | 結果 |
|---|---|---|---|
| C→S | なし | string (semver) |
| C→S | なし | number |
| S→C | | 通知 |
| C→S | | |
| C→S | | string[] | undefined |
| C→S | | string | undefined |
| C→S | | Type | undefined |
| C→S | | Type | undefined |
| C→S | | Type | undefined |
- サーバーは統合するクライアントによって要求されるメッセージを実装し、結果形状で許可されている場所のみ
を返すべきです。undefined
型クエリの違い
3 つの型クエリリクエストは、報告される型の種類が異なります。
: コードフローから推測された型getComputedType- 例:
を絞り込みa: int
とすると、b = a + 1
はb
。int
- 例:
: ソースに明示的に記述された型getDeclaredType- 例:
の場合、def foo(a: int \| str)
はa
。int \| str
- 例:
: 周囲のコンテキストが期待する型getExpectedType- 例:
の呼び出しにおける引数の想定型はfoo(4)
。int \| str
- 例:
エラー処理
標準的な JSON-RPC エラーレスポンスを使用します。
| シチュエーション | エラーコード | ガイドライン |
|---|---|---|
| 古いスナップショット | (ServerCancelled) | クライアントは新しいスナップショットを要求して再試行できます。 |
| 無効なパラメータ | (InvalidParams) | 必要なフィールドが欠落しているか、破損しています。 |
| 内部エラー | (InternalError) | サーバーが予期せぬ失敗をしました。 |
メッセージ詳細の注意点: エラーには失敗したリクエストを特定するのに十分な情報を含める必要がありますが、ローカルシークレットや実装固有の状態を暴露してはなりません。
互換性チェックリスト
型サーバーは以下の振る舞いを検証すべきです。
はクライアントの SemVer と互換性を保つ文字列を返す。getSupportedProtocolVersion- すべてのペイロードはプロトコルアティファクトに従ってシリアライズされる。
は減少しない非負整数を返す。getSnapshot- ファイルや設定の変更がスナップショット無効化を適切に引き起こす。
- 古いスナップショットへの要求は再試行可能なエラー(-32802)で失敗する。
- 位置・範囲の変換に LSP 規格(0 ベース UTF-16)を使用する。
- インポート解決はドキュメント URI または結果なしを返す。
- 型クエリは適切な Type オブジェクトまたは
を返す。undefined - マルチ接続はネゴシエ可能なトランポートのみ広告する。
- 追加接続は許可された TSP メッセージのみ受け入れ、その他を拒否する。
最終更新情報: この仕様の最後のコンテンツ更新は Pylance 2026.4.1 と一致しています。