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

bms-chat-engine

v0.3.2

Published

Headless chat engine (orchestrator + tools + LLM layer) for HOSxP/BMS, runnable against any OpenAI-compatible endpoint without a BMS session.

Readme

BMS Session ID — Blank Dashboard Template

Blank starter template for building hospital dashboards with HOSxP data via BMS Session API. Clone this repo, pick a dashboard template from the overview page, and let AI generate a full dashboard automatically.

Quick Start

npm install
npm run dev

Open http://localhost:5173/?bms-session-id=YOUR_SESSION_ID

Docker

docker compose up -d

Open http://localhost:3080/?bms-session-id=YOUR_SESSION_ID

How It Works

  1. User arrives with ?bms-session-id=GUID in the URL
  2. App retrieves session config from https://hosxp.net/phapi/PasteJSON
  3. App probes local API gateway at http://127.0.0.1:45011 — uses it if available (faster), falls back to remote tunnel
  4. Auto-detects database type (MySQL/PostgreSQL) via SELECT VERSION()
  5. Overview page shows 18 dashboard templates grouped by department
  6. User picks a template, edits the prompt if needed, copies it, and pastes into an AI chat to generate the dashboard

Session Input Methods

| Method | Description | |--------|-------------| | URL parameter | ?bms-session-id=GUID — saved to cookie, removed from URL | | Cookie | Persisted for 7 days, auto-reconnects on next visit | | Manual input | Login form for pasting a session ID |

Local API Detection

When connecting, the app automatically checks if the HOSxP API gateway is running locally on port 45011. If reachable, all API calls use http://127.0.0.1:45011 instead of the remote *.tunnel.hosxp.net endpoint. This eliminates tunnel latency for users running the gateway on the same machine.

Tech Stack

| Layer | Technology | |-------|------------| | Framework | React 19 + TypeScript 5.x (strict mode) | | Build | Vite 6 | | UI | shadcn/ui + Tailwind CSS v4 | | Tables | TanStack Table v8 | | Charts | Recharts 3.x | | Testing | Vitest + React Testing Library + MSW | | Date | date-fns | | MCP | vite-plugin-mcp (dev tools for AI coding assistants) |

Dashboard Templates (21)

Templates are grouped by hospital department on the overview page:

| Group | Templates | |-------|-----------| | Patient Services | OPD, IPD, Appointments, ER, OPD Screening (Nurse), Doctor Workbench, Refer | | Clinical Support | Lab, Radiology, Pharmacy, Dental, Operating Room | | Community Health (PCU) | Population, NCD Screening, ANC/Labor (Acc.2), MCH (Acc.3), EPI/Vaccine (Acc.4), School Health (Acc.5), Family Planning (Acc.6) | | Administration | Finance/Revenue, Medical Records |

Each template generates a prompt with specific KPIs, chart types, and data points based on HOSxP knowledge base.

Project Structure

src/
  services/
    bmsSession.ts        # Session retrieval, SQL execution, local API probe
    apiQueue.ts          # Concurrency control, deduplication, retry on 429
    queryBuilder.ts      # MySQL/PostgreSQL SQL generation
  hooks/
    useBmsSession.ts     # Session state management
    useQuery.ts          # Async query lifecycle (loading/error/success)
  contexts/
    BmsSessionContext.tsx # Session provider, auto-connect from URL/cookie
  components/
    ui/                  # shadcn/ui primitives (button, card, dialog, etc.)
    layout/              # AppHeader, AppLayout, LoadingSpinner
    session/             # LoginForm, SessionExpired, SessionValidator
  pages/
    Overview.tsx         # Main page with grouped dashboard templates
  types/
    index.ts             # TypeScript interfaces
  utils/
    sessionStorage.ts    # Cookie CRUD, URL parameter handling
    dateUtils.ts         # Date formatting helpers
tests/
  unit/                  # Service and utility tests
  component/             # React component tests
  integration/           # Cross-module flow tests
  api/                   # BMS Session API contract tests

API Request Queue

All SQL queries go through executeSqlViaApiQueued() which provides:

  • Concurrency limiting — max 3 concurrent API calls
  • Request deduplication — identical concurrent queries share the same result
  • Automatic retry — exponential backoff on HTTP 429 (rate limit)
  • Queue cleanup — pending requests cancelled on disconnect

Development

npm run dev              # Start dev server (port 5173)
npm test                 # Run all tests
npm run test:unit        # Unit tests only
npm run test:coverage    # Coverage report (80% threshold)
npm run lint             # ESLint
npm run build            # Production build

MCP Dev Tools

This project includes vite-plugin-mcp which exposes an MCP server at http://localhost:5173/__mcp/sse during development. AI coding assistants (Claude Code, Cursor, etc.) can connect to it for Vite config and module graph information. The .mcp.json file is auto-configured when the dev server starts.

BMS Session API Reference

  • Session retrieval: GET https://hosxp.net/phapi/PasteJSON?Action=GET&code={sessionId}
  • SQL execution: POST {bms_url}/api/sql with Authorization: Bearer {token}
  • Allowed SQL: SELECT, DESCRIBE, EXPLAIN, SHOW, WITH (read-only)
  • Blocked tables: opduser, opdconfig, sys_var, user_var, user_jwt (max 20 tables per query)

See docs/BMS-SESSION-FOR-DEV.md for the full API specification.

Database Support

The query builder auto-generates SQL for the detected database:

| Function | MySQL | PostgreSQL | |----------|-------|------------| | Current date | CURDATE() | CURRENT_DATE | | Date format | DATE_FORMAT(col, '%Y-%m') | TO_CHAR(col, 'YYYY-MM') | | Date subtract | DATE_SUB(CURDATE(), INTERVAL 30 DAY) | CURRENT_DATE - INTERVAL '30 days' | | Age calc | TIMESTAMPDIFF(YEAR, bday, CURDATE()) | EXTRACT(YEAR FROM AGE(bday)) | | Hour extract | HOUR(col) | EXTRACT(HOUR FROM col)::int | | Cast to text | CAST(col AS CHAR) | col::text |

License

Private — BMS (Bangkok Medical Software)

Use as a library (bms-chat-engine)

The core chat engine is publishable as a headless npm library and runs without a BMS session — point it at any OpenAI-compatible endpoint.

import { createChatEngine } from 'bms-chat-engine';

const engine = createChatEngine({
  llm: { baseURL: 'https://api.openai.com', apiKey: process.env.OPENAI_API_KEY!, model: 'gpt-4o-mini' },
  systemPrompt: 'You are a helpful assistant.',
});

const result = await engine.run([{ role: 'user', content: 'Hello' }]);
const reply = [...result.messages].reverse().find((m) => m.role === 'assistant')?.content;

Bring your own SDK via the escape hatch:

const engine = createChatEngine({ llm: { client: myLlmClient } }); // implements callLlm/streamLlm

With the BMS/HOSxP preset

import { createBmsChatEngine } from 'bms-chat-engine/bms';

const engine = createBmsChatEngine({
  session: { sessionId, config }, // BMS ConnectionConfig
  userInfo,                       // drives the น้องใบเตย persona
});

Build

npm run build:lib   # tsc + tsc-alias → ESM + .d.ts in dist/

Note: the library currently targets bundler/Vite consumers (it uses import.meta.glob to load skills). A bare-Node build and a full core/domain split are planned follow-ups. See docs/superpowers/specs/2026-07-01-chat-engine-library-design.md.

Ready-to-use React UI (bms-chat-engine/react)

The bms-chat-engine/react entry ships a batteries-included chat surface. ChatWidget injects its own scoped styles (no CSS import, no Tailwind), drives a ChatEngine turn-by-turn with token streaming, and renders a message list over an input. Wrap it in a sized container — it fills its parent:

import { createChatEngine } from 'bms-chat-engine';
import { ChatWidget } from 'bms-chat-engine/react';

const engine = createChatEngine({
  llm: { baseURL: 'https://api.openai.com', apiKey: import.meta.env.VITE_OPENAI_API_KEY, model: 'gpt-4o-mini' },
  systemPrompt: 'You are a helpful assistant.',
});

export function App() {
  return (
    <div style={{ height: 480 }}>
      <ChatWidget engine={engine} welcomeMessage="Ask me anything" />
    </div>
  );
}

react and react-dom are optional peer dependencies — only the consumer installs them (the core bms-chat-engine entry stays React-free). Add them to your app:

npm install react react-dom

Theming

ChatWidget is themeable with the theme prop — a preset ('dark', the default, or 'light') or a partial map of CSS-variable overrides. All styles are scoped under [data-bms-chat], so nothing leaks into the host app:

<ChatWidget engine={engine} theme="light" />

<ChatWidget
  engine={engine}
  theme={{ '--bmschat-bubble-user': '#0ea5e9', '--bmschat-radius': '20px' }}
/>

Headless primitives

Prefer to compose your own layout? Import the primitives and wire them together yourself. useChatEngine owns the message list, the in-flight streaming draft, loading/error state, and abort; MessageList and MessageInput render them:

The primitives are unstyled on their own — you own the CSS. Call ensureChatStyles() once on mount to inject the scoped [data-bms-chat] stylesheet, and spread resolveTheme(...) onto the data-bms-chat root so the CSS variables the primitives read are defined:

import { useEffect } from 'react';
import {
  useChatEngine,
  MessageList,
  MessageInput,
  ensureChatStyles,
  resolveTheme,
} from 'bms-chat-engine/react';

function MyChat({ engine }) {
  const { messages, streamingText, error, isStreaming, send } = useChatEngine(engine);
  useEffect(() => ensureChatStyles(), []);
  return (
    <div data-bms-chat style={{ ...resolveTheme('dark'), height: 480 }}>
      <MessageList messages={messages} streamingText={streamingText} error={error} />
      <MessageInput onSend={send} disabled={isStreaming} />
    </div>
  );
}

MessageBubble and Markdown are exported too, for full control over how a single message renders.

A2UI tool surfaces (opt-in)

Assistant turns that emit render_ui surfaces can be displayed by passing the A2UISurfaceRenderer from the separate bms-chat-engine/react/a2ui entry to the renderToolSurface prop. It is the only module that pulls in the heavy A2UI renderer, so the base /react bundle stays a2ui-free unless you opt in:

import { ChatWidget } from 'bms-chat-engine/react';
import { A2UISurfaceRenderer } from 'bms-chat-engine/react/a2ui';

<div style={{ height: 480 }}>
  <ChatWidget engine={engine} renderToolSurface={A2UISurfaceRenderer} />
</div>