@nomyx/assistant
Version:
A powerful assistant library and cli for your AI projects. works with Vertex AI (Claude and Gemini)
120 lines (100 loc) • 3.93 kB
text/typescript
import { ChatMessage, ChatOptions, ProviderResponse } from '../../../types/chat';
import { Tool, GenericToolSchema, StandardizedToolCall } from '../../../types/tool';
import { IAIProvider, AIProviderMiddleware, AIProviderPlugin, ProviderCapabilities } from '../../../types/provider';
import { AnthropicProviderConfig } from '../../../types/provider';
import { AnthropicCacheKey } from './types';
import { AnthropicCache } from './cache';
import { chat } from './chat';
import { streamChat } from './streaming';
import { AnthropicConfig } from './config';
import { handleAnthropicError } from './errors';
import { ILogger } from '../../../types/common';
import { convertToolSchema, convertToolCall } from './tools';
export class AnthropicProvider implements IAIProvider {
private config: AnthropicConfig;
private cache: AnthropicCache;
private middleware: AIProviderMiddleware[] = [];
constructor(config: AnthropicProviderConfig, logger: ILogger) {
this.config = new AnthropicConfig(config, logger);
this.cache = new AnthropicCache();
}
async chat(messages: ChatMessage[], options: ChatOptions, tools?: Tool[]): Promise<ProviderResponse> {
try {
const cacheKey: AnthropicCacheKey = { messages, options, tools };
if (this.cache.has(cacheKey)) {
return this.cache.get(cacheKey)!;
}
let processedMessages = messages;
for (const mw of this.middleware) {
processedMessages = await mw.preProcess(processedMessages);
}
let response: ProviderResponse = await chat(this.config, processedMessages, options, tools);
for (const mw of this.middleware) {
response = await mw.postProcess(response);
}
if (response.toolCalls && response.toolCalls.length > 0) {
for (const mw of this.middleware) {
if (mw.processToolCalls) {
response.toolCalls = await mw.processToolCalls(response.toolCalls);
}
}
}
this.cache.set(cacheKey, response);
return response;
} catch (error) {
throw handleAnthropicError(error);
}
}
async *streamChat(messages: ChatMessage[], options: ChatOptions, tools?: Tool[]): AsyncIterableIterator<ProviderResponse> {
try {
let processedMessages = messages;
for (const mw of this.middleware) {
processedMessages = await mw.preProcess(processedMessages);
}
const stream = streamChat(this.config, processedMessages, options, tools);
for await (const chunk of stream) {
let processedChunk = chunk;
for (const mw of this.middleware) {
processedChunk = await mw.postProcess(processedChunk);
}
if (processedChunk.toolCalls && processedChunk.toolCalls.length > 0) {
for (const mw of this.middleware) {
if (mw.processToolCalls) {
processedChunk.toolCalls = await mw.processToolCalls(processedChunk.toolCalls);
}
}
}
yield processedChunk;
}
} catch (error) {
throw handleAnthropicError(error);
}
}
getCapabilities(): ProviderCapabilities {
return {
maxTokens: 100000, // Adjust based on Anthropic's actual limits
supportsFunctionCalling: true,
supportsStreaming: true,
supportedModels: [this.config.model],
maxSimultaneousCalls: 1, // Adjust based on Anthropic's rate limits
supportsSemanticCaching: false,
};
}
use(middleware: AIProviderMiddleware): void {
this.middleware.push(middleware);
}
registerPlugin(plugin: AIProviderPlugin): void {
plugin.initialize(this);
}
convertToolSchema(schema: GenericToolSchema): any {
return convertToolSchema(schema);
}
convertToolCall(call: any): StandardizedToolCall {
return convertToolCall(call);
}
clearCache(): void {
this.cache.clear();
}
}
export * from './types';
export { AnthropicProviderError } from './errors';