npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mongrov/ai

v0.2.0

Published

AI chat and completion hooks for React Native / Expo — XState-powered with AI SDK integration

Readme

@mongrov/ai

AI chat and completion hooks for React Native / Expo applications. Built with XState for state management and compatible with the AI SDK.

Installation

npm install @mongrov/ai
# or
pnpm add @mongrov/ai

Peer Dependencies

npm install react ai xstate @xstate/react

Optional Dependencies

For the pre-built chat UI:

npm install react-native-gifted-chat uniwind

Features

  • XState-powered: Robust state management for chat and completion flows
  • AI SDK compatible: Works with Vercel AI SDK providers
  • Streaming support: Real-time streaming text responses
  • Type-safe: Full TypeScript support
  • UI components: Optional pre-built chat components

Quick Start

1. Set up the Provider

import { AIProvider, createAIClient } from '@mongrov/ai';

const aiClient = createAIClient({
  baseUrl: 'https://your-ai-api.com',
  apiKey: 'your-api-key',
  model: 'gpt-4',
});

function App() {
  return (
    <AIProvider client={aiClient}>
      <ChatScreen />
    </AIProvider>
  );
}

2. Use the Chat Hook

import { useAIChat } from '@mongrov/ai';

function ChatScreen() {
  const {
    messages,
    sendMessage,
    isLoading,
    error,
    stop,
  } = useAIChat();

  const handleSend = (text: string) => {
    sendMessage({ content: text });
  };

  return (
    <View>
      {messages.map((msg) => (
        <MessageBubble key={msg.id} message={msg} />
      ))}
      <ChatInput onSend={handleSend} disabled={isLoading} />
    </View>
  );
}

3. Use the Completion Hook

For single completions (non-chat):

import { useAICompletion } from '@mongrov/ai';

function CompletionExample() {
  const {
    completion,
    complete,
    isLoading,
    error,
  } = useAICompletion();

  const handleGenerate = async () => {
    await complete('Write a haiku about coding');
  };

  return (
    <View>
      <Button onPress={handleGenerate} title="Generate" />
      {isLoading && <ActivityIndicator />}
      {completion && <Text>{completion}</Text>}
    </View>
  );
}

API Reference

AIProvider

The context provider for AI functionality.

import { AIProvider } from '@mongrov/ai';

<AIProvider
  client={aiClient}           // Required: AI client instance
  config={{                   // Optional: Additional config
    systemPrompt: 'You are a helpful assistant',
    maxTokens: 1000,
  }}
>
  {children}
</AIProvider>

createAIClient

Creates an AI client instance.

import { createAIClient } from '@mongrov/ai';

const client = createAIClient({
  baseUrl: 'https://api.openai.com/v1',  // API endpoint
  apiKey: 'sk-...',                       // API key
  model: 'gpt-4',                         // Model to use
  headers: {},                            // Optional: Additional headers
});

useAIChat

Hook for managing chat conversations.

const {
  // State
  messages,      // Message[] - conversation history
  isLoading,     // boolean - whether a request is in progress
  error,         // Error | null - last error

  // Actions
  sendMessage,   // (params: { content: string }) => void
  stop,          // () => void - stop streaming
  reset,         // () => void - clear conversation

  // Metadata
  status,        // 'idle' | 'loading' | 'streaming' | 'error'
} = useAIChat({
  initialMessages: [],        // Optional: Starting messages
  onError: (error) => {},     // Optional: Error callback
  onFinish: (message) => {},  // Optional: Completion callback
});

useAICompletion

Hook for single completions.

const {
  // State
  completion,    // string | null - generated text
  isLoading,     // boolean
  error,         // Error | null

  // Actions
  complete,      // (prompt: string) => Promise<void>
  stop,          // () => void
  reset,         // () => void
} = useAICompletion({
  onError: (error) => {},
  onFinish: (result) => {},
});

useAIContext

Access the AI context directly.

import { useAIContext, useAIClient, useAIConfig } from '@mongrov/ai';

// Get the full context
const context = useAIContext();

// Get just the client
const client = useAIClient();

// Get just the config
const config = useAIConfig();

UI Components

Optional pre-built UI components for chat interfaces.

StreamingText

Displays text with a streaming cursor effect.

import { StreamingText } from '@mongrov/ai/ui';

<StreamingText
  text={message.content}
  isStreaming={isGenerating}
  cursorChar="|"
/>

QuickReplyBar

Displays quick reply suggestions.

import { QuickReplyBar } from '@mongrov/ai/ui';

<QuickReplyBar
  replies={['Tell me more', 'What else?', 'Thanks!']}
  onSelect={(reply) => sendMessage({ content: reply })}
/>

ChatEmptyState

Empty state for chat screens.

import { ChatEmptyState } from '@mongrov/ai/ui';

<ChatEmptyState
  title="Start a conversation"
  subtitle="Send a message to begin chatting"
/>

Message Adapter

Convert between AI SDK messages and Gifted Chat format:

import { toGiftedChatMessages, fromGiftedChatMessage } from '@mongrov/ai/ui';

// AI SDK -> Gifted Chat
const giftedMessages = toGiftedChatMessages(aiMessages, currentUserId);

// Gifted Chat -> AI SDK
const aiMessage = fromGiftedChatMessage(giftedMessage);

Types

interface Message {
  id: string;
  role: 'user' | 'assistant' | 'system';
  content: string;
  createdAt?: Date;
}

interface AIConfig {
  baseUrl: string;
  apiKey: string;
  model: string;
  systemPrompt?: string;
  maxTokens?: number;
  temperature?: number;
}

interface UseAIChatReturn {
  messages: Message[];
  isLoading: boolean;
  error: Error | null;
  status: 'idle' | 'loading' | 'streaming' | 'error';
  sendMessage: (params: { content: string }) => void;
  stop: () => void;
  reset: () => void;
}

Examples

With Gifted Chat

import { GiftedChat } from 'react-native-gifted-chat';
import { useAIChat } from '@mongrov/ai';
import { toGiftedChatMessages, fromGiftedChatMessage } from '@mongrov/ai/ui';

function ChatScreen() {
  const { messages, sendMessage, isLoading } = useAIChat();
  const currentUserId = 'user-1';

  const giftedMessages = toGiftedChatMessages(messages, currentUserId);

  const onSend = (newMessages: IMessage[]) => {
    const message = fromGiftedChatMessage(newMessages[0]);
    sendMessage({ content: message.content });
  };

  return (
    <GiftedChat
      messages={giftedMessages}
      onSend={onSend}
      user={{ _id: currentUserId }}
      isTyping={isLoading}
    />
  );
}

Error Handling

import { useAIChat } from '@mongrov/ai';

function ChatWithErrorHandling() {
  const { messages, sendMessage, error, reset } = useAIChat({
    onError: (err) => {
      console.error('AI Error:', err);
      // Show toast, log to analytics, etc.
    },
  });

  if (error) {
    return (
      <ErrorState
        message={error.message}
        onRetry={() => {
          reset();
          // Retry last message
        }}
      />
    );
  }

  // ... rest of component
}

License

MIT