@i-dot-ai-npm/utilities
v1.0.1
Published
Utility functions for i-dot-ai applications
Downloads
199
Maintainers
Readme
@i-dot-ai-npm/utilities
A comprehensive TypeScript utility library for building applications with LangChain and i.AI's centralised authentication service.
Features
- 🔐 Authentication Utilities - Framework-agnostic auth client for i.AI's centralised auth API
- 💬 LangChain Chat - Stateful chat management with session persistence and Langfuse observability
- 🎯 Type-Safe - Full TypeScript support with strict typing
- 🔌 Framework Agnostic - Works with Express, Fastify, or any Node.js framework
Installation
npm install @i-dot-ai-npm/utilitiesQuick Start
Authentication
import { AuthApiClient, createAuthUtils } from '@i-dot-ai-npm/utilities';
// Initialise the auth client
const authClient = new AuthApiClient({
appName: 'my-app',
authApiUrl: 'https://auth-api.i.ai.gov.uk',
timeout: 5000 // optional, defaults to 5000ms
});
// Create auth utility functions
const { isAuthorisedUser, getUserInfo, handleUnauthorisedResponse } = createAuthUtils(authClient);
// Use in your route handlers
app.get('/protected', async (req, res) => {
const token = req.header('Authorization')?.replace('Bearer ', '');
if (!token || !(await isAuthorisedUser(token))) {
return res.status(401).json({ error: 'Unauthorised' });
}
res.json({ message: 'Success' });
});LangChain Chat
import { LangChainChat } from '@i-dot-ai-npm/utilities';
// Initialise chat with basic options
const chat = new LangChainChat({
model: 'gpt-3.5-turbo',
apiKey: process.env.OPENAI_API_KEY,
temperature: 0.7
});
// Send a message
const response = await chat.chat('Hello, how are you?');
console.log(response.message);Authentication API
AuthApiClient
The AuthApiClient communicates with i.AI's centralised authentication service to validate user tokens.
Constructor Options
interface AuthApiClientOptions {
appName: string; // Your application name
authApiUrl: string; // Base URL of the auth API
logger?: Logger; // Optional logger (defaults to console)
timeout?: number; // Request timeout in ms (defaults to 5000)
}Methods
getUserAuthorisationInfo(token: string): Promise<UserAuthorisationResult>
Validates a user token and returns authorisation details.
const result = await authClient.getUserAuthorisationInfo(token);
console.log(result.email); // [email protected]
console.log(result.isAuthorised); // true/false
console.log(result.authReason); // "VALID" or error reasonReturns:
interface UserAuthorisationResult {
email: string;
isAuthorised: boolean;
authReason: string;
}Auth Utilities
The createAuthUtils factory function creates three helper functions for common auth patterns.
const authUtils = createAuthUtils(authClient, logger?);isAuthorisedUser(authToken: string): Promise<boolean>
Simple boolean check for authorisation. Returns false on any error.
if (await isAuthorisedUser(token)) {
// User is authorised
}getUserInfo(authToken: string): Promise<UserAuthorisationResult>
Returns full user information. Returns safe defaults on error:
{
email: 'unknown',
isAuthorised: false,
authReason: 'unknown'
}handleUnauthorisedResponse(res: HttpResponse, userInfo: UserAuthorisationResult): HttpResponse
Sends a standardised 401 response with appropriate error messages.
const userInfo = await getUserInfo(token);
if (!userInfo.isAuthorised) {
return handleUnauthorisedResponse(res, userInfo);
}Token Expiry Handling:
- If
authReason === 'TOKEN_EXPIRED': Returns "Your login token has expired. Please log in again" - Otherwise: Returns "{email} is not authorised to access this app"
Full Authentication Example
import express from 'express';
import { AuthApiClient, createAuthUtils } from '@i-dot-ai-npm/utilities';
const authClient = new AuthApiClient({
appName: 'my-app',
authApiUrl: process.env.AUTH_API_URL!,
});
const { isAuthorisedUser, getUserInfo, handleUnauthorisedResponse } = createAuthUtils(authClient);
const app = express();
// Extract token from Authorization header
const getToken = (req: express.Request): string | null => {
const authHeader = req.header('Authorization');
if (!authHeader) return null;
return authHeader.startsWith('Bearer ') ? authHeader.substring(7) : authHeader;
};
// Simple authorisation check
app.get('/api/data', async (req, res) => {
const token = getToken(req);
if (!token || !(await isAuthorisedUser(token))) {
return res.status(401).json({ error: 'Unauthorised' });
}
res.json({ data: 'protected data' });
});
// Authorisation with user info
app.get('/api/profile', async (req, res) => {
const token = getToken(req);
if (!token) {
return res.status(401).json({ error: 'Authorization header required' });
}
const userInfo = await getUserInfo(token);
if (!userInfo.isAuthorised) {
return handleUnauthorisedResponse(res, userInfo);
}
res.json({ email: userInfo.email });
});
app.listen(3000);LangChain Chat API
LangChainChat
A stateful chat manager that maintains conversation history with optional Langfuse observability integration.
Constructor Options
interface ChatOptions {
model?: string; // Model name (default: 'gpt-3.5-turbo')
temperature?: number; // 0-1 (default: 0.7)
maxTokens?: number; // Maximum tokens (default: 1000)
apiKey?: string; // OpenAI API key
baseUrl?: string; // Custom API base URL
langfuseSecretKey?: string; // Langfuse secret key
langfusePublicKey?: string; // Langfuse public key
langfuseHost?: string; // Langfuse host URL
sessionId?: string; // Session ID for tracking
userId?: string; // User ID for tracking
}Constructor:
const chat = new LangChainChat(globalOptions?: ChatOptions);Global options are merged with per-call options (per-call options take precedence).
Methods
chat(message: string, options?: ChatOptions, sessionId?: string): Promise<ChatResponse>
Send a message and get a response. Sessions are automatically created if not provided.
const response = await chat.chat('What is TypeScript?');
console.log(response.message);
console.log(response.usage); // Token usage stats
console.log(response.sessionId); // Auto-generated or providedReturns:
interface ChatResponse {
message: string;
model: string;
sessionId?: string;
usage?: {
promptTokens: number;
completionTokens: number;
totalTokens: number;
};
}getSession(sessionId: string): ChatSession | undefined
Retrieve a session's complete history and metadata.
const session = chat.getSession('session-123');
if (session) {
console.log(session.messages); // Full message history
console.log(session.createdAt); // Session creation time
console.log(session.updatedAt); // Last activity time
}clearSession(sessionId: string): boolean
Delete a session and its history. Returns true if deleted, false if not found.
if (chat.clearSession('session-123')) {
console.log('Session cleared');
}listSessions(): string[]
Get all active session IDs.
const sessions = chat.listSessions();
console.log(`Active sessions: ${sessions.length}`);Chat Examples
Basic Usage
import { LangChainChat } from '@i-dot-ai-npm/utilities';
const chat = new LangChainChat({
apiKey: process.env.OPENAI_API_KEY,
temperature: 0.7,
maxTokens: 1000
});
const response = await chat.chat('Explain quantum computing in simple terms');
console.log(response.message);Session Management
// Create a persistent conversation
const sessionId = 'user-123-conversation';
const response1 = await chat.chat('My name is Alice', {}, sessionId);
const response2 = await chat.chat('What is my name?', {}, sessionId);
// Response: "Your name is Alice"
// View conversation history
const session = chat.getSession(sessionId);
console.log(session?.messages); // All messages in order
// Clear when done
chat.clearSession(sessionId);With Langfuse Observability
const chat = new LangChainChat({
model: 'gpt-4',
apiKey: process.env.OPENAI_API_KEY,
langfuseSecretKey: process.env.LANGFUSE_SECRET_KEY,
langfusePublicKey: process.env.LANGFUSE_PUBLIC_KEY,
langfuseHost: 'https://cloud.langfuse.com',
userId: 'user-123'
});
const response = await chat.chat('Hello!', {}, 'session-123');
// Automatically tracked in Langfuse dashboardPer-Call Options
// Global defaults
const chat = new LangChainChat({
model: 'gpt-3.5-turbo',
temperature: 0.7
});
// Override for specific call
const response = await chat.chat('Be creative!', {
temperature: 1.0, // Higher temperature for this call
maxTokens: 2000
});Custom OpenAI Compatible API
const chat = new LangChainChat({
model: 'llama-3-70b',
apiKey: 'your-api-key',
baseUrl: 'https://api.your-provider.com/v1'
});Error Handling
Authentication Errors
import { AuthApiRequestError } from '@i-dot-ai-npm/utilities';
try {
const result = await authClient.getUserAuthorisationInfo(token);
} catch (error) {
if (error instanceof AuthApiRequestError) {
console.error('Auth API failed:', error.message);
// Handle auth service being down
}
}The auth utilities (isAuthorisedUser, getUserInfo) catch errors internally and return safe defaults, so try-catch is optional.
Chat Errors
try {
const response = await chat.chat('Hello');
} catch (error) {
console.error('Chat failed:', error);
// Handle API errors, network issues, etc.
}TypeScript Support
Full TypeScript definitions are included. Import types as needed:
import {
// Auth types
UserAuthorisationResult,
AuthApiResponse,
Logger,
// Chat types
ChatMessage,
ChatOptions,
ChatResponse,
ChatSession
} from '@i-dot-ai-npm/utilities';Development
# Install dependencies
npm install
# Build the package
npm run build
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Lint code
npm run lint
# Fix linting issues
npm run lint:fix
# Development mode (watch)
npm run devProject Structure
src/
├── auth/ # Authentication utilities
│ ├── authApiClient.ts # HTTP client for auth API
│ ├── auth.ts # Utility functions factory
│ └── types.ts # Auth type definitions
├── llm/ # LangChain utilities
│ └── langchain/
│ ├── chat/ # Chat implementation
│ └── types/ # Chat type definitions
└── index.ts # Main exportsVersioning
This package uses semantic-release with conventional commits:
feat:→ Minor version bumpfix:,perf:,refactor:→ Patch version bumpBREAKING CHANGE:in commit body → Major version bumpdocs:,test:,chore:→ No release
Example commits:
git commit -m "feat: add custom logger support"
git commit -m "fix: handle empty auth token"
git commit -m "feat: change auth API interface
BREAKING CHANGE: AuthApiClient constructor now requires options object"License
MIT
Support
For issues and feature requests, please use the GitHub issue tracker.
