@juspay/neurolink 5.1.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -9
- package/README.md +123 -126
- package/dist/agent/direct-tools.d.ts +6 -6
- package/dist/cli/commands/config.d.ts +3 -3
- package/dist/cli/commands/mcp.js +8 -7
- package/dist/cli/factories/command-factory.d.ts +4 -0
- package/dist/cli/factories/command-factory.js +57 -3
- package/dist/cli/index.js +87 -140
- package/dist/core/base-provider.d.ts +423 -0
- package/dist/core/base-provider.js +365 -0
- package/dist/core/constants.d.ts +1 -1
- package/dist/core/constants.js +1 -1
- package/dist/core/dynamic-models.d.ts +6 -6
- package/dist/core/evaluation.d.ts +19 -80
- package/dist/core/evaluation.js +185 -484
- package/dist/core/factory.d.ts +3 -3
- package/dist/core/factory.js +31 -91
- package/dist/core/service-registry.d.ts +47 -0
- package/dist/core/service-registry.js +112 -0
- package/dist/core/types.d.ts +8 -1
- package/dist/factories/compatibility-factory.js +1 -1
- package/dist/factories/provider-factory.d.ts +72 -0
- package/dist/factories/provider-factory.js +144 -0
- package/dist/factories/provider-registry.d.ts +38 -0
- package/dist/factories/provider-registry.js +107 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +2 -4
- package/dist/lib/agent/direct-tools.d.ts +6 -6
- package/dist/lib/core/base-provider.d.ts +423 -0
- package/dist/lib/core/base-provider.js +365 -0
- package/dist/lib/core/constants.d.ts +1 -1
- package/dist/lib/core/constants.js +1 -1
- package/dist/lib/core/dynamic-models.d.ts +6 -6
- package/dist/lib/core/evaluation.d.ts +19 -80
- package/dist/lib/core/evaluation.js +185 -484
- package/dist/lib/core/factory.d.ts +3 -3
- package/dist/lib/core/factory.js +30 -91
- package/dist/lib/core/service-registry.d.ts +47 -0
- package/dist/lib/core/service-registry.js +112 -0
- package/dist/lib/core/types.d.ts +8 -1
- package/dist/lib/factories/compatibility-factory.js +1 -1
- package/dist/lib/factories/provider-factory.d.ts +72 -0
- package/dist/lib/factories/provider-factory.js +144 -0
- package/dist/lib/factories/provider-registry.d.ts +38 -0
- package/dist/lib/factories/provider-registry.js +107 -0
- package/dist/lib/index.d.ts +4 -3
- package/dist/lib/index.js +2 -4
- package/dist/lib/mcp/config.js +28 -3
- package/dist/lib/mcp/function-calling.js +1 -1
- package/dist/lib/mcp/initialize-tools.d.ts +1 -1
- package/dist/lib/mcp/initialize-tools.js +45 -1
- package/dist/lib/mcp/initialize.js +16 -6
- package/dist/lib/mcp/servers/agent/direct-tools-server.d.ts +8 -0
- package/dist/lib/mcp/servers/agent/direct-tools-server.js +109 -0
- package/dist/lib/mcp/servers/ai-providers/ai-core-server.js +3 -1
- package/dist/lib/mcp/servers/ai-providers/ai-workflow-tools.d.ts +2 -2
- package/dist/lib/mcp/unified-registry.d.ts +4 -0
- package/dist/lib/mcp/unified-registry.js +42 -9
- package/dist/lib/neurolink.d.ts +156 -117
- package/dist/lib/neurolink.js +619 -404
- package/dist/lib/providers/amazon-bedrock.d.ts +32 -0
- package/dist/lib/providers/amazon-bedrock.js +143 -0
- package/dist/lib/providers/analytics-helper.js +7 -4
- package/dist/lib/providers/anthropic-baseprovider.d.ts +23 -0
- package/dist/lib/providers/anthropic-baseprovider.js +114 -0
- package/dist/lib/providers/anthropic.d.ts +19 -43
- package/dist/lib/providers/anthropic.js +82 -306
- package/dist/lib/providers/azure-openai.d.ts +20 -0
- package/dist/lib/providers/azure-openai.js +89 -0
- package/dist/lib/providers/google-ai-studio.d.ts +23 -0
- package/dist/lib/providers/google-ai-studio.js +107 -0
- package/dist/lib/providers/google-vertex.d.ts +47 -0
- package/dist/lib/providers/google-vertex.js +205 -0
- package/dist/lib/providers/huggingFace.d.ts +32 -25
- package/dist/lib/providers/huggingFace.js +97 -431
- package/dist/lib/providers/index.d.ts +9 -9
- package/dist/lib/providers/index.js +9 -9
- package/dist/lib/providers/mcp-provider.js +4 -0
- package/dist/lib/providers/mistral.d.ts +42 -0
- package/dist/lib/providers/mistral.js +160 -0
- package/dist/lib/providers/ollama.d.ts +52 -36
- package/dist/lib/providers/ollama.js +297 -520
- package/dist/lib/providers/openAI.d.ts +19 -18
- package/dist/lib/providers/openAI.js +76 -275
- package/dist/lib/sdk/tool-extension.d.ts +181 -0
- package/dist/lib/sdk/tool-extension.js +283 -0
- package/dist/lib/sdk/tool-registration.d.ts +95 -0
- package/dist/lib/sdk/tool-registration.js +167 -0
- package/dist/lib/types/generate-types.d.ts +1 -0
- package/dist/lib/types/mcp-types.d.ts +116 -0
- package/dist/lib/types/mcp-types.js +5 -0
- package/dist/lib/types/stream-types.d.ts +30 -18
- package/dist/lib/types/universal-provider-options.d.ts +87 -0
- package/dist/lib/types/universal-provider-options.js +53 -0
- package/dist/mcp/config.js +28 -3
- package/dist/mcp/function-calling.js +1 -1
- package/dist/mcp/initialize-tools.d.ts +1 -1
- package/dist/mcp/initialize-tools.js +45 -1
- package/dist/mcp/initialize.js +16 -6
- package/dist/mcp/servers/agent/direct-tools-server.d.ts +8 -0
- package/dist/mcp/servers/agent/direct-tools-server.js +109 -0
- package/dist/mcp/servers/ai-providers/ai-core-server.js +3 -1
- package/dist/mcp/servers/ai-providers/ai-workflow-tools.d.ts +2 -2
- package/dist/mcp/unified-registry.d.ts +4 -0
- package/dist/mcp/unified-registry.js +42 -9
- package/dist/neurolink.d.ts +156 -117
- package/dist/neurolink.js +619 -404
- package/dist/providers/amazon-bedrock.d.ts +32 -0
- package/dist/providers/amazon-bedrock.js +143 -0
- package/dist/providers/analytics-helper.js +7 -4
- package/dist/providers/anthropic-baseprovider.d.ts +23 -0
- package/dist/providers/anthropic-baseprovider.js +114 -0
- package/dist/providers/anthropic.d.ts +19 -43
- package/dist/providers/anthropic.js +81 -305
- package/dist/providers/azure-openai.d.ts +20 -0
- package/dist/providers/azure-openai.js +89 -0
- package/dist/providers/google-ai-studio.d.ts +23 -0
- package/dist/providers/google-ai-studio.js +108 -0
- package/dist/providers/google-vertex.d.ts +47 -0
- package/dist/providers/google-vertex.js +205 -0
- package/dist/providers/huggingFace.d.ts +32 -25
- package/dist/providers/huggingFace.js +96 -430
- package/dist/providers/index.d.ts +9 -9
- package/dist/providers/index.js +9 -9
- package/dist/providers/mcp-provider.js +4 -0
- package/dist/providers/mistral.d.ts +42 -0
- package/dist/providers/mistral.js +160 -0
- package/dist/providers/ollama.d.ts +52 -36
- package/dist/providers/ollama.js +297 -519
- package/dist/providers/openAI.d.ts +19 -18
- package/dist/providers/openAI.js +76 -276
- package/dist/sdk/tool-extension.d.ts +181 -0
- package/dist/sdk/tool-extension.js +283 -0
- package/dist/sdk/tool-registration.d.ts +95 -0
- package/dist/sdk/tool-registration.js +168 -0
- package/dist/types/generate-types.d.ts +1 -0
- package/dist/types/mcp-types.d.ts +116 -0
- package/dist/types/mcp-types.js +5 -0
- package/dist/types/stream-types.d.ts +30 -18
- package/dist/types/universal-provider-options.d.ts +87 -0
- package/dist/types/universal-provider-options.js +53 -0
- package/package.json +15 -10
- package/dist/lib/providers/agent-enhanced-provider.d.ts +0 -93
- package/dist/lib/providers/agent-enhanced-provider.js +0 -605
- package/dist/lib/providers/amazonBedrock.d.ts +0 -28
- package/dist/lib/providers/amazonBedrock.js +0 -364
- package/dist/lib/providers/azureOpenAI.d.ts +0 -42
- package/dist/lib/providers/azureOpenAI.js +0 -347
- package/dist/lib/providers/googleAIStudio.d.ts +0 -42
- package/dist/lib/providers/googleAIStudio.js +0 -364
- package/dist/lib/providers/googleVertexAI.d.ts +0 -34
- package/dist/lib/providers/googleVertexAI.js +0 -547
- package/dist/lib/providers/mistralAI.d.ts +0 -37
- package/dist/lib/providers/mistralAI.js +0 -325
- package/dist/providers/agent-enhanced-provider.d.ts +0 -93
- package/dist/providers/agent-enhanced-provider.js +0 -606
- package/dist/providers/amazonBedrock.d.ts +0 -28
- package/dist/providers/amazonBedrock.js +0 -364
- package/dist/providers/azureOpenAI.d.ts +0 -42
- package/dist/providers/azureOpenAI.js +0 -348
- package/dist/providers/googleAIStudio.d.ts +0 -42
- package/dist/providers/googleAIStudio.js +0 -364
- package/dist/providers/googleVertexAI.d.ts +0 -34
- package/dist/providers/googleVertexAI.js +0 -547
- package/dist/providers/mistralAI.d.ts +0 -37
- package/dist/providers/mistralAI.js +0 -325
|
@@ -1,335 +1,111 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* Direct integration with Anthropic's Claude models via their native API.
|
|
5
|
-
* Supports Claude 3.5 Sonnet, Claude 3.5 Haiku, and Claude 3 Opus.
|
|
6
|
-
*/
|
|
7
|
-
import { AIProviderName } from "../core/types.js";
|
|
1
|
+
import { anthropic } from "@ai-sdk/anthropic";
|
|
2
|
+
import { streamText } from "ai";
|
|
3
|
+
import { BaseProvider } from "../core/base-provider.js";
|
|
8
4
|
import { logger } from "../utils/logger.js";
|
|
9
|
-
import { createTimeoutController, TimeoutError,
|
|
5
|
+
import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
|
|
10
6
|
import { DEFAULT_MAX_TOKENS } from "../core/constants.js";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
7
|
+
// Configuration helpers
|
|
8
|
+
const getAnthropicApiKey = () => {
|
|
9
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
10
|
+
if (!apiKey) {
|
|
11
|
+
throw new Error(`❌ Anthropic Provider Configuration Error\n\nMissing required environment variable: ANTHROPIC_API_KEY\n\n🔧 Step 1: Get Anthropic API Key\n1. Visit: https://console.anthropic.com/\n2. Sign in or create an account\n3. Go to API Keys section\n4. Create a new API key\n\n🔧 Step 2: Set Environment Variable\nAdd to your .env file:\nANTHROPIC_API_KEY=your_api_key_here\n\n🔧 Step 3: Restart Application\nRestart your application to load the new environment variables.`);
|
|
12
|
+
}
|
|
13
|
+
return apiKey;
|
|
14
|
+
};
|
|
15
|
+
const getDefaultAnthropicModel = () => {
|
|
16
|
+
return process.env.ANTHROPIC_MODEL || "claude-3-5-sonnet-20241022";
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Anthropic Provider v2 - BaseProvider Implementation
|
|
20
|
+
* Fixed syntax and enhanced with proper error handling
|
|
21
|
+
*/
|
|
22
|
+
export class AnthropicProvider extends BaseProvider {
|
|
23
|
+
model;
|
|
24
|
+
constructor(modelName, sdk) {
|
|
25
|
+
super(modelName, "anthropic", sdk);
|
|
26
|
+
// Initialize Anthropic model with API key validation
|
|
27
|
+
const apiKey = getAnthropicApiKey();
|
|
28
|
+
this.model = anthropic(this.modelName || getDefaultAnthropicModel());
|
|
29
|
+
logger.debug("Anthropic Provider v2 initialized", {
|
|
30
|
+
modelName: this.modelName,
|
|
31
|
+
provider: this.providerName,
|
|
32
|
+
});
|
|
26
33
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (!apiKey) {
|
|
30
|
-
throw new Error("ANTHROPIC_API_KEY environment variable is required");
|
|
31
|
-
}
|
|
32
|
-
return apiKey;
|
|
34
|
+
getProviderName() {
|
|
35
|
+
return "anthropic";
|
|
33
36
|
}
|
|
34
|
-
|
|
35
|
-
return
|
|
36
|
-
}
|
|
37
|
-
async makeRequest(endpoint, body, stream = false, signal) {
|
|
38
|
-
const url = `${this.baseURL}/v1/${endpoint}`;
|
|
39
|
-
const headers = {
|
|
40
|
-
"Content-Type": "application/json",
|
|
41
|
-
"x-api-key": this.apiKey,
|
|
42
|
-
"anthropic-version": "2023-06-01",
|
|
43
|
-
"anthropic-dangerous-direct-browser-access": "true", // Required for browser usage
|
|
44
|
-
};
|
|
45
|
-
logger.debug(`[AnthropicProvider.makeRequest] ${stream ? "Streaming" : "Non-streaming"} request to ${url}`);
|
|
46
|
-
logger.debug(`[AnthropicProvider.makeRequest] Model: ${body.model}, Max tokens: ${body.max_tokens}`);
|
|
47
|
-
const proxyFetch = createProxyFetch();
|
|
48
|
-
const response = await proxyFetch(url, {
|
|
49
|
-
method: "POST",
|
|
50
|
-
headers,
|
|
51
|
-
body: JSON.stringify(body),
|
|
52
|
-
signal, // Add abort signal for timeout support
|
|
53
|
-
});
|
|
54
|
-
if (!response.ok) {
|
|
55
|
-
const errorText = await response.text();
|
|
56
|
-
logger.error(`[AnthropicProvider.makeRequest] API error ${response.status}: ${errorText}`);
|
|
57
|
-
throw new Error(`Anthropic API error ${response.status}: ${errorText}`);
|
|
58
|
-
}
|
|
59
|
-
return response;
|
|
37
|
+
getDefaultModel() {
|
|
38
|
+
return getDefaultAnthropicModel();
|
|
60
39
|
}
|
|
61
40
|
/**
|
|
62
|
-
*
|
|
63
|
-
* Future-ready for multi-modal capabilities with current text focus
|
|
41
|
+
* Returns the Vercel AI SDK model instance for Anthropic
|
|
64
42
|
*/
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const options = typeof optionsOrPrompt === "string"
|
|
72
|
-
? { input: { text: optionsOrPrompt } }
|
|
73
|
-
: optionsOrPrompt;
|
|
74
|
-
// Validate input
|
|
75
|
-
if (!options?.input?.text ||
|
|
76
|
-
typeof options.input.text !== "string" ||
|
|
77
|
-
options.input.text.trim() === "") {
|
|
78
|
-
throw new Error("Stream options must include input.text as a non-empty string");
|
|
43
|
+
getAISDKModel() {
|
|
44
|
+
return this.model;
|
|
45
|
+
}
|
|
46
|
+
handleProviderError(error) {
|
|
47
|
+
if (error instanceof TimeoutError) {
|
|
48
|
+
return new Error(`Anthropic request timed out: ${error.message}`);
|
|
79
49
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// Create timeout controller if timeout is specified
|
|
84
|
-
const timeoutController = createTimeoutController(timeout, provider, "stream");
|
|
85
|
-
try {
|
|
86
|
-
const body = {
|
|
87
|
-
model: this.getModel(),
|
|
88
|
-
max_tokens: maxTokens,
|
|
89
|
-
messages: [
|
|
90
|
-
...(systemPrompt
|
|
91
|
-
? [{ role: "assistant", content: systemPrompt }]
|
|
92
|
-
: []),
|
|
93
|
-
{ role: "user", content: prompt },
|
|
94
|
-
],
|
|
95
|
-
temperature,
|
|
96
|
-
stream: true,
|
|
97
|
-
};
|
|
98
|
-
const response = await this.makeRequest("messages", body, true, timeoutController?.controller.signal);
|
|
99
|
-
const streamIterable = this.createAsyncIterable(response.body, timeoutController?.controller.signal);
|
|
100
|
-
// Clean up timeout controller
|
|
101
|
-
timeoutController?.cleanup();
|
|
102
|
-
logger.debug(`[${functionTag}] Stream initialized successfully`);
|
|
103
|
-
// Convert to StreamResult format
|
|
104
|
-
return {
|
|
105
|
-
stream: (async function* () {
|
|
106
|
-
for await (const chunk of streamIterable) {
|
|
107
|
-
yield { content: chunk };
|
|
108
|
-
}
|
|
109
|
-
})(),
|
|
110
|
-
provider: "anthropic",
|
|
111
|
-
model: this.getModel(),
|
|
112
|
-
metadata: {
|
|
113
|
-
streamId: `anthropic-${Date.now()}`,
|
|
114
|
-
startTime,
|
|
115
|
-
},
|
|
116
|
-
};
|
|
50
|
+
if (error?.message?.includes("API_KEY_INVALID") ||
|
|
51
|
+
error?.message?.includes("Invalid API key")) {
|
|
52
|
+
return new Error("Invalid Anthropic API key. Please check your ANTHROPIC_API_KEY environment variable.");
|
|
117
53
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
timeoutController?.cleanup();
|
|
121
|
-
if (error.name === "AbortError" || error.message.includes("timeout")) {
|
|
122
|
-
const timeoutError = new TimeoutError(`${provider} stream operation timed out after ${timeout}`, timeoutController?.timeoutMs || 0, provider, "stream");
|
|
123
|
-
logger.error(`[${functionTag}] Timeout error`, {
|
|
124
|
-
provider,
|
|
125
|
-
timeout: timeoutController?.timeoutMs,
|
|
126
|
-
message: timeoutError.message,
|
|
127
|
-
});
|
|
128
|
-
throw timeoutError;
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
logger.error(`[${functionTag}] Error:`, error);
|
|
132
|
-
}
|
|
133
|
-
throw error;
|
|
54
|
+
if (error?.message?.includes("rate limit")) {
|
|
55
|
+
return new Error("Anthropic rate limit exceeded. Please try again later.");
|
|
134
56
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
:
|
|
145
|
-
const { prompt, temperature = 0.7, maxTokens = DEFAULT_MAX_TOKENS, systemPrompt = "You are Claude, an AI assistant created by Anthropic. You are helpful, harmless, and honest.", timeout = getDefaultTimeout(provider, "generate"), enableAnalytics = false, enableEvaluation = false, context, } = options;
|
|
146
|
-
logger.debug(`[${functionTag}] Prompt: "${prompt.substring(0, 100)}...", Temperature: ${temperature}, Max tokens: ${maxTokens}, Timeout: ${timeout}`);
|
|
147
|
-
const requestBody = {
|
|
148
|
-
model: this.getModel(),
|
|
149
|
-
max_tokens: maxTokens,
|
|
150
|
-
messages: [
|
|
151
|
-
{
|
|
152
|
-
role: "user",
|
|
153
|
-
content: prompt,
|
|
154
|
-
},
|
|
155
|
-
],
|
|
156
|
-
temperature,
|
|
157
|
-
system: systemPrompt,
|
|
57
|
+
return new Error(`Anthropic error: ${error?.message || "Unknown error"}`);
|
|
58
|
+
}
|
|
59
|
+
// executeGenerate removed - BaseProvider handles all generation with tools
|
|
60
|
+
async executeStream(options, analysisSchema) {
|
|
61
|
+
// Convert StreamOptions to TextGenerationOptions for validation
|
|
62
|
+
const validationOptions = {
|
|
63
|
+
prompt: options.input.text,
|
|
64
|
+
systemPrompt: options.systemPrompt,
|
|
65
|
+
temperature: options.temperature,
|
|
66
|
+
maxTokens: options.maxTokens,
|
|
158
67
|
};
|
|
159
|
-
|
|
160
|
-
const
|
|
68
|
+
this.validateOptions(validationOptions);
|
|
69
|
+
const timeout = this.getTimeout(options);
|
|
70
|
+
const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
|
|
161
71
|
try {
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
provider: this.name,
|
|
171
|
-
model: data.model,
|
|
172
|
-
usage: {
|
|
173
|
-
promptTokens: data.usage.input_tokens,
|
|
174
|
-
completionTokens: data.usage.output_tokens,
|
|
175
|
-
totalTokens: data.usage.input_tokens + data.usage.output_tokens,
|
|
176
|
-
},
|
|
177
|
-
finishReason: data.stop_reason,
|
|
178
|
-
};
|
|
179
|
-
// Add analytics if enabled
|
|
180
|
-
if (options.enableAnalytics) {
|
|
181
|
-
result.analytics = createAnalytics(provider, this.defaultModel, result, Date.now() - startTime, options.context);
|
|
182
|
-
}
|
|
183
|
-
// Add evaluation if enabled
|
|
184
|
-
if (options.enableEvaluation) {
|
|
185
|
-
result.evaluation = await evaluateResponse(prompt, result.content, options.context);
|
|
186
|
-
}
|
|
187
|
-
return result;
|
|
188
|
-
}
|
|
189
|
-
catch (error) {
|
|
190
|
-
// Always cleanup timeout
|
|
72
|
+
const result = await streamText({
|
|
73
|
+
model: this.model,
|
|
74
|
+
prompt: options.input.text,
|
|
75
|
+
system: options.systemPrompt || undefined,
|
|
76
|
+
temperature: options.temperature,
|
|
77
|
+
maxTokens: options.maxTokens || DEFAULT_MAX_TOKENS,
|
|
78
|
+
abortSignal: timeoutController?.controller.signal,
|
|
79
|
+
});
|
|
191
80
|
timeoutController?.cleanup();
|
|
192
|
-
//
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
timeout: error.timeout,
|
|
197
|
-
message: error.message,
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
else if (error?.name === "AbortError") {
|
|
201
|
-
// Convert AbortError to TimeoutError
|
|
202
|
-
const timeoutError = new TimeoutError(`${provider} generate operation timed out after ${timeout}`, timeoutController?.timeoutMs || 0, provider, "generate");
|
|
203
|
-
logger.error(`[${functionTag}] Timeout error`, {
|
|
204
|
-
provider,
|
|
205
|
-
timeout: timeoutController?.timeoutMs,
|
|
206
|
-
message: timeoutError.message,
|
|
207
|
-
});
|
|
208
|
-
throw timeoutError;
|
|
209
|
-
}
|
|
210
|
-
else {
|
|
211
|
-
logger.error(`[${functionTag}] Error:`, error);
|
|
212
|
-
}
|
|
213
|
-
throw error;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* LEGACY METHOD: Use stream() instead for new code
|
|
218
|
-
* @deprecated Use stream() method instead
|
|
219
|
-
*/
|
|
220
|
-
async *createAsyncIterable(body, signal) {
|
|
221
|
-
const reader = body.getReader();
|
|
222
|
-
const decoder = new TextDecoder();
|
|
223
|
-
let buffer = "";
|
|
224
|
-
try {
|
|
225
|
-
while (true) {
|
|
226
|
-
// Check if aborted
|
|
227
|
-
if (signal?.aborted) {
|
|
228
|
-
throw new Error("AbortError");
|
|
229
|
-
}
|
|
230
|
-
const { done, value } = await reader.read();
|
|
231
|
-
if (done) {
|
|
232
|
-
break;
|
|
233
|
-
}
|
|
234
|
-
buffer += decoder.decode(value, { stream: true });
|
|
235
|
-
const lines = buffer.split("\n");
|
|
236
|
-
buffer = lines.pop() || "";
|
|
237
|
-
for (const line of lines) {
|
|
238
|
-
if (line.trim() === "") {
|
|
239
|
-
continue;
|
|
240
|
-
}
|
|
241
|
-
if (line.startsWith("data: ")) {
|
|
242
|
-
const data = line.slice(6);
|
|
243
|
-
if (data.trim() === "[DONE]") {
|
|
244
|
-
continue;
|
|
245
|
-
}
|
|
246
|
-
try {
|
|
247
|
-
const chunk = JSON.parse(data);
|
|
248
|
-
// Extract text content from different chunk types
|
|
249
|
-
if (chunk.type === "content_block_delta" && chunk.delta?.text) {
|
|
250
|
-
yield chunk.delta.text;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
catch (parseError) {
|
|
254
|
-
logger.warn("[AnthropicProvider.createAsyncIterable] Failed to parse chunk:", parseError);
|
|
255
|
-
continue;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
81
|
+
// Transform string stream to content object stream
|
|
82
|
+
const transformedStream = async function* () {
|
|
83
|
+
for await (const chunk of result.textStream) {
|
|
84
|
+
yield { content: chunk };
|
|
258
85
|
}
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
finally {
|
|
262
|
-
reader.releaseLock();
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
async testConnection() {
|
|
266
|
-
logger.debug("[AnthropicProvider.testConnection] Testing connection to Anthropic API");
|
|
267
|
-
const startTime = Date.now();
|
|
268
|
-
try {
|
|
269
|
-
await this.generate({
|
|
270
|
-
prompt: "Hello",
|
|
271
|
-
maxTokens: 5,
|
|
272
|
-
});
|
|
273
|
-
const responseTime = Date.now() - startTime;
|
|
274
|
-
logger.debug(`[AnthropicProvider.testConnection] Connection test successful (${responseTime}ms)`);
|
|
86
|
+
};
|
|
275
87
|
return {
|
|
276
|
-
|
|
277
|
-
|
|
88
|
+
stream: transformedStream(),
|
|
89
|
+
provider: this.providerName,
|
|
90
|
+
model: this.modelName,
|
|
278
91
|
};
|
|
279
92
|
}
|
|
280
93
|
catch (error) {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
return {
|
|
284
|
-
success: false,
|
|
285
|
-
error: error instanceof Error ? error.message : "Unknown error",
|
|
286
|
-
responseTime,
|
|
287
|
-
};
|
|
94
|
+
timeoutController?.cleanup();
|
|
95
|
+
throw this.handleProviderError(error);
|
|
288
96
|
}
|
|
289
97
|
}
|
|
290
|
-
|
|
98
|
+
async isAvailable() {
|
|
291
99
|
try {
|
|
292
|
-
|
|
100
|
+
getAnthropicApiKey();
|
|
293
101
|
return true;
|
|
294
102
|
}
|
|
295
103
|
catch {
|
|
296
104
|
return false;
|
|
297
105
|
}
|
|
298
106
|
}
|
|
299
|
-
|
|
300
|
-
return
|
|
301
|
-
}
|
|
302
|
-
getOptionalConfig() {
|
|
303
|
-
return ["ANTHROPIC_MODEL", "ANTHROPIC_BASE_URL"];
|
|
304
|
-
}
|
|
305
|
-
getModels() {
|
|
306
|
-
return [
|
|
307
|
-
"claude-3-5-sonnet-20241022",
|
|
308
|
-
"claude-3-5-haiku-20241022",
|
|
309
|
-
"claude-3-opus-20240229",
|
|
310
|
-
"claude-3-sonnet-20240229",
|
|
311
|
-
"claude-3-haiku-20240307",
|
|
312
|
-
];
|
|
313
|
-
}
|
|
314
|
-
supportsStreaming() {
|
|
315
|
-
return true;
|
|
316
|
-
}
|
|
317
|
-
supportsSchema() {
|
|
318
|
-
return false; // Anthropic doesn't have native JSON schema support like OpenAI
|
|
319
|
-
}
|
|
320
|
-
getCapabilities() {
|
|
321
|
-
return [
|
|
322
|
-
"text-generation",
|
|
323
|
-
"streaming",
|
|
324
|
-
"conversation",
|
|
325
|
-
"system-prompts",
|
|
326
|
-
"long-context", // Claude models support up to 200k tokens
|
|
327
|
-
];
|
|
328
|
-
}
|
|
329
|
-
/**
|
|
330
|
-
* Short alias for generate() - CLI-SDK consistency
|
|
331
|
-
*/
|
|
332
|
-
async gen(optionsOrPrompt, analysisSchema) {
|
|
333
|
-
return this.generate(optionsOrPrompt, analysisSchema);
|
|
107
|
+
getModel() {
|
|
108
|
+
return this.model;
|
|
334
109
|
}
|
|
335
110
|
}
|
|
111
|
+
export default AnthropicProvider;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BaseProvider } from "../core/base-provider.js";
|
|
2
|
+
import type { AIProviderName } from "../core/types.js";
|
|
3
|
+
import type { StreamOptions, StreamResult } from "../types/stream-types.js";
|
|
4
|
+
export declare class AzureOpenAIProvider extends BaseProvider {
|
|
5
|
+
private apiKey;
|
|
6
|
+
private resourceName;
|
|
7
|
+
private deployment;
|
|
8
|
+
private apiVersion;
|
|
9
|
+
private azureProvider;
|
|
10
|
+
constructor(modelName?: string);
|
|
11
|
+
protected getProviderName(): AIProviderName;
|
|
12
|
+
protected getDefaultModel(): string;
|
|
13
|
+
/**
|
|
14
|
+
* Returns the Vercel AI SDK model instance for Azure OpenAI
|
|
15
|
+
*/
|
|
16
|
+
protected getAISDKModel(): any;
|
|
17
|
+
protected handleProviderError(error: any): Error;
|
|
18
|
+
protected executeStream(options: StreamOptions, analysisSchema?: any): Promise<StreamResult>;
|
|
19
|
+
}
|
|
20
|
+
export default AzureOpenAIProvider;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { createAzure } from "@ai-sdk/azure";
|
|
2
|
+
import { streamText } from "ai";
|
|
3
|
+
import { BaseProvider } from "../core/base-provider.js";
|
|
4
|
+
export class AzureOpenAIProvider extends BaseProvider {
|
|
5
|
+
apiKey;
|
|
6
|
+
resourceName;
|
|
7
|
+
deployment;
|
|
8
|
+
apiVersion;
|
|
9
|
+
azureProvider;
|
|
10
|
+
constructor(modelName) {
|
|
11
|
+
super(modelName, "azure");
|
|
12
|
+
this.apiKey = process.env.AZURE_OPENAI_API_KEY || "";
|
|
13
|
+
const endpoint = process.env.AZURE_OPENAI_ENDPOINT || "";
|
|
14
|
+
this.resourceName = endpoint
|
|
15
|
+
.replace("https://", "")
|
|
16
|
+
.replace(/\/+$/, "") // Remove trailing slashes
|
|
17
|
+
.replace(".openai.azure.com", "");
|
|
18
|
+
this.deployment =
|
|
19
|
+
modelName ||
|
|
20
|
+
process.env.AZURE_OPENAI_DEPLOYMENT ||
|
|
21
|
+
process.env.AZURE_OPENAI_DEPLOYMENT_ID ||
|
|
22
|
+
"gpt-4o";
|
|
23
|
+
this.apiVersion = process.env.AZURE_API_VERSION || "2024-10-01-preview";
|
|
24
|
+
if (!this.apiKey) {
|
|
25
|
+
throw new Error("AZURE_OPENAI_API_KEY environment variable is required");
|
|
26
|
+
}
|
|
27
|
+
if (!this.resourceName) {
|
|
28
|
+
throw new Error("AZURE_OPENAI_ENDPOINT environment variable is required");
|
|
29
|
+
}
|
|
30
|
+
// Create the Azure provider instance
|
|
31
|
+
this.azureProvider = createAzure({
|
|
32
|
+
resourceName: this.resourceName,
|
|
33
|
+
apiKey: this.apiKey,
|
|
34
|
+
apiVersion: this.apiVersion,
|
|
35
|
+
});
|
|
36
|
+
console.log("Azure Vercel Provider initialized", {
|
|
37
|
+
deployment: this.deployment,
|
|
38
|
+
resourceName: this.resourceName,
|
|
39
|
+
provider: "azure-vercel",
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
getProviderName() {
|
|
43
|
+
return "azure";
|
|
44
|
+
}
|
|
45
|
+
getDefaultModel() {
|
|
46
|
+
return this.deployment;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Returns the Vercel AI SDK model instance for Azure OpenAI
|
|
50
|
+
*/
|
|
51
|
+
getAISDKModel() {
|
|
52
|
+
return this.azureProvider(this.deployment);
|
|
53
|
+
}
|
|
54
|
+
handleProviderError(error) {
|
|
55
|
+
if (error?.message?.includes("401")) {
|
|
56
|
+
return new Error("Invalid Azure OpenAI API key or endpoint.");
|
|
57
|
+
}
|
|
58
|
+
return new Error(`Azure OpenAI error: ${error?.message || "Unknown error"}`);
|
|
59
|
+
}
|
|
60
|
+
// executeGenerate removed - BaseProvider handles all generation with tools
|
|
61
|
+
async executeStream(options, analysisSchema) {
|
|
62
|
+
try {
|
|
63
|
+
const stream = await streamText({
|
|
64
|
+
model: this.azureProvider(this.deployment),
|
|
65
|
+
prompt: options.input?.text || "",
|
|
66
|
+
maxTokens: options.maxTokens || 1000,
|
|
67
|
+
temperature: options.temperature || 0.7,
|
|
68
|
+
system: options.systemPrompt,
|
|
69
|
+
});
|
|
70
|
+
return {
|
|
71
|
+
stream: (async function* () {
|
|
72
|
+
for await (const chunk of stream.textStream) {
|
|
73
|
+
yield { content: chunk };
|
|
74
|
+
}
|
|
75
|
+
})(),
|
|
76
|
+
provider: "azure",
|
|
77
|
+
model: this.deployment,
|
|
78
|
+
metadata: {
|
|
79
|
+
streamId: `azure-${Date.now()}`,
|
|
80
|
+
startTime: Date.now(),
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
throw this.handleProviderError(error);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export default AzureOpenAIProvider;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ZodType, ZodTypeDef } from "zod";
|
|
2
|
+
import { type Schema, type LanguageModelV1 } from "ai";
|
|
3
|
+
import type { AIProviderName } from "../core/types.js";
|
|
4
|
+
import type { StreamOptions, StreamResult } from "../types/stream-types.js";
|
|
5
|
+
import { BaseProvider } from "../core/base-provider.js";
|
|
6
|
+
/**
|
|
7
|
+
* Google AI Studio provider implementation using BaseProvider
|
|
8
|
+
* Migrated from original GoogleAIStudio class to new factory pattern
|
|
9
|
+
*/
|
|
10
|
+
export declare class GoogleAIStudioProvider extends BaseProvider {
|
|
11
|
+
constructor(modelName?: string, sdk?: any);
|
|
12
|
+
protected getProviderName(): AIProviderName;
|
|
13
|
+
protected getDefaultModel(): string;
|
|
14
|
+
/**
|
|
15
|
+
* 🔧 PHASE 2: Return AI SDK model instance for tool calling
|
|
16
|
+
*/
|
|
17
|
+
protected getAISDKModel(): LanguageModelV1;
|
|
18
|
+
protected handleProviderError(error: any): Error;
|
|
19
|
+
protected executeStream(options: StreamOptions, analysisSchema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>): Promise<StreamResult>;
|
|
20
|
+
private getApiKey;
|
|
21
|
+
private validateStreamOptions;
|
|
22
|
+
}
|
|
23
|
+
export default GoogleAIStudioProvider;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
2
|
+
import { streamText } from "ai";
|
|
3
|
+
import { GoogleAIModels } from "../core/types.js";
|
|
4
|
+
import { BaseProvider } from "../core/base-provider.js";
|
|
5
|
+
import { logger } from "../utils/logger.js";
|
|
6
|
+
import { createTimeoutController, TimeoutError, } from "../utils/timeout.js";
|
|
7
|
+
import { DEFAULT_MAX_TOKENS } from "../core/constants.js";
|
|
8
|
+
// Environment variable setup
|
|
9
|
+
if (!process.env.GOOGLE_GENERATIVE_AI_API_KEY &&
|
|
10
|
+
process.env.GOOGLE_AI_API_KEY) {
|
|
11
|
+
process.env.GOOGLE_GENERATIVE_AI_API_KEY = process.env.GOOGLE_AI_API_KEY;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Google AI Studio provider implementation using BaseProvider
|
|
15
|
+
* Migrated from original GoogleAIStudio class to new factory pattern
|
|
16
|
+
*/
|
|
17
|
+
export class GoogleAIStudioProvider extends BaseProvider {
|
|
18
|
+
constructor(modelName, sdk) {
|
|
19
|
+
super(modelName, "google-ai", sdk);
|
|
20
|
+
logger.debug("GoogleAIStudioProvider initialized", {
|
|
21
|
+
model: this.modelName,
|
|
22
|
+
provider: this.providerName,
|
|
23
|
+
sdkProvided: !!sdk,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
// ===================
|
|
27
|
+
// ABSTRACT METHOD IMPLEMENTATIONS
|
|
28
|
+
// ===================
|
|
29
|
+
getProviderName() {
|
|
30
|
+
return "google-ai";
|
|
31
|
+
}
|
|
32
|
+
getDefaultModel() {
|
|
33
|
+
return process.env.GOOGLE_AI_MODEL || GoogleAIModels.GEMINI_2_5_FLASH;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 🔧 PHASE 2: Return AI SDK model instance for tool calling
|
|
37
|
+
*/
|
|
38
|
+
getAISDKModel() {
|
|
39
|
+
const apiKey = this.getApiKey();
|
|
40
|
+
const google = createGoogleGenerativeAI({ apiKey });
|
|
41
|
+
return google(this.modelName);
|
|
42
|
+
}
|
|
43
|
+
handleProviderError(error) {
|
|
44
|
+
if (error instanceof TimeoutError) {
|
|
45
|
+
return new Error(`Google AI request timed out: ${error.message}`);
|
|
46
|
+
}
|
|
47
|
+
if (error?.message?.includes("API_KEY_INVALID")) {
|
|
48
|
+
return new Error("Invalid Google AI API key. Please check your GOOGLE_AI_API_KEY environment variable.");
|
|
49
|
+
}
|
|
50
|
+
if (error?.message?.includes("RATE_LIMIT_EXCEEDED")) {
|
|
51
|
+
return new Error("Google AI rate limit exceeded. Please try again later.");
|
|
52
|
+
}
|
|
53
|
+
return new Error(`Google AI error: ${error?.message || "Unknown error"}`);
|
|
54
|
+
}
|
|
55
|
+
// executeGenerate removed - BaseProvider handles all generation with tools
|
|
56
|
+
async executeStream(options, analysisSchema) {
|
|
57
|
+
this.validateStreamOptions(options);
|
|
58
|
+
const apiKey = this.getApiKey();
|
|
59
|
+
const google = createGoogleGenerativeAI({ apiKey });
|
|
60
|
+
const model = google(this.modelName);
|
|
61
|
+
const timeout = this.getTimeout(options);
|
|
62
|
+
const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
|
|
63
|
+
try {
|
|
64
|
+
const result = await streamText({
|
|
65
|
+
model,
|
|
66
|
+
prompt: options.input.text,
|
|
67
|
+
system: options.systemPrompt,
|
|
68
|
+
temperature: options.temperature,
|
|
69
|
+
maxTokens: options.maxTokens || DEFAULT_MAX_TOKENS,
|
|
70
|
+
tools: options.tools,
|
|
71
|
+
toolChoice: "auto",
|
|
72
|
+
abortSignal: timeoutController?.controller.signal,
|
|
73
|
+
});
|
|
74
|
+
timeoutController?.cleanup();
|
|
75
|
+
// Transform string stream to content object stream
|
|
76
|
+
const transformedStream = async function* () {
|
|
77
|
+
for await (const chunk of result.textStream) {
|
|
78
|
+
yield { content: chunk };
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
return {
|
|
82
|
+
stream: transformedStream(),
|
|
83
|
+
provider: this.providerName,
|
|
84
|
+
model: this.modelName,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
throw this.handleProviderError(error);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// ===================
|
|
92
|
+
// HELPER METHODS
|
|
93
|
+
// ===================
|
|
94
|
+
getApiKey() {
|
|
95
|
+
const apiKey = process.env.GOOGLE_AI_API_KEY || process.env.GOOGLE_GENERATIVE_AI_API_KEY;
|
|
96
|
+
if (!apiKey) {
|
|
97
|
+
throw new Error("GOOGLE_AI_API_KEY or GOOGLE_GENERATIVE_AI_API_KEY environment variable is not set");
|
|
98
|
+
}
|
|
99
|
+
return apiKey;
|
|
100
|
+
}
|
|
101
|
+
validateStreamOptions(options) {
|
|
102
|
+
if (!options.input?.text || options.input.text.trim().length === 0) {
|
|
103
|
+
throw new Error("Input text is required and cannot be empty");
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
export default GoogleAIStudioProvider;
|