Error model
All provider and native errors are normalized to a single ExpoAIError at the boundary,
so app code handles one shape regardless of which adapter failed.
export class ExpoAIError extends Error {
code: ExpoAIErrorCode;
provider: ExpoAIProvider;
retryable: boolean;
fallbackRecommended: boolean;
nativeMessage?: string;
}
export type ExpoAIErrorCode =
| 'UNAVAILABLE'
| 'UNSUPPORTED_DEVICE'
| 'MODEL_NOT_READY'
| 'MODEL_DOWNLOAD_REQUIRED'
| 'USER_SETTING_REQUIRED'
| 'INVALID_PROMPT'
| 'CONTEXT_WINDOW_EXCEEDED'
| 'SAFETY_BLOCKED'
| 'RATE_LIMITED'
| 'CANCELLED'
| 'TIMEOUT'
| 'NATIVE_PROVIDER_ERROR'
| 'UNKNOWN';
retryabletells the app whether trying again may succeed (e.g. AICore still initializing).fallbackRecommendedsignals that switching to another provider is the right recovery, which the router uses when fallback is allowed.nativeMessagepreserves the original platform error for logging without leaking it into your normalized handling.