vercel/ai -- 導出ルール集
出典: repos/vercel/ai/ | 生成日: 2026-02-20 用途: CLAUDE.md にそのまま貼り付けて AI コンテキストとして活用
型安全性・インターフェース設計
[MUST]パッケージ境界を超えるエラー判定にはinstanceofではなくSymbol.for()ベースのマーカーパターンとstatic isInstance()型ガードを使う- 根拠: error-handling-idioms — AI SDK は 35 以上のエラークラスすべてでこのパターンを採用し、パッケージバージョン不一致問題を構造的に解決している
[MUST]判別共用体の判別フィールドはリテラル型の union で定義する —string全体を許容すると型絞り込みが機能しない- 根拠: type-system-patterns —
LanguageModelV3StreamPartはtypeフィールドに 15 以上のリテラル型を使い、switch/case で型安全に分岐している
- 根拠: type-system-patterns —
[SHOULD]バージョン付きインターフェースにはリテラル型のspecificationVersionフィールドを含め、discriminated union として扱えるようにする- 根拠: architecture, design-philosophy — v2/v3 をリテラル型で区別し、Proxy ベースのアダプタで透過的に変換。コアは最新バージョンのみを扱う設計
[SHOULD]複数のスキーマライブラリをサポートする場合、union 型 + 条件付き推論型(InferSchema<T>)で統一的な抽象層を作る- 根拠: schema-validation-patterns —
FlexibleSchemaが Zod 3/4、Standard Schema、JSON Schema を統合し、一貫した型推論を提供
- 根拠: schema-validation-patterns —
[SHOULD]テンプレートリテラル型で文字列 ID のフォーマットをコンパイル時に検証する- 根拠: type-system-patterns —
ProviderRegistryProviderが${KEY}${SEPARATOR}${modelId}形式を型レベルで強制
- 根拠: type-system-patterns —
[SHOULD]排他的パラメータはnever型で型レベルの排他制約を設け、加えてランタイムバリデーションで多層防御する- 根拠: api-design-practices —
Prompt型がprompt?: never/messages?: neverの union で排他性を表現
- 根拠: api-design-practices —
[SHOULD]ジェネリクスの推論ソースを制御するためにNoInfer<T>を使い、意図しないパラメータから型が推論されることを防ぐ- 根拠: api-design-practices —
generateTextのtoolChoice,activeTools等がNoInfer<TOOLS>を使い、toolsのみを推論元にしている
- 根拠: api-design-practices —
[SHOULD]列挙型のモデル ID にはリテラルユニオン +(string & {})を使い、IDE 補完と将来の拡張性を両立する- 根拠: adapter-implementation-patterns — 30+ プロバイダーの全モデル ID 型がこのパターンを採用
エラーハンドリング・バリデーション
[MUST]外部入力の JSON パースにはプロトタイプ汚染対策済みのラッパーを使用し、JSON.parseの直接呼び出しを禁止する- 根拠: design-philosophy, schema-validation-patterns —
secureJsonParseで__proto__/constructor.prototypeを検出・排除し、コードベース全体でJSON.parse直接使用を排除
- 根拠: design-philosophy, schema-validation-patterns —
[MUST]catch ブロックでエラーをラップする際は、既知のエラー型をisInstanceで判定し再スローしてから、未知のエラーのみをラップする- 根拠: error-handling-idioms —
parseJSON,download等で一貫して使われ、エラーの二重ラップを防止
- 根拠: error-handling-idioms —
[SHOULD]失敗が想定内の操作(パース・バリデーション等)には、例外を投げる版と Result 型を返す safe 版を対で提供する- 根拠: error-handling-idioms, schema-validation-patterns —
parseJSON/safeParseJSON、validateTypes/safeValidateTypesが対で存在
- 根拠: error-handling-idioms, schema-validation-patterns —
[SHOULD]エラークラスのコンストラクタは名前付きオブジェクト引数を取り、ドメイン固有のコンテキスト情報をreadonlyプロパティで公開する- 根拠: error-handling-idioms —
APICallErrorのurl,statusCode,isRetryable等により、catch 側がプログラム的にリトライ等の制御を行える
- 根拠: error-handling-idioms —
[SHOULD]外部 API レスポンスの Zod スキーマではフィールドに.nullish()を使い、必要最小限のフィールドだけをスキーマに含める- 根拠: adapter-implementation-patterns — 30+ プロバイダーが全てこのパターンを採用し、API 仕様変更への耐性を最大化
[SHOULD]不完全な入力(LLM 出力等)に対してはパース → 自動修復 → 外部修復の多段階パイプラインを設ける- 根拠: schema-validation-patterns —
fixJson(ルールベース修復) →repairText(外部コールバック修復)の多段階リカバリーを実装
- 根拠: schema-validation-patterns —
[AVOID]JSON.parseをライブラリコード内で直接呼び出す — セキュアパーサーまたはsafeParseJSONを経由すべき- 根拠: error-handling-idioms — AI SDK の実行コードでは
JSON.parseの直接呼び出しはゼロ
- 根拠: error-handling-idioms — AI SDK の実行コードでは
ストリーミング・非同期処理
[MUST]ReadableStream に AsyncIterable を実装する際はpipeThrough(new TransformStream())で新しいストリームを生成してからイテレータを付与する — 元のストリームに直接 reader を取得するとロック競合が発生する- 根拠: streaming-and-async-patterns —
createAsyncIterableStreamで必ず pipeThrough を挟んでいる
- 根拠: streaming-and-async-patterns —
[MUST]ストリームの AsyncIterator 実装ではreturn()とthrow()で必ずリーダーの cancel と releaseLock を呼ぶ- 根拠: streaming-and-async-patterns —
for await...ofの break やエラーでリソースリークが発生する
- 根拠: streaming-and-async-patterns —
[MUST]TransformStream のflush()でストリーム完了時のファイナライゼーション(Promise resolve、コールバック呼び出し)を実行する- 根拠: streaming-and-async-patterns — flush がないと最終状態の通知が漏れる
[SHOULD]ストリームの最終結果を Promise で公開する場合は Lazy Promise(アクセス時に構築)を使い、未アクセス時の unhandled rejection を防ぐ- 根拠: streaming-and-async-patterns, performance-techniques —
DelayedPromiseで Promise 生成を.promiseアクセスまで遅延
- 根拠: streaming-and-async-patterns, performance-techniques —
[SHOULD]複数の AbortSignal を扱う場合は新しい AbortController に集約し、任意のソースからのキャンセルを統一的にハンドリングする- 根拠: streaming-and-async-patterns —
mergeAbortSignalsで複数シグナルを一つに統合
- 根拠: streaming-and-async-patterns —
[SHOULD]ストリームの変換は単一責務の TransformStream を.pipeThrough()で直列に接続し、各変換を独立にテスト・差し替え可能にする- 根拠: streaming-and-async-patterns —
stream.pipeThrough(outputTransform).pipeThrough(eventProcessor)チェーン
- 根拠: streaming-and-async-patterns —
[AVOID]ストリームを生成して消費しないまま放置する — バックプレッシャーによりプロデューサー側が停止し、Promise が永久に resolve しない- 根拠: streaming-and-async-patterns — get アクセス時に
consumeStream()を呼ぶ防御策が入っている
- 根拠: streaming-and-async-patterns — get アクセス時に
API 設計・拡張性
[MUST]公開 API に不安定な機能を追加する際は、命名規約によるプレフィックス(experimental_)で安定度を明示し、安定化時にはプレフィックスなし版を追加して旧名を@deprecatedにする- 根拠: api-design-practices, extensibility-mechanisms — 全 experimental_ API がこのパターンに従い、ポリシーとして明文化
[SHOULD]プラグイン固有の拡張パラメータは、コアインターフェースに名前空間付きの汎用フィールド(Record<string, JSONObject>型)を設け、プラグイン側でスキーマ検証する- 根拠: design-philosophy, architecture —
providerOptionsでプロバイダー名をキーとした名前空間により衝突を防ぎ、各プロバイダーが Zod スキーマで検証
- 根拠: design-philosophy, architecture —
[SHOULD]同一ドメインの同期/ストリーミング API はオプション構造と結果型のプロパティ名を統一し、モード切り替え時の学習コストを最小化する- 根拠: api-design-practices —
generateTextとstreamTextがCallSettings & Promptを共有し、結果型も統一
- 根拠: api-design-practices —
[SHOULD]ユーザーに直接呼ばれるべきでない低レベルメソッドには、不自然なプレフィクス(do-、_、internal-等)を付けて誤用を抑止する- 根拠: design-philosophy, abstraction-patterns —
doGenerate/doStreamのdoプレフィクスで内部 API であることを命名から明確にしている
- 根拠: design-philosophy, abstraction-patterns —
[SHOULD]ミドルウェアの戻り値型を元のモデルインターフェースと同一に保ち、ラップが透過的に動作するようにする- 根拠: extensibility-mechanisms —
wrapLanguageModelはLanguageModelV3を返すため、利用側はミドルウェアの有無を意識しない
- 根拠: extensibility-mechanisms —
[SHOULD]サポートしない機能は例外ではなく警告で報告し、処理を続行する(グレースフルデグラデーション)。ただし、未サポートのモデルタイプは専用エラー(NoSuchModelError)を throw する- 根拠: architecture —
warnings配列パターンでプロバイダー間の機能差を透過的に伝達。abstraction-patterns — 未サポート機能のサイレント無視は禁止
- 根拠: architecture —
[SHOULD]高レベル API 関数には_internalパラメータで非決定的要素(ID 生成、現在時刻等)を注入できる接合点を設け、テスト容易性を確保する- 根拠: api-design-practices —
generateText,generateObject,streamTextが全て_internalパラメータを持つ
- 根拠: api-design-practices —
[SHOULD]仕様インターフェースの戻り値型はPromiseではなくPromiseLikeにして、実装側の自由度を最大化する- 根拠: design-philosophy —
LanguageModelV3の全メソッドがPromiseLikeを返し、カスタム thenable も受け入れる
- 根拠: design-philosophy —
パフォーマンス・バンドル
[MUST]ライブラリの全パッケージのpackage.jsonに"sideEffects": falseを設定して tree-shaking を有効化する- 根拠: performance-techniques — 全パッケージに一貫して
"sideEffects": falseを設定
- 根拠: performance-techniques — 全パッケージに一貫して
[MUST]ストリーミングレスポンスを Node.js のServerResponseに書き込む際は、write()の戻り値を確認し、falseならdrainイベントを待つ- 根拠: performance-techniques — バックプレッシャー制御がないとメモリが無制限に消費される
[SHOULD]バンドルサイズを CI パイプラインで定量チェックし、閾値超過でビルドを失敗させる- 根拠: build-and-tooling, ci-cd — esbuild で minify + tree-shake 後のサイズを Node/Browser 両方で検証し、560KB 上限を強制
[SHOULD]Edge Runtime / ブラウザ / Node.js の全環境で動作させるために、コアロジックでは Web 標準 API を使い、Node.js 固有 API は分離モジュールに閉じ込める- 根拠: performance-techniques —
create-text-stream-response.ts(Web 標準)とpipe-text-stream-to-response.ts(Node.js 固有)が並行存在
- 根拠: performance-techniques —
[SHOULD]大規模レスポンスのダウンロードにはサイズ上限を設けて、fetch().arrayBuffer()の 2 倍メモリオーバーヘッドによる OOM を防止する- 根拠: performance-techniques —
readResponseWithSizeLimitが Content-Length 早期拒否とストリーミング中サイズチェックの 2 段階で防止
- 根拠: performance-techniques —
[SHOULD]スキーマの JSON Schema 変換は遅延評価(lazySchema)し、実際に必要になるまで計算コストを発生させない- 根拠: schema-validation-patterns — プロバイダーパッケージ全体で
lazySchemaが広く使用されている
- 根拠: schema-validation-patterns — プロバイダーパッケージ全体で
テスト
[MUST]マルチランタイムをサポートする SDK では、同一テストスイートを各ターゲットランタイム環境で実行する設定を用意する- 根拠: testing-practices — 全 40+ パッケージで
vitest.edge.config.jsとvitest.node.config.jsを分離
- 根拠: testing-practices — 全 40+ パッケージで
[SHOULD]ジェネリクスを多用するライブラリでは*.test-d.tsファイルで型推論の正しさを独立して検証する- 根拠: testing-practices — 13 の
test-d.tsファイルでexpectTypeOfを使い、型回帰を検出
- 根拠: testing-practices — 13 の
[SHOULD]モノレポのテストユーティリティは独立パッケージとして切り出し、テストランナーとの統合は別エントリポイントで提供する- 根拠: testing-practices —
@ai-sdk/test-serverはコア(MSW ラッパー)とwith-vitest(ライフサイクル統合)を分離
- 根拠: testing-practices —
[SHOULD]テストフィクスチャは実際の API レスポンスをキャプチャして作成し、手書きで模倣しない- 根拠: testing-practices —
saveRawChunksヘルパーとcontributing/testing.mdがキャプチャワークフローを標準化
- 根拠: testing-practices —
モノレポ・ビルド
[MUST]モノレポのパッケージ間依存は DAG(有向非巡回グラフ)とし、tsconfig の references や package.json の dependencies で方向制約を表現する- 根拠: project-structure, architecture —
@ai-sdk/providerの tsconfig references が空配列で最下層を保証、循環依存を型レベルで防止
- 根拠: project-structure, architecture —
[MUST]モノレポ内のパッケージ間依存はworkspace:*で統一し、パブリッシュ時にツール(Changesets 等)が実バージョンに置き換える- 根拠: dependency-management — 全 53 パッケージが
workspace:*で内部依存を宣言
- 根拠: dependency-management — 全 53 パッケージが
[MUST]同一カテゴリのパッケージ(プロバイダー等)は scripts, exports, dependencies のパターンを統一する- 根拠: project-structure — 30+ プロバイダーが同一の package.json 構造を持ち、テンプレート化を実現
[SHOULD]モノレポ内の共有設定(tsconfig, eslint)は private ワークスペースパッケージとして配布し、各パッケージからworkspace:*で参照する- 根拠: project-structure, build-and-tooling —
@vercel/ai-tsconfigが 3 つのプリセットを提供し、50+ パッケージが extends で参照
- 根拠: project-structure, build-and-tooling —
[SHOULD]パッケージの公開 API、内部 API、テストユーティリティはexportsフィールドのサブパス(.,./internal,./test)で分離する- 根拠: project-structure — セマンティックバージョニングの対象を公開 API に限定しつつ、パッケージ間の内部共有を可能に
[SHOULD]パッケージバージョンはビルド時にdefineで注入し、ランタイムで package.json を読み込まない。テスト環境用のフォールバック値を用意する- 根拠: build-and-tooling, dev-conventions — 40+ パッケージが
__PACKAGE_VERSION__を tsup の define で注入し、'0.0.0-test'にフォールバック
- 根拠: build-and-tooling, dev-conventions — 40+ パッケージが
[SHOULD]ユーザー選択ライブラリ(UI フレームワーク、バリデーター等)は peerDependencies に配置し、devDependencies に pinned バージョンを併記する- 根拠: dependency-management — 全プロバイダーで zod を peerDependencies に範囲指定、devDependencies に固定バージョン
CI/CD・品質ゲート
[MUST]パフォーマンス指標(バンドルサイズ、ロード時間等)は CI の品質ゲートとして閾値付きで自動チェックする- 根拠: ci-cd — 560KB バンドルサイズ上限と 65-100ms ロード時間上限を CI で強制
[MUST]CI マトリクスの結果を集約するファサードジョブを作り、そのジョブ名を branch protection の required check に指定する- 根拠: ci-cd — マトリクスのバリアント名は変動するため、ファサードジョブで安定化。
if: ${{ !cancelled() }}を忘れない
- 根拠: ci-cd — マトリクスのバリアント名は変動するため、ファサードジョブで安定化。
[SHOULD]フォーマッタとリンターの責務を分離し、ESLint config にprettier(eslint-config-prettier)を必ず含める- 根拠: dev-conventions —
extends: ['next', 'turbo', 'prettier']で衝突を排除
- 根拠: dev-conventions —
[SHOULD]changeset のバージョン制約はドキュメントだけでなく CI で機械的に検証する- 根拠: dev-conventions, ci-cd —
verify-changesetsワークフローが changeset の frontmatter を解析し、patch 以外を自動拒否
- 根拠: dev-conventions, ci-cd —
[SHOULD]pre-commit hook にはバイパス機構を設け、品質保証は CI を信頼源とする二層構造にする- 根拠: dev-conventions —
ARTISANAL_MODE環境変数でバイパス可能にし、CI で同等チェックを実行
- 根拠: dev-conventions —
[SHOULD]依存更新ツールのスケジュールを依存の種類(production / dev / infra)ごとに差分化する- 根拠: ci-cd, build-and-tooling — production deps は毎週、devDeps は月次、examples は四半期ごとに更新
[AVOID]タスクランナーのキャッシュキーにビルド出力に影響しない環境変数(API キー等)を含める- 根拠: build-and-tooling —
turbo.jsonのbuild.envに 60+ の API キーが列挙され、キー変更のたびにキャッシュが無効化される問題
- 根拠: build-and-tooling —
AI アシスタント設定
[MUST]AI アシスタント設定ファイルに禁止事項を "Do Not" セクションとして明示的に列挙する- 根拠: ai-settings — AGENTS.md 末尾の "Do Not" セクションで AI がやりがちな誤りを防止
[SHOULD]複数の AI ツールを対象にする場合、1 つの正規ファイル(AGENTS.md)を作成し、他のファイル名(CLAUDE.md 等)はシンボリックリンクで対応する- 根拠: ai-settings —
CLAUDE.md -> AGENTS.mdのシンボリックリンクでファイル複製の同期問題を回避
- 根拠: ai-settings —
[SHOULD]AI アシスタント設定を階層構造(プロジェクト全体 → パッケージ → タスク)にし、ルートファイルは 300 行以下に抑える- 根拠: ai-settings — AGENTS.md を 285 行に抑え、詳細を skills/ と contributing/ に分離
[SHOULD]頻繁に変更される API を扱うプロジェクトでは、AI に内部知識を信用させず、ソースコードまたはドキュメントからの検証を強制する- 根拠: ai-settings —
use-ai-sdk/SKILL.mdが "Everything you know is outdated or wrong" と明示し、ドキュメント検索を必須ステップに
- 根拠: ai-settings —
ルール優先度の解釈
[MUST]: 違反するとバグ・セキュリティリスク・重大な設計劣化を招くルール[SHOULD]: 従うことで品質が向上するが、文脈によっては例外を許容するルール[AVOID]: 意図的に避けるべきアンチパターン・非推奨プラクティス