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

@pulse8-ai/chat

v0.3.1

Published

A pluggable, customizable chat UI component package for React applications. Supports streaming, custom tool renderers, and any AI backend.

Downloads

21

Readme

@pulse8-ai/chat

A pluggable, customizable chat UI component library for React applications. Build AI chat interfaces with any backend, custom tool renderers, and full theming support.

Features

  • Backend Agnostic - Works with any AI backend (OpenAI, Anthropic, Gemini, custom APIs)
  • Pre-built Adapters - Out-of-the-box adapters for OpenAI, Anthropic, and Google Gemini
  • Streaming Utilities - Built-in SSE parsing and streaming helpers
  • Custom Tool Renderers - Register your own components for tool outputs (charts, tables, etc.)
  • Event Adapter Pattern - Transform any backend response format to the standard event format
  • Full Theme Customization - Customize colors, fonts, and all visual elements
  • Streaming Support - Real-time message streaming with proper state management
  • PDF Upload Support - Built-in support for file attachments
  • TypeScript First - Full TypeScript support with exported types
  • Minimal Dependencies - Core package has minimal dependencies; bring your own chart/table libraries

Installation

npm install @pulse8-ai/chat

Peer Dependencies

npm install react react-dom

Adding Styles

// In your main.tsx or App.tsx
import '@pulse8-ai/chat/styles.css'

Basic Usage (New Simplified API)

The easiest way to get started is using the streamConfig option:

import { ChatPanel, useChatMessages, openAIStreamConfig } from '@pulse8-ai/chat'
import '@pulse8-ai/chat/styles.css'

function ChatPage() {
  const { messages, isStreaming, sendMessage, stopStreaming } = useChatMessages({
    streamConfig: openAIStreamConfig({ apiKey: OPENAI_API_KEY })
  })

  return (
    <div className="h-screen bg-gray-900">
      <ChatPanel
        messages={messages}
        isStreaming={isStreaming}
        onSendMessage={(msg) => sendMessage(msg, 'gpt-4')}
        onStopStreaming={stopStreaming}
        emptyStateTitle="Hi! How can I help you today?"
      />
    </div>
  )
}

Custom Usage (With sendMessageToApi)

If you need full control over the API call (e.g. custom headers, complex body transformation), use sendMessageToApi. For detailed provider examples, see Advanced Streaming.

const { messages, sendMessage } = useChatMessages({
  sendMessageToApi: async (params) => {
    await streamSSE({
      url: '/api/chat',
      body: { message: params.userInput },
      adapter: createOpenAIAdapter(),
      onEvent: params.onEvent,
      onComplete: params.onComplete,
      onError: params.onError,
      signal: params.abortSignal,
    })
  },
})

Simple Message Appending (Custom Logic)

If you don't need streaming (e.g. your API returns the full response at once) or if you want to implement custom message flows, use the append helpers. This is often the easiest way to integrate with existing REST APIs.

const { appendUserMessage, appendAssistantMessage } = useChatMessages({
  sendMessageToApi: async () => {}, // no-op when you only append
})

const handleSend = async (question: string) => {
  // 1. Add the user message to UI immediately
  appendUserMessage(question)

  // 2. Call your API
  const response = await fetch('/api/chat', {
    method: 'POST',
    body: JSON.stringify({ question }),
  })
  const data = await response.json()

  // 3. Add the assistant response to UI
  appendAssistantMessage(data.answer)
}
  • appendUserMessage(content) – add a user message.
  • appendAssistantMessage(content) – add an assistant message (includes fade-in animation).
  • appendMessage({ role, content, ... }) – full control over ID, timestamp, etc.

Pre-built Adapters

The library ships with adapters for major AI providers:

| Provider | Full Adapter | Text-Only Adapter | Tool Support | |----------|--------------|-------------------|--------------| | OpenAI | createOpenAIAdapter() | openAITextAdapter | Function Calling | | Anthropic | createAnthropicAdapter() | anthropicTextAdapter | Tool Use | | Google Gemini | createGeminiAdapter() | geminiTextAdapter | Function Calling |

// From main package
import { createOpenAIAdapter, streamSSE } from '@pulse8-ai/chat'

// Or from subpaths (tree-shakeable)
import { createOpenAIAdapter } from '@pulse8-ai/chat/adapters'
import { streamSSE } from '@pulse8-ai/chat/utils'

Streaming Utilities

For advanced custom streaming implementations using SSE, see Advanced Streaming.

  • streamSSE - Main utility for SSE connections
  • parseSSELine - Low-level line parser
  • createSSEParser - Stateful parser for chunked data

Configuration

ChatConfigProvider

Wrap your app with ChatConfigProvider to customize tool renderers, event adapters, and more:

import { ChatConfigProvider, ChatPanel } from '@pulse8-ai/chat'
import type { IChatConfig } from '@pulse8-ai/chat'

const chatConfig: IChatConfig = {
  toolRenderers: {
    'generate_chart': MyChartRenderer,
    'search_results': MySearchRenderer,
  },
  toolNameMapping: {
    'generate_chart': 'Chart',
    'search_results': 'Web Search',
  },
  inlineTools: ['generate_chart'],
  hiddenTools: ['internal_lookup'],
}

function App() {
  return (
    <ChatConfigProvider config={chatConfig}>
      <ChatPage />
    </ChatConfigProvider>
  )
}

Components

ChatPanel

Main component combining messages and input:

<ChatPanel
  messages={messages}
  isStreaming={isStreaming}
  onSendMessage={handleSendMessage}
  onStopStreaming={stopStreaming}
  uploadedPdfs={uploadedPdfs}
  onUploadPdf={handleUploadPdf}
  onRemovePdf={handleRemovePdf}
  onClearChat={handleClearChat}
  emptyStateTitle="How can I help?"
  theme={customTheme}
  availableModels={models}
  selectedModel={selectedModel}
  onModelChange={setSelectedModel}
/>

Individual Components

For custom layouts:

  • ChatContainer - Message display area
  • ChatInput - Input with PDF upload support
  • ChatInputMinimal - Simplified input
  • Message - Generic message component
  • UserMessage - User message styling
  • AssistantMessage - Assistant message with tool outputs
  • MessageContentRenderer - Markdown and tool rendering
  • SuggestedQuestions - Question suggestions

Hooks

useChatMessages

Manages chat state and streaming:

const {
  messages,            // IMessage[]
  isStreaming,         // boolean
  uploadedPdfs,        // IPdfFile[]
  sendMessage,         // (message: string, model: string) => Promise<void>
  stopStreaming,       // () => void
  addPdf,              // (pdf: IPdfFile) => void
  removePdf,           // (uuid: string) => void
  clearChat,           // () => void
  appendMessage,       // (message: Partial<IMessage>) => void
  appendUserMessage,   // (content: string, attachedFiles?: IPdfFile[]) => void
  appendAssistantMessage, // (content: string) => void
} = useChatMessages({
  sendMessageToApi: async (params) => { ... },
  generateId: () => uuid(),  // Optional custom ID generator
  maxMessages: 100,          // Optional message limit
})

useModelSelection

Manages AI model selection:

const { selectedModel, setSelectedModel, availableModels } = useModelSelection({
  defaultModel: 'gpt-4',
  models: [
    { id: 'gpt-4', name: 'GPT-4' },
    { id: 'claude-3', name: 'Claude 3' },
  ],
})

Types

interface IMessage {
  id: string
  role: 'user' | 'assistant'
  content: string
  attachedFiles?: IPdfFile[]
  toolOutputs?: IToolOutput[]
  contentSegments?: IContentSegment[]
  timestamp: Date
}

interface IToolOutput {
  toolName: string
  friendlyName: string
  output: string
  visible: boolean
  title?: string
}

interface IPdfFile {
  uuid: string
  name: string
}

type EventAdapter = (rawEvent: unknown) => IStreamEvent | null

UI Components

Reusable UI primitives:

import { Button, Input, Select, Textarea } from '@pulse8-ai/chat'
// or
import { Button } from '@pulse8-ai/chat/ui'

Error Handling

The package includes error boundaries to prevent crashes:

import { ErrorBoundary, MessageErrorBoundary } from '@pulse8-ai/chat'

<ErrorBoundary
  fallback={<div>Chat is temporarily unavailable</div>}
  onError={(error) => logToService(error)}
>
  <ChatPanel {...props} />
</ErrorBoundary>

Documentation

For detailed guides, see:

Development

# Install dependencies
npm install

# Build
npm run build

# Type check
npm run type-check

# Lint
npm run lint

# Run Storybook
npm run storybook

Requirements

  • React ^18.0.0 || ^19.0.0
  • React DOM ^18.0.0 || ^19.0.0

Browser Support

| Browser | Minimum Version | |---------|-----------------| | Chrome | 80+ | | Firefox | 75+ | | Safari | 14+ | | Edge | 80+ |

Note: Requires support for:

  • Fetch API with streaming (ReadableStream)
  • ES2020+ features
  • CSS Custom Properties

License

MIT - see LICENSE for details.

Contributing

See CONTRIBUTING.md for contribution guidelines.