@nomyx/assistant
Version:
A powerful assistant library and cli for your AI projects. works with Vertex AI (Claude and Gemini)
108 lines (95 loc) • 4.26 kB
text/typescript
import { ChatMessage, ChatOptions, ProviderResponse } from '../../../types/chat';
import { ProviderCapabilities } from '../../../types/provider';
import { Tool, GenericToolSchema, StandardizedToolCall } from '../../../types/tool';
import { ILogger } from '../../../types/common';
import { BaseProvider } from '../BaseProvider';
import { OpenRouterProviderConfig } from './types';
import { OpenRouterConfig } from './config';
import { OpenRouterCache } from './cache';
import { chat } from './chat';
import { streamChat } from './streaming';
import { embed, embedBatch } from './embedding';
import { convertToolSchema, convertToolCall } from './tools';
import { handleOpenRouterError, OpenRouterProviderError } from './errors';
export class OpenRouterProvider extends BaseProvider {
private config: OpenRouterConfig;
private cache: OpenRouterCache;
constructor(config: OpenRouterProviderConfig, logger: ILogger) {
super(logger);
this.config = new OpenRouterConfig(config, logger);
this.cache = new OpenRouterCache();
}
async chat(messages: ChatMessage[], options: ChatOptions, tools?: Tool[]): Promise<ProviderResponse> {
try {
const cacheKey = { messages, options, tools };
if (this.cache.has(cacheKey)) {
this.logger.debug('Cache hit for chat request');
return this.cache.get(cacheKey)!;
}
const processedMessages = await this.applyMiddleware(messages);
const response = await chat(this.config, processedMessages, options, tools);
const processedResponse = await this.applyMiddlewareToResponse(response);
if (processedResponse.toolCalls) {
processedResponse.toolCalls = await this.applyMiddlewareToToolCalls(processedResponse.toolCalls);
}
this.cache.set(cacheKey, processedResponse);
return processedResponse;
} catch (error: unknown) {
this.logger.error('Error in OpenRouterProvider chat', { error: error instanceof Error ? error.message : String(error) });
throw handleOpenRouterError(error);
}
}
async *streamChat(messages: ChatMessage[], options: ChatOptions, tools?: Tool[]): AsyncIterableIterator<ProviderResponse> {
try {
const processedMessages = await this.applyMiddleware(messages);
for await (const response of streamChat(this.config, processedMessages, options, tools)) {
const processedResponse = await this.applyMiddlewareToResponse(response);
if (processedResponse.toolCalls) {
processedResponse.toolCalls = await this.applyMiddlewareToToolCalls(processedResponse.toolCalls);
}
yield processedResponse;
}
} catch (error: unknown) {
this.logger.error('Error in OpenRouterProvider streamChat', { error: error instanceof Error ? error.message : String(error) });
throw handleOpenRouterError(error);
}
}
getCapabilities(): ProviderCapabilities {
return {
maxTokens: 4096, // This may vary depending on the specific model
supportsFunctionCalling: true,
supportsStreaming: true,
supportedModels: ['gpt-3.5-turbo', 'gpt-4', 'claude-2', 'palm-2'], // Add more supported models
maxSimultaneousCalls: 1,
supportsSemanticCaching: false,
};
}
async embed(text: string): Promise<number[]> {
try {
return await embed(this.config, text);
} catch (error: unknown) {
this.logger.error('Error in OpenRouterProvider embed', { error: error instanceof Error ? error.message : String(error) });
throw handleOpenRouterError(error);
}
}
async embedBatch(texts: string[]): Promise<number[][]> {
try {
return await embedBatch(this.config, texts);
} catch (error: unknown) {
this.logger.error('Error in OpenRouterProvider embedBatch', { error: error instanceof Error ? error.message : String(error) });
throw handleOpenRouterError(error);
}
}
convertToolSchema(schema: GenericToolSchema): any {
return convertToolSchema(schema);
}
convertToolCall(call: any): StandardizedToolCall {
return convertToolCall(call);
}
clearCache(): void {
this.cache.clear();
this.logger.debug('OpenRouterProvider cache cleared');
}
}
export * from './types';
export { OpenRouterProviderError } from './errors';