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.
Maintainers
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
isLoadingproperty 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-chataipnpm add wanglin-chataiyarn add wanglin-chataibun add wanglin-chataiRequirements
- Node.js 18+
- A Google Gemini API key — Get one free at Google AI Studio
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 responseRetrieve 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.mdDevelopment
# 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 typecheckPublishing
# Build the package
npm run build
# Bump version (semantic release or manually)
npm version patch # or minor, or major
# Publish to npm
npm publishNote: The package is configured with
"publishConfig": { "access": "public" }so it works out of the box for scoped and unscoped packages.
Contributing
Contributions are welcome!
- Fork the repository.
- Create a feature branch:
git checkout -b feat/my-feature - Commit your changes:
git commit -m "feat: add my feature" - Push the branch:
git push origin feat/my-feature - 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.
