UNPKG

ai

Version:

AI SDK by Vercel - build apps like ChatGPT, Claude, Gemini, and more with a single interface for any model using the Vercel AI Gateway or go direct to OpenAI, Anthropic, Google, or any other model provider.

45 lines (40 loc) 1.35 kB
import { convertUint8ArrayToBase64 } from '@ai-sdk/provider-utils'; const encoder = new TextEncoder(); /** * Deterministic JSON serialization: object keys are sorted so that two * structurally-equal values always produce the same string regardless of key * insertion order. Used as the input to content hashing. */ export function canonicalJSON(value: unknown): string { if (value === null || value === undefined) { return JSON.stringify(value); } if (typeof value !== 'object') { return JSON.stringify(value); } if (Array.isArray(value)) { return `[${value.map(canonicalJSON).join(',')}]`; } const keys = Object.keys(value as Record<string, unknown>).sort(); const entries = keys.map( k => `${JSON.stringify(k)}:${canonicalJSON((value as Record<string, unknown>)[k])}`, ); return `{${entries.join(',')}}`; } export function toBase64url(bytes: Uint8Array): string { return convertUint8ArrayToBase64(bytes) .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=+$/g, ''); } /** * Canonical SHA-256 digest (base64url) of an arbitrary JSON-serializable value. */ export async function hashCanonical(value: unknown): Promise<string> { const digest = await crypto.subtle.digest( 'SHA-256', encoder.encode(canonicalJSON(value)), ); return toBase64url(new Uint8Array(digest)); }