JavaScript / TypeScript から Jev を使う公式 SDK は @typesafe-ai/sdk です。choice() noul() score() のヘルパーで質問を書くと、答えの型が質問から推論されます。
1. インストール
npm install @typesafe-ai/sdk
# pnpm add @typesafe-ai/sdk
公式の要件は Node.js 20 以上です。ESM・CommonJS・TypeScript の型定義が同梱されています。
Python 版は typesafe-sdk、JS 版は @typesafe-ai/sdk と、パッケージ名の付け方が違います。
2. API キー
TypeSafe のコンソールでキーを発行し、環境変数 TYPESAFE_API_KEY に入れます。.env.local に TYPESAFE_API_KEY=… と書く場合、このファイルは Git に入れないでください。
下のコードを index.ts として保存し、次のように実行します。
node --env-file=.env.local index.ts
SDK 自体の要件は Node.js 20 以上ですが、.ts のファイルを node でそのまま実行できるのは Node.js 22.18 以降です(それより前は tsx などを使うか、.mjs として書きます)。このページの結果は Node.js 26 で実行したものです。
3. 最初の判定
TypeSafeClient を作り、判定したい内容(state)と質問(questions)を systemOne に渡します。質問は noul・choice・score の関数で組み立てます。
import { choice, noul, score, TypeSafeClient } from '@typesafe-ai/sdk';
const client = new TypeSafeClient();
const res = await client.systemOne({
state: { message: '助けてください!3日前から入金がずっと失敗しています。' },
questions: {
isUrgent: noul('Does `message` convey urgency?'),
department: choice('Which team should handle `message`?', {
billing: 'Payments, invoicing, refunds',
technical: 'Bugs, outages, integrations',
other: null,
}),
frustration: score('How frustrated is the customer?', ['Calm', 'Frustrated', 'Very angry']),
},
});
console.log(res.model); // jev-1.13.0
console.log(res.answers.isUrgent.noul); // 0.96
console.log(res.answers.department.choice); // billing
console.log(res.answers.department.confidence); // 0.9
console.log(res.answers.frustration.score); // 1.05
console.log(res.usage); // { input_tokens: 415, output_tokens: 72 }
コメントの値は 2026-09-21 に実際に返ってきたものです。往復は約 0.6 秒でした(1回の計測)。
レスポンスは REST API と同じ形(model / answers / usage)です。answers の中身も noul、choice、confidence、legend、probabilities と、REST の項目名のままです(REST API の使い方)。
型が質問から決まる
choice() に渡した選択肢のキーが、そのまま答えの型になります。
const d = res.answers.department.choice; // 'billing' | 'technical' | 'other'
switch (d) {
case 'billing':
break;
case 'technical':
break;
case 'other':
break;
// case 'sales': ← 選択肢に無い値なので、ここに書くとコンパイルエラー
default: {
const unreachable: never = d; // 選択肢を足して case を書き忘れると、ここがコンパイルエラーになる
throw new Error(`未対応の選択肢: ${unreachable}`);
}
}
存在しない選択肢を case に書く誤りは、型だけで防げます。選択肢を足したのに case を書き忘れる誤りは、そのままでは通ってしまうので、default に never への代入を置いて検出します。
確率を === で比べない
実行結果の probabilities には、billing: 0.9400000000000001 のような値が入っていました。浮動小数点の表現によるものです。確率やスコアは > < でしきい値と比べ、=== 0.94 のような一致の判定はしないでください。
説明の要らない選択肢は null
名前だけで意味が通る選択肢は、説明を null にできます。どれにも当てはまらない入力が来得るなら、上の例の other のような逃げ道を入れます(質問タイプの書き方)。
エラー
SDK は、ステータスごとの例外クラスを持っています。
| 例外 | 状況 | 確認 |
|---|---|---|
AuthenticationError(401) | API キーが無い・誤っている | 実行して確認 |
BadRequestError(400) | 存在しないモデル名 | 実行して確認 |
UnprocessableEntityError(422) | リクエストの形が不正(例: Choice に選択肢が無い) | 実行して確認 |
RateLimitError | レート制限の超過 | 未確認(公式の一覧より) |
APIConnectionError / APITimeoutError | 通信の失敗 | 未確認(公式の一覧より) |
例外は2系統に分かれています(@typesafe-ai/sdk 0.6.0 のクラスの継承を実際にたどって確認)。
- HTTP のエラー(サーバーが応答を返した):
AuthenticationError、BadRequestError、UnprocessableEntityError、RateLimitErrorなどはAPIErrorを継承し、e.statusにステータスが入る - 通信の失敗(応答が無い):
APIConnectionErrorはAPIErrorではなくTypeSafeErrorの直下。APITimeoutErrorはAPIConnectionErrorの派生。statusはありません
だから e instanceof APIError だけで捕まえると、通信の失敗とタイムアウトを取りこぼします。SDK の例外をすべて捕まえるなら TypeSafeError です。
import { APIConnectionError, APIError, TypeSafeError } from '@typesafe-ai/sdk';
try {
await client.systemOne({ state, questions });
} catch (e) {
if (e instanceof APIError && e.status === 422) {
// 質問の組み立てに不具合がある。再試行しても直らない
} else if (e instanceof APIConnectionError) {
// 応答が無かった(タイムアウトを含む)。e.status は無い
} else if (e instanceof TypeSafeError) {
// そのほかの SDK の例外
}
throw e;
}
422 のメッセージには 422 questions.c.choice.criteria: Field required のように、問題の場所が入っていました。
429 と 529 は SDK が既定で間隔を空けて再試行する、と公式ドキュメントにあります。回数などは RetryPolicy で変えられます。例外クラスの一覧は公式の API reference にあります。
AI SDK(experimental_evaluate)との違い
| 比較項目 | @typesafe-ai/sdk | AI SDK の experimental_evaluate |
|---|---|---|
| はい/いいえ | noul() → answers.x.noul | type: 'boolean' → answers.x.probability |
| 確信度 | answers.x.confidence | providerMetadata.typesafe.confidence.x |
| 答えたバージョン | res.model(jev-1.13.0) | Gateway 経由では入らなかった |
| 環境変数 | TYPESAFE_API_KEY | 直結は TYPESAFE_AI_API_KEY、Gateway は AI_GATEWAY_API_KEY |
| 安定性 | 公式 SDK(0.x) | experimental。patch リリースでも変わり得る |
| 他社モデルへの差し替え | できない | できる |
詳しくは AI SDK で使う。
次に読むもの
stateに何を入れるか → state の設計- 料金と上限 → 料金・モデル ID・制限
- やらせてはいけないこと → Jev が苦手なこと
よくある質問
npm のパッケージ名は typesafe-sdk ですか?
いいえ。公式の JS SDK は @typesafe-ai/sdk です。Python の typesafe-sdk と名前が違うので注意してください。
AI SDK の experimental_evaluate とどちらを使うべきですか?
すでに Vercel AI SDK を使っていて手早く試したいなら experimental_evaluate、TypeSafe の API の形(noul、confidence、legend、答えたバージョン ID)をそのまま扱いたいなら @typesafe-ai/sdk です。experimental_evaluate は patch リリースでも変わり得ると明記されています。
ブラウザから直接呼べますか?
API キーが利用者に見えてしまうので、ブラウザから直接呼ぶべきではありません。サーバー側(API ルートやサーバー関数)から呼んでください。
出典・参考リンク
- 一次情報 JavaScript SDK
- 一次情報 npm: @typesafe-ai/sdk
- 一次情報 typesafe-sdk-js