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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@redhat-cloud-services/ai-client-common

v0.13.0

Published

Common interfaces and utilities for AI client packages in the Red Hat Cloud Services ecosystem.

Readme

@redhat-cloud-services/ai-client-common

Common interfaces and utilities for AI client packages in the Red Hat Cloud Services ecosystem.

Features

  • Standardized AI Client Interface - Common IAIClient interface for all AI services
  • Conversation Management - Standard conversation interface with locking support
  • Dependency Injection - Interfaces for custom fetch implementations and streaming handlers
  • TypeScript Support - Comprehensive type definitions for AI client development
  • Error Handling - Base error classes with validation error support
  • Streaming Support - Generic streaming handler interface for real-time responses
  • Zero Dependencies - Pure TypeScript interfaces with no runtime dependencies

Installation

npm install @redhat-cloud-services/ai-client-common

Core Interfaces

IAIClient Interface

All AI clients in this workspace implement the IAIClient interface:

import { IAIClient, ClientInitLimitation, IInitErrorResponse } from '@redhat-cloud-services/ai-client-common';

declare class IAIClient<AP extends Record<string, unknown> = Record<string, unknown>> {
  constructor(config: IBaseClientConfig);
  
  init(): Promise<{
    conversations: IConversation[];
    limitation?: ClientInitLimitation;
    error?: IInitErrorResponse;
  }>;
  
  // Basic message sending
  sendMessage<T extends Record<string, unknown> = Record<string, unknown>>(
    conversationId: string, 
    message: string, 
    options?: ISendMessageOptions<T>
  ): Promise<IMessageResponse<AP>>;
  
  // Message sending with custom request payload
  sendMessage<
    T extends Record<string, unknown> = Record<string, unknown>,
    R extends Record<string, unknown> = Record<string, unknown>
  >(
    conversationId: string, 
    message: string, 
    options?: ISendMessageOptions<T, R>
  ): Promise<IMessageResponse<AP>>;
  
  getConversationHistory(conversationId: string, options?: IRequestOptions): Promise<IConversationHistoryResponse<AP>>;
  
  healthCheck(options?: IRequestOptions): Promise<unknown>;
  
  getServiceStatus?(options?: IRequestOptions): Promise<unknown>;
  
  createNewConversation(): Promise<IConversation>;
}

Dependency Injection

Custom Fetch Implementation

Important: Do NOT set 'Content-Type' headers in your fetchFunction - AI clients manage these internally based on endpoint requirements.

import { IFetchFunction } from '@redhat-cloud-services/ai-client-common';

const customFetch: IFetchFunction = async (input, init) => {
  // Add authentication headers
  const token = await getAuthToken();
  
  return fetch(input, {
    ...init,
    headers: {
      ...init?.headers,
      'Authorization': `Bearer ${token}`,
      // DO NOT set 'Content-Type' - AI clients handle this internally
    },
  });
};

Base Client Configuration

import { IBaseClientConfig } from '@redhat-cloud-services/ai-client-common';

const config: IBaseClientConfig = {
  baseUrl: 'https://your-ai-service.com',
  fetchFunction: customFetch // Optional - defaults to native fetch
};

Lazy Initialization (Default Behavior)

AI clients now use lazy initialization by default. The init() method no longer auto-creates conversations - instead, conversations are created automatically when needed (e.g., on first message send).

Default Behavior:

  • Client init() only loads existing conversations
  • No conversations are auto-created during initialization
  • Conversations are created automatically on first sendMessage() call
  • Provides optimal performance and seamless user experience

Key Changes:

  • Removed: ClientInitOptions interface (no longer needed)
  • Removed: getInitOptions() method from IAIClient interface
  • Removed: initialConversationId from init() return type
  • New: Automatic conversation creation on first message send

Client Initialization Responses

The init() method returns additional information about client limitations and errors:

import { ClientInitLimitation, IInitErrorResponse } from '@redhat-cloud-services/ai-client-common';

// Client limitations (e.g., quota exceeded)
type ClientInitLimitation = {
  reason: string;
  detail?: string;
};

// Initialization errors
interface IInitErrorResponse {
  message: string;
  status: number;
}

// Utility function to check if an object is an IInitErrorResponse
function isInitErrorResponse(obj: unknown): obj is IInitErrorResponse;

Streaming Support

The streaming interface has been updated to standardize chunk handling across all AI clients. The handleChunk callback now receives an IStreamChunk object with standardized structure.

IStreamChunk Interface

import { IStreamChunk } from '@redhat-cloud-services/ai-client-common';

interface IStreamChunk<T extends Record<string, unknown> = Record<string, unknown>> {
  answer: string;
  messageId: string;
  conversationId: string;
  additionalAttributes: T;
}

Implementing a Custom Streaming Handler

import { IStreamingHandler, HandleChunkCallback, IStreamChunk } from '@redhat-cloud-services/ai-client-common';

class CustomStreamingHandler<TChunk = unknown> implements IStreamingHandler<TChunk> {
  onChunk(chunk: TChunk, handleChunk?: HandleChunkCallback): void {
    console.log('Received chunk:', chunk);
    
    // Process the chunk and call handleChunk with standardized format
    if (handleChunk) {
      handleChunk({
        answer: extractAnswer(chunk), // Extract answer from chunk
        additionalAttributes: extractAttributes(chunk) // Extract additional data
      });
    }
  }

  onStart?(conversationId?: string, messageId?: string): void {
    console.log('Stream started', { conversationId, messageId });
  }

  onComplete?(finalChunk: TChunk): void {
    console.log('Stream completed:', finalChunk);
  }

  onError?(error: Error): void {
    console.error('Stream error:', error);
  }

  onAbort?(): void {
    console.log('Stream aborted');
  }
}

Send Message Options

import { ISendMessageOptions, IStreamChunk } from '@redhat-cloud-services/ai-client-common';

// Basic streaming options
const streamingOptions: ISendMessageOptions = {
  stream: true,
  headers: { 'Custom-Header': 'value' },
  signal: abortController.signal,
  handleChunk: (chunk: IStreamChunk) => {
    // Process each standardized chunk as it arrives
    console.log('Answer:', chunk.answer);
    console.log('Message ID:', chunk.messageId);
    console.log('Conversation ID:', chunk.conversationId);
    console.log('Additional data:', chunk.additionalAttributes);
    updateUI(chunk.answer);
  }
};

// Options with custom request payload (client-specific)
const optionsWithPayload: ISendMessageOptions<AdditionalProps, CustomPayload> = {
  stream: false,
  headers: { 'X-Custom': 'value' },
  requestPayload: {
    // Client-specific payload data
    customData: 'value',
    options: { setting: true }
  }
};

Request Payload Support

The ISendMessageOptions interface supports method overloading to enable client-specific request payloads:

// Interface definition
export interface ISendMessageOptions<
  T extends Record<string, unknown> = Record<string, unknown>,
  R extends Record<string, unknown> = never
> extends IRequestOptions {
  stream?: boolean;
  handleChunk?: HandleChunkCallback<T>;
  requestPayload?: R extends never ? never : R;
}

// Usage with client-specific payload
interface MyClientPayload {
  context?: { systemInfo: string };
  skipCache?: boolean;
}

const response = await client.sendMessage(
  'conversation-id',
  'message',
  {
    requestPayload: {
      context: { systemInfo: 'linux' },
      skipCache: true
    }
  }
);

Error Handling

Base Error Classes

import { 
  AIClientError, 
  AIClientValidationError 
} from '@redhat-cloud-services/ai-client-common';

try {
  const response = await client.sendMessage(conversationId, message);
} catch (error) {
  if (error instanceof AIClientValidationError) {
    console.error('Validation errors:', error.validationErrors);
    error.validationErrors.forEach(validationError => {
      console.log(`Field: ${validationError.loc.join('.')}`);
      console.log(`Message: ${validationError.msg}`);
      console.log(`Type: ${validationError.type}`);
    });
  } else if (error instanceof AIClientError) {
    console.error(`API Error ${error.status}: ${error.message}`);
    console.error('Response data:', error.data);
  } else {
    console.error('Unexpected error:', error);
  }
}

Type Definitions

Request and Response Types

import { 
  IRequestOptions,
  IMessageResponse,
  IConversationHistoryResponse,
  IConversation
} from '@redhat-cloud-services/ai-client-common';

// Standard request options
const options: IRequestOptions = {
  headers: { 'Custom-Header': 'value' },
  signal: new AbortController().signal
};

// Message response structure
interface IMessageResponse<AP = Record<string, unknown>> {
  messageId: string;
  answer: string;
  conversationId: string;
  date?: Date;
  additionalAttributes?: AP;
}

// Conversation structure
interface IConversation {
  id: string;
  title: string;
  locked: boolean; // Prevents new messages when true
  createdAt: Date;
}

Compatible Packages

This package provides the foundation for:

Building

Run nx build ai-client-common to build the library.

Running unit tests

Run nx test ai-client-common to execute the unit tests via Jest.

Development

This package follows the workspace standards:

  • Strict TypeScript with no any types
  • Zero runtime dependencies
  • Comprehensive interface definitions