LocalMode
React

Provider Fallback

React hook for per-capability Chrome Built-in AI ⇄ Transformers.js provider resolution with truthful badge provenance.

Provider Fallback Hook

See it in action

Try the Writing Tools blocks for a working demo — the Write / Translate / Summarize / Complete blocks resolve Chrome Built-in AI independently per capability and fall back to Transformers.js behind an explicit download gate, rendering a truthful provider badge derived from this hook.

useProviderFallback

Resolve each capability (Summarizer, Translator, AI-edit, fill-mask) to Chrome Built-in AI or Transformers.js. Detection is independent per capability and reads the browser globals directly, so one capability can be Chrome-AI-served while another falls back in the same session. Every provider package is loaded via a dynamic import() inside the resolution path, so @localmode/react gains no hard dependency on @localmode/chrome-ai or @localmode/transformers — nothing about a provider ships until a capability first resolves. Resolution is lazy and session-cached, and each result carries truthful resolution provenance for a badge.

import { useProviderFallback, providerName } from '@localmode/react';

function SummarizeTab() {
  const { resolveSummarizer, resolution, isResolving } = useProviderFallback();

  async function run(text: string) {
    const { model } = await resolveSummarizer({
      chromeStyle: 'key-points',
      length: 'medium',
      fallbackModelId: 'Xenova/distilbart-cnn-6-6',
    });
    return summarize({ model, text });
  }

  return resolution ? <Badge provider={providerName(resolution.provider)} tier={resolution.tier} /> : null;
}

Options

Prop

Type

In the browser, inject static loader overrides

The default loadChromeAI / loadTransformers loaders use a Function-constructed import() so @localmode/react keeps no hard dependency on the provider packages. That indirection is opaque to bundlers, so a browser build can't resolve the bare specifier at runtime. When you consume this hook in the browser, pass loaders with literal imports the bundler can see:

useProviderFallback({
  loadChromeAI: () => import('@localmode/chrome-ai'),
  loadTransformers: () => import('@localmode/transformers'),
});

Return Value

Prop

Type

Resolver Params

Each resolver takes exactly the params its capability needs, so the split Write / Translate / Summarize / Complete surfaces each import only one. resolveFillMask takes a plain modelId: string (no Chrome equivalent).

ResolveSummarizerParams

Prop

Type

ResolveTranslatorParams

Prop

Type

ResolveEditEngineParams

Prop

Type

ResolvedModel and provenance

Every resolver returns a ResolvedModel<M> — the concrete model instance plus the provenance a badge derives from — and updates the hook's resolution, so a badge reflects what actually serves requests, never the detection probe alone.

Prop

Type

Standalone detectors and badge helpers

The detection functions are exported standalone (all async, all returning a ProviderId of 'chrome-ai' | 'transformers'). They read the same browser surfaces the @localmode/chrome-ai detectors read, so no provider import is needed to detect.

FunctionSignatureBehavior
detectSummarizerProvider() => Promise<ProviderId>'chrome-ai' when the Chrome Summarizer API is present, else 'transformers'.
detectTranslatorProvider() => Promise<ProviderId>'chrome-ai' when the Chrome Translator API is present, else 'transformers'.
detectPromptProvider() => Promise<ProviderId>Gated on LanguageModel.availability() === 'available' — presence alone is not enough, which prevents committing to a merely-downloadable Gemini Nano. Every other state falls back to 'transformers'. The legacy self.ai.languageModel surface (no availability()) trusts presence.
providerTier(provider: ProviderId) => ProviderTierMaps 'chrome-ai''built-in', 'transformers''download'.
providerName(provider: ProviderId) => stringHuman-readable name: 'Chrome AI' or 'Transformers.js'.
import { detectPromptProvider, providerName, providerTier } from '@localmode/react';

const provider = await detectPromptProvider(); // 'chrome-ai' only when Gemini Nano is actually 'available'
const label = providerName(provider); // 'Chrome AI' | 'Transformers.js'
const tier = providerTier(provider); // 'built-in' | 'download'

For the Chrome Built-in AI provider (Summarizer, Translator, Prompt APIs) see the Chrome AI guide; for the Transformers.js fallback models see the Transformers provider guide.

Blocks

AppDescriptionLinks
Writing ToolsPer-capability Chrome AI ⇄ Transformers.js resolution with a truthful provider-fallback badge via useProviderFallbackLive block · Source

On this page