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

@plumbus/chat-ui

v0.1.7

Published

React UI for @plumbus/chat

Readme

@plumbus/chat-ui

React UI for @plumbus/chat. Drop in a working AI chat surface in 5 lines — message stream, input, source citations, refusal notices, cooldowns, and confirmation slot — all wired to the framework's ChatEvent protocol.

npm license peer: @plumbus/chat ≥0.1.11 peer: @plumbus/core ≥0.6.11 peer: react ≥19

What is this?

Plumbus is an AI-native, contract-driven TypeScript application framework. You declare your app's primitives (capabilities, entities, etc.) through define*() functions; the framework generates routes, validation, audit, and types.

@plumbus/chat adds a conversation primitive — one defineChat({...}) declaration becomes a fully-governed chat surface with policy guards, retrieval grounding, budgets, citations, and a streamed ChatEvent protocol.

@plumbus/chat-ui is the React client for that protocol. It consumes the event stream the server emits and renders the chat. If you're not using @plumbus/chat, this package has nothing to render.

Where it fits

┌─ server (Plumbus app) ────────────────────────────────────────┐
│  defineChat({...})  →  registerChatRoutes(app, ...)           │
│                              │                                 │
│                              ▼                                 │
│                  POST /chat/:name/turn (SSE / JSON)            │
└──────────────────────────────┬─────────────────────────────────┘
                               │  body: { sessionId, userMessage, audience, locale, clientHistory? }
                               │  stream: ChatEvent[]
┌──────────────────────────────▼─────────────────────────────────┐
│  browser (your React app)                                      │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │ @plumbus/chat-ui                                         │  │
│  │                                                          │  │
│  │  <ChatPanel chatName audience locale sessionId .../>     │  │
│  │       └─ uses useChat()                                  │  │
│  │              └─ fetch → readChatStream → applyChatEvent  │  │
│  │                     │                                    │  │
│  │                     ▼                                    │  │
│  │              React state (ChatUiState)                   │  │
│  │              ├─ <ChatMessages />                         │  │
│  │              ├─ <ChatInput />                            │  │
│  │              ├─ <ConfirmationDialog />                   │  │
│  │              └─ <SourceCitation />                       │  │
│  └──────────────────────────────────────────────────────────┘  │
└────────────────────────────────────────────────────────────────┘

The server owns policy, retrieval, audit; the UI just renders state derived from the events.

Status

Peer-locked to @plumbus/chat 0.1.x. useChat.confirm() performs the real POST /chat/:name/confirm round-trip (plus decline and lastConfirmResult) — see Key gotchas.

Install

pnpm add @plumbus/chat-ui

Peers:

  • @plumbus/chat 0.1.x (≥ 0.1.11./protocol subpath + Path B confirm route)
  • @plumbus/core 0.5.x || 0.6.x (≥ 0.6.11 via chat 0.1.11)
  • react >=19 — provided transitively by @plumbus/ui in Plumbus apps; do not add React to your own package.json

Prerequisites: a server-side defineChat({...}) declaration and registerChatRoutes(app, routeConfig, [chat]) from @plumbus/chat.

Quick start

'use client';
import { ChatPanel } from '@plumbus/chat-ui';
import { useState } from 'react';

export function HelpWidget() {
  const [sessionId] = useState(() => crypto.randomUUID());
  return (
    <ChatPanel
      chatName="help"           // must match the server-side defineChat({ name })
      sessionId={sessionId}
      audience="user"
      locale="en"
    />
  );
}

The panel posts to POST /chat/help/turn with credentials: 'include', streams the assistant reply, attaches cited sources to each message, surfaces notices (cooldown, out-of-scope), and renders any confirmation_required event.

What's included

| Surface | What it does | |---|---| | <ChatPanel /> | High-level component: messages + input + notices + confirmation slot. The 80% case. | | useChat({...}) | State machine alone. Returns { messages, status, notices, pendingConfirmation, send, confirm, cancel }. Drop into a custom layout. | | <ChatMessages />, <ChatInput />, <ConfirmationDialog />, <SourceCitation /> | Presentational sub-components for custom layouts. | | applyChatEvent(state, event) | Pure reducer(state, ChatEvent) → state. Testable without React or DOM. | | buildTurnRequestBody({...}) | Pure helper — builds the POST body, including capped clientHistory in client-persistence mode. | | pushUserMessage(state, text), initialChatUiState | More pure helpers for custom hooks. | | readChatStream(Response) | Async-iterable SSE parser. Use for non-React clients or custom transports. | | Types: ChatUiState, ChatUiMessage, ChatUiNotice, ChatUiPendingConfirmation, ChatUiStatus, TurnRequestBody, BuildTurnBodyArgs | The hook's shapes. | | useChatSession() | Placeholder. Returns useState defaults; sessions never populates. Do not depend on its shape. |

ChatPanel props

| Prop | Type | Required | Notes | |---|---|---|---| | chatName | string | yes | Must match defineChat({ name }) on the server. | | sessionId | string | yes | Caller-generated (crypto.randomUUID()); persists across the conversation. | | audience | string | yes | Threaded to the server's audience guard + prompt anchor. | | locale | string | yes | Validated against policy.scope.locales if set. | | persistence | 'server' \| 'client' | no (default 'server') | Must match the server's defineChat({ persistence: { messageContent } }). | | turnUrl | string | no (default /chat/{chatName}/turn) | Override when routes are namespaced (e.g. /api/chat/help/turn). | | className | string | no | Applied to the wrapper div. |

Key gotchas

  • persistence must match the server. <ChatPanel persistence="client" /> ships the last 20 messages on every turn; 'server' ships nothing. Mismatching values still runs but breaks context (server-mode client + client-mode server = model sees no history).
  • useChat.confirm() performs the server round-trip. It POSTs to confirmUrl (default /chat/{chatName}/confirm); the server authenticates like /turn, executes the confirmed capability/flow through the framework pipeline, and resumes the turn. decline(actionId) posts a reject; the terminal outcome lands in lastConfirmResult and a confirmation.resolved event. Cookie-authenticated apps must be served from the server's configured origin (exact-Origin + CSRF enforced server-side).
  • Cookie auth only. useChat and <ChatPanel /> hard-code credentials: 'include'. Bearer-auth flows need a small fork (~80 lines — see instructions/custom-ui.md).
  • useChatSession is a placeholder. Kept on the barrel so a real multi-session API can land later without a breaking export change.
  • No /testing subpath. The pure helpers (applyChatEvent, buildTurnRequestBody, pushUserMessage) are testable with vitest directly — no jsdom needed.

Documentation

The Plumbus ecosystem

@plumbus/chat-ui is one package in the Plumbus framework. For the full list of packages and when to use each, see the Plumbus monorepo README.

Links

License

MIT