diff --git a/src/polyfills.ts b/src/polyfills.ts index c9c8fde..f5aa7d9 100644 --- a/src/polyfills.ts +++ b/src/polyfills.ts @@ -1,7 +1,7 @@ /** * Polyfills that must run before any other app code (including LangChain/LangGraph). * This file is imported as the very first line in App.tsx so that ReadableStream - * exists before @langchain/core or @langchain/langgraph are loaded. + * and crypto.getRandomValues exist before @langchain/core / uuid are loaded. */ import 'web-streams-polyfill'; @@ -13,3 +13,33 @@ if (typeof (g as any).ReadableStream === 'undefined') { (g as any).WritableStream = ponyfill.WritableStream; (g as any).TransformStream = ponyfill.TransformStream; } + +// Polyfill crypto.getRandomValues for React Native/Expo (required by uuid, LangChain, etc.) +if (typeof g !== 'undefined') { + const cryptoObj = (g as any).crypto; + if (!cryptoObj || typeof (cryptoObj.getRandomValues) !== 'function') { + try { + const ExpoCrypto = require('expo-crypto'); + const getRandomValues = (array: ArrayBufferView): ArrayBufferView => { + ExpoCrypto.getRandomValues(array); + return array; + }; + if (!(g as any).crypto) (g as any).crypto = {}; + (g as any).crypto.getRandomValues = getRandomValues; + } catch (e) { + console.warn('[polyfills] crypto.getRandomValues polyfill failed:', e); + } + } +} + +// Polyfill AbortSignal.prototype.throwIfAborted (required by fetch/LangChain in RN; not present in older runtimes) +const AbortSignalGlobal = (g as any).AbortSignal; +if (typeof AbortSignalGlobal === 'function' && AbortSignalGlobal.prototype && typeof AbortSignalGlobal.prototype.throwIfAborted !== 'function') { + AbortSignalGlobal.prototype.throwIfAborted = function (this: AbortSignal) { + if (this.aborted) { + const e = new Error('Aborted'); + e.name = 'AbortError'; + throw e; + } + }; +}