@juspay/neurolink
Version:
Universal AI Development Platform with working MCP integration, multi-provider support, and professional CLI. Built-in tools operational, 58+ external MCP servers discoverable. Connect to filesystem, GitHub, database operations, and more. Build, test, and
119 lines (118 loc) • 4.65 kB
JavaScript
import { anthropic } from "@ai-sdk/anthropic";
import { streamText, Output } from "ai";
import { BaseProvider } from "../core/baseProvider.js";
import { logger } from "../utils/logger.js";
import { createTimeoutController, TimeoutError, getDefaultTimeout, } from "../utils/timeout.js";
import { DEFAULT_MAX_TOKENS } from "../core/constants.js";
import { validateApiKey, createAnthropicConfig, getProviderModel, } from "../utils/providerConfig.js";
// Configuration helpers - now using consolidated utility
const getAnthropicApiKey = () => {
return validateApiKey(createAnthropicConfig());
};
const getDefaultAnthropicModel = () => {
return getProviderModel("ANTHROPIC_MODEL", "claude-3-5-sonnet-20241022");
};
/**
* Anthropic Provider v2 - BaseProvider Implementation
* Fixed syntax and enhanced with proper error handling
*/
export class AnthropicProvider extends BaseProvider {
model;
constructor(modelName, sdk) {
super(modelName, "anthropic", sdk);
// Initialize Anthropic model with API key validation
const apiKey = getAnthropicApiKey();
// Set Anthropic API key as environment variable (required by @ai-sdk/anthropic)
process.env.ANTHROPIC_API_KEY = apiKey;
// Initialize Anthropic with proper configuration
this.model = anthropic(this.modelName || getDefaultAnthropicModel());
logger.debug("Anthropic Provider v2 initialized", {
modelName: this.modelName,
provider: this.providerName,
});
}
getProviderName() {
return "anthropic";
}
getDefaultModel() {
return getDefaultAnthropicModel();
}
/**
* Returns the Vercel AI SDK model instance for Anthropic
*/
getAISDKModel() {
return this.model;
}
handleProviderError(error) {
if (error instanceof TimeoutError) {
return new Error(`Anthropic request timed out: ${error.message}`);
}
const errorRecord = error;
if ((typeof errorRecord?.message === "string" &&
errorRecord.message.includes("API_KEY_INVALID")) ||
(typeof errorRecord?.message === "string" &&
errorRecord.message.includes("Invalid API key"))) {
return new Error("Invalid Anthropic API key. Please check your ANTHROPIC_API_KEY environment variable.");
}
if (typeof errorRecord?.message === "string" &&
errorRecord.message.includes("rate limit")) {
return new Error("Anthropic rate limit exceeded. Please try again later.");
}
const message = typeof errorRecord?.message === "string"
? errorRecord.message
: "Unknown error";
return new Error(`Anthropic error: ${message}`);
}
// executeGenerate removed - BaseProvider handles all generation with tools
async executeStream(options, analysisSchema) {
// Convert StreamOptions to TextGenerationOptions for validation
const validationOptions = {
prompt: options.input.text,
systemPrompt: options.systemPrompt,
temperature: options.temperature,
maxTokens: options.maxTokens,
};
this.validateOptions(validationOptions);
const timeout = this.getTimeout(options);
const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
try {
const result = await streamText({
model: this.model,
prompt: options.input.text,
system: options.systemPrompt || undefined,
temperature: options.temperature,
maxTokens: options.maxTokens || DEFAULT_MAX_TOKENS,
abortSignal: timeoutController?.controller.signal,
});
timeoutController?.cleanup();
// Transform string stream to content object stream
const transformedStream = async function* () {
for await (const chunk of result.textStream) {
yield { content: chunk };
}
};
return {
stream: transformedStream(),
provider: this.providerName,
model: this.modelName,
};
}
catch (error) {
timeoutController?.cleanup();
throw this.handleProviderError(error);
}
}
async isAvailable() {
try {
getAnthropicApiKey();
return true;
}
catch {
return false;
}
}
getModel() {
return this.model;
}
}
export default AnthropicProvider;