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

wanglin-chatai

v0.0.1

Published

Headless AI Chat Engine — lightweight wrapper around Google Gemini API with conversation history, configurable models, and strong TypeScript support.

Readme

WangLin ChatAI

Headless AI Chat Engine — A lightweight, framework-agnostic TypeScript wrapper around the Google Gemini API for managing AI chat sessions, conversation history, and model configuration.

const chat = new WangLinChatAI({ apiKey: "YOUR_API_KEY" });
const reply = await chat.sendMessage("Hello!");

Features

  • Headless — Zero UI dependencies. Use it with React, Vue, Svelte, Next.js, Nuxt, Express, Electron, or vanilla Node.js.
  • Session management — Automatic conversation history tracking across turns.
  • Configurable models — Supports any Gemini model (gemini-2.5-flash, etc.).
  • System instructions — Set custom behaviour for the assistant.
  • Loading state — Exposed isLoading property for UI bindings.
  • Strongly typed — Full TypeScript declarations with no any.
  • Custom errors — Distinct error classes for API key, validation, and API failures.
  • Tree-shakeable — ESM and CommonJS builds with sideEffects: false.

Installation

npm install wanglin-chatai
pnpm add wanglin-chatai
yarn add wanglin-chatai
bun add wanglin-chatai

Requirements

Quick Start

TypeScript

import { WangLinChatAI } from "wanglin-chatai";

const chat = new WangLinChatAI({
  apiKey: "YOUR_API_KEY",
  systemInstruction: "You are a helpful assistant.",
});

async function main() {
  const result = await chat.sendMessage("What is the capital of France?");
  console.log(result.text);
  // → "The capital of France is Paris."

  console.log(result.history);
  // → [{ role: "user", text: "..." }, { role: "model", text: "..." }]
}

main();

JavaScript (CommonJS)

const { WangLinChatAI } = require("wanglin-chatai");

const chat = new WangLinChatAI({
  apiKey: process.env.GEMINI_API_KEY,
});

async function main() {
  const result = await chat.sendMessage("Tell me a joke.");
  console.log(result.text);
}

main();

JavaScript (ESM)

import { WangLinChatAI } from "wanglin-chatai";

const chat = new WangLinChatAI({
  apiKey: process.env.GEMINI_API_KEY,
});

const result = await chat.sendMessage("How does AI work?");
console.log(result.text);

Usage

Initialize the client

import { WangLinChatAI } from "wanglin-chatai";

const chat = new WangLinChatAI({
  apiKey: "YOUR_API_KEY",
  model: "gemini-2.5-flash",
  systemInstruction: "Answer concisely.",
  temperature: 0.5,
});

Send a message

const { text, history } = await chat.sendMessage("Hello!");
console.log(text); // Assistant response

Retrieve conversation history

const history = await chat.getHistory();
// → [{ role: "user", text: "Hello!" }, { role: "model", text: "Hi there!" }]

Clear history

chat.clearHistory();
const history = await chat.getHistory();
// → []

Handle errors

import {
  MissingApiKeyError,
  InvalidMessageError,
  GeminiRequestError,
} from "wanglin-chatai";

try {
  const result = await chat.sendMessage("");
} catch (error) {
  if (error instanceof InvalidMessageError) {
    console.error("Invalid message:", error.message);
  } else if (error instanceof GeminiRequestError) {
    console.error("API error:", error.message, error.cause);
  }
}

API Reference

WangLinChatAI

The main class for interacting with the Google Gemini API.

Constructor

new WangLinChatAI(options?: WangLinChatAIOptions)

| Option | Type | Default | Description | |---------------------|----------|-----------------------|----------------------------------------------------------| | apiKey | string | GEMINI_API_KEY env | Your Google Gemini API key. | | model | string | "gemini-2.5-flash" | The Gemini model identifier. | | systemInstruction | string | undefined | System prompt to set the assistant's behaviour. | | temperature | number | 0.7 | Output randomness (0.0 – 1.0). |

If no apiKey is provided, the constructor reads process.env.GEMINI_API_KEY, then falls back to process.env.GOOGLE_API_KEY. If none are set, a MissingApiKeyError is thrown.

Properties

| Property | Type | Description | |-------------|-----------|------------------------------------------------| | isLoading | boolean | true while waiting for a model response. |

Methods

sendMessage(text: string): Promise<SendMessageResult>

Sends a text message to the model and returns the response.

| Parameter | Type | Description | |-----------|----------|----------------------------------| | text | string | The user message (non-empty). |

Returns:

interface SendMessageResult {
  text: string;           // Assistant's response
  history: ChatMessage[]; // Full conversation history after this turn
}

Throws:

  • InvalidMessageError — If the message is empty or whitespace-only.
  • GeminiRequestError — If the API call fails.
const { text, history } = await chat.sendMessage("What is TypeScript?");
getHistory(): Promise<ChatMessage[]>

Returns the conversation history.

interface ChatMessage {
  role: "user" | "model";
  text: string;
}
const history = await chat.getHistory();
// → [{ role: "user", text: "Hi" }, { role: "model", text: "Hello!" }]
clearHistory(): void

Resets the chat session and clears all history.

chat.clearHistory();
const history = await chat.getHistory();
// → []

Error Handling

The package exports three custom error classes for granular error handling.

| Error | Thrown when | |---------------------|-----------------------------------------------| | MissingApiKeyError | No API key is provided via options or env vars | | InvalidMessageError | Message is empty, whitespace-only, or not a string | | GeminiRequestError | The Gemini API returns an error |

All errors extend the native Error class and have a distinct name property for reliable instanceof checks.

import {
  MissingApiKeyError,
  InvalidMessageError,
  GeminiRequestError,
} from "wanglin-chatai";

try {
  await chat.sendMessage("");
} catch (error) {
  if (error instanceof MissingApiKeyError) {
    // Handle missing API key
  } else if (error instanceof InvalidMessageError) {
    // Handle invalid message
  } else if (error instanceof GeminiRequestError) {
    // Handle API failure
    console.error(error.message, error.cause);
  }
}

Project Structure

wanglin-chatai/
├── src/
│   ├── index.ts             # Public API exports
│   ├── WangLinChatAI.ts     # Main chat engine class
│   ├── types.ts             # TypeScript interfaces & types
│   ├── errors.ts            # Custom error classes
│   └── utils.ts             # Internal utilities (config, validation)
├── test/
│   └── WangLinChatAI.test.ts # Unit tests (Vitest)
├── dist/                     # Build output (ESM + CJS + types)
├── package.json
├── tsconfig.json
├── tsup.config.ts
├── vitest.config.ts
└── README.md

Development

# Clone and install
git https://github.com/wanglinsaputra/wanglin-chatai.git
cd wanglin-chatai
npm install

# Build (ESM + CJS + type declarations)
npm run build

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Run tests with coverage
npm run test:coverage

# Type-check without emitting
npm run typecheck

Publishing

# Build the package
npm run build

# Bump version (semantic release or manually)
npm version patch  # or minor, or major

# Publish to npm
npm publish

Note: The package is configured with "publishConfig": { "access": "public" } so it works out of the box for scoped and unscoped packages.

Contributing

Contributions are welcome!

  1. Fork the repository.
  2. Create a feature branch: git checkout -b feat/my-feature
  3. Commit your changes: git commit -m "feat: add my feature"
  4. Push the branch: git push origin feat/my-feature
  5. Open a pull request.

Please ensure:

  • All existing tests pass (npm test).
  • New features include tests.
  • The code is typed (no any).
  • Commit messages follow Conventional Commits.

Disclaimer

This package is provided for legitimate educational and development purposes. I am not responsible for any misuse of this package for illegal, unlawful, or harmful activities. The law applies accordingly — use wisely and responsibly.

License

MIT © Wanglin Saputra