@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.
Files changed (166) hide show
  1. package/CHANGELOG.md +15 -9
  2. package/README.md +123 -126
  3. package/dist/agent/direct-tools.d.ts +6 -6
  4. package/dist/cli/commands/config.d.ts +3 -3
  5. package/dist/cli/commands/mcp.js +8 -7
  6. package/dist/cli/factories/command-factory.d.ts +4 -0
  7. package/dist/cli/factories/command-factory.js +57 -3
  8. package/dist/cli/index.js +87 -140
  9. package/dist/core/base-provider.d.ts +423 -0
  10. package/dist/core/base-provider.js +365 -0
  11. package/dist/core/constants.d.ts +1 -1
  12. package/dist/core/constants.js +1 -1
  13. package/dist/core/dynamic-models.d.ts +6 -6
  14. package/dist/core/evaluation.d.ts +19 -80
  15. package/dist/core/evaluation.js +185 -484
  16. package/dist/core/factory.d.ts +3 -3
  17. package/dist/core/factory.js +31 -91
  18. package/dist/core/service-registry.d.ts +47 -0
  19. package/dist/core/service-registry.js +112 -0
  20. package/dist/core/types.d.ts +8 -1
  21. package/dist/factories/compatibility-factory.js +1 -1
  22. package/dist/factories/provider-factory.d.ts +72 -0
  23. package/dist/factories/provider-factory.js +144 -0
  24. package/dist/factories/provider-registry.d.ts +38 -0
  25. package/dist/factories/provider-registry.js +107 -0
  26. package/dist/index.d.ts +4 -3
  27. package/dist/index.js +2 -4
  28. package/dist/lib/agent/direct-tools.d.ts +6 -6
  29. package/dist/lib/core/base-provider.d.ts +423 -0
  30. package/dist/lib/core/base-provider.js +365 -0
  31. package/dist/lib/core/constants.d.ts +1 -1
  32. package/dist/lib/core/constants.js +1 -1
  33. package/dist/lib/core/dynamic-models.d.ts +6 -6
  34. package/dist/lib/core/evaluation.d.ts +19 -80
  35. package/dist/lib/core/evaluation.js +185 -484
  36. package/dist/lib/core/factory.d.ts +3 -3
  37. package/dist/lib/core/factory.js +30 -91
  38. package/dist/lib/core/service-registry.d.ts +47 -0
  39. package/dist/lib/core/service-registry.js +112 -0
  40. package/dist/lib/core/types.d.ts +8 -1
  41. package/dist/lib/factories/compatibility-factory.js +1 -1
  42. package/dist/lib/factories/provider-factory.d.ts +72 -0
  43. package/dist/lib/factories/provider-factory.js +144 -0
  44. package/dist/lib/factories/provider-registry.d.ts +38 -0
  45. package/dist/lib/factories/provider-registry.js +107 -0
  46. package/dist/lib/index.d.ts +4 -3
  47. package/dist/lib/index.js +2 -4
  48. package/dist/lib/mcp/config.js +28 -3
  49. package/dist/lib/mcp/function-calling.js +1 -1
  50. package/dist/lib/mcp/initialize-tools.d.ts +1 -1
  51. package/dist/lib/mcp/initialize-tools.js +45 -1
  52. package/dist/lib/mcp/initialize.js +16 -6
  53. package/dist/lib/mcp/servers/agent/direct-tools-server.d.ts +8 -0
  54. package/dist/lib/mcp/servers/agent/direct-tools-server.js +109 -0
  55. package/dist/lib/mcp/servers/ai-providers/ai-core-server.js +3 -1
  56. package/dist/lib/mcp/servers/ai-providers/ai-workflow-tools.d.ts +2 -2
  57. package/dist/lib/mcp/unified-registry.d.ts +4 -0
  58. package/dist/lib/mcp/unified-registry.js +42 -9
  59. package/dist/lib/neurolink.d.ts +156 -117
  60. package/dist/lib/neurolink.js +619 -404
  61. package/dist/lib/providers/amazon-bedrock.d.ts +32 -0
  62. package/dist/lib/providers/amazon-bedrock.js +143 -0
  63. package/dist/lib/providers/analytics-helper.js +7 -4
  64. package/dist/lib/providers/anthropic-baseprovider.d.ts +23 -0
  65. package/dist/lib/providers/anthropic-baseprovider.js +114 -0
  66. package/dist/lib/providers/anthropic.d.ts +19 -43
  67. package/dist/lib/providers/anthropic.js +82 -306
  68. package/dist/lib/providers/azure-openai.d.ts +20 -0
  69. package/dist/lib/providers/azure-openai.js +89 -0
  70. package/dist/lib/providers/google-ai-studio.d.ts +23 -0
  71. package/dist/lib/providers/google-ai-studio.js +107 -0
  72. package/dist/lib/providers/google-vertex.d.ts +47 -0
  73. package/dist/lib/providers/google-vertex.js +205 -0
  74. package/dist/lib/providers/huggingFace.d.ts +32 -25
  75. package/dist/lib/providers/huggingFace.js +97 -431
  76. package/dist/lib/providers/index.d.ts +9 -9
  77. package/dist/lib/providers/index.js +9 -9
  78. package/dist/lib/providers/mcp-provider.js +4 -0
  79. package/dist/lib/providers/mistral.d.ts +42 -0
  80. package/dist/lib/providers/mistral.js +160 -0
  81. package/dist/lib/providers/ollama.d.ts +52 -36
  82. package/dist/lib/providers/ollama.js +297 -520
  83. package/dist/lib/providers/openAI.d.ts +19 -18
  84. package/dist/lib/providers/openAI.js +76 -275
  85. package/dist/lib/sdk/tool-extension.d.ts +181 -0
  86. package/dist/lib/sdk/tool-extension.js +283 -0
  87. package/dist/lib/sdk/tool-registration.d.ts +95 -0
  88. package/dist/lib/sdk/tool-registration.js +167 -0
  89. package/dist/lib/types/generate-types.d.ts +1 -0
  90. package/dist/lib/types/mcp-types.d.ts +116 -0
  91. package/dist/lib/types/mcp-types.js +5 -0
  92. package/dist/lib/types/stream-types.d.ts +30 -18
  93. package/dist/lib/types/universal-provider-options.d.ts +87 -0
  94. package/dist/lib/types/universal-provider-options.js +53 -0
  95. package/dist/mcp/config.js +28 -3
  96. package/dist/mcp/function-calling.js +1 -1
  97. package/dist/mcp/initialize-tools.d.ts +1 -1
  98. package/dist/mcp/initialize-tools.js +45 -1
  99. package/dist/mcp/initialize.js +16 -6
  100. package/dist/mcp/servers/agent/direct-tools-server.d.ts +8 -0
  101. package/dist/mcp/servers/agent/direct-tools-server.js +109 -0
  102. package/dist/mcp/servers/ai-providers/ai-core-server.js +3 -1
  103. package/dist/mcp/servers/ai-providers/ai-workflow-tools.d.ts +2 -2
  104. package/dist/mcp/unified-registry.d.ts +4 -0
  105. package/dist/mcp/unified-registry.js +42 -9
  106. package/dist/neurolink.d.ts +156 -117
  107. package/dist/neurolink.js +619 -404
  108. package/dist/providers/amazon-bedrock.d.ts +32 -0
  109. package/dist/providers/amazon-bedrock.js +143 -0
  110. package/dist/providers/analytics-helper.js +7 -4
  111. package/dist/providers/anthropic-baseprovider.d.ts +23 -0
  112. package/dist/providers/anthropic-baseprovider.js +114 -0
  113. package/dist/providers/anthropic.d.ts +19 -43
  114. package/dist/providers/anthropic.js +81 -305
  115. package/dist/providers/azure-openai.d.ts +20 -0
  116. package/dist/providers/azure-openai.js +89 -0
  117. package/dist/providers/google-ai-studio.d.ts +23 -0
  118. package/dist/providers/google-ai-studio.js +108 -0
  119. package/dist/providers/google-vertex.d.ts +47 -0
  120. package/dist/providers/google-vertex.js +205 -0
  121. package/dist/providers/huggingFace.d.ts +32 -25
  122. package/dist/providers/huggingFace.js +96 -430
  123. package/dist/providers/index.d.ts +9 -9
  124. package/dist/providers/index.js +9 -9
  125. package/dist/providers/mcp-provider.js +4 -0
  126. package/dist/providers/mistral.d.ts +42 -0
  127. package/dist/providers/mistral.js +160 -0
  128. package/dist/providers/ollama.d.ts +52 -36
  129. package/dist/providers/ollama.js +297 -519
  130. package/dist/providers/openAI.d.ts +19 -18
  131. package/dist/providers/openAI.js +76 -276
  132. package/dist/sdk/tool-extension.d.ts +181 -0
  133. package/dist/sdk/tool-extension.js +283 -0
  134. package/dist/sdk/tool-registration.d.ts +95 -0
  135. package/dist/sdk/tool-registration.js +168 -0
  136. package/dist/types/generate-types.d.ts +1 -0
  137. package/dist/types/mcp-types.d.ts +116 -0
  138. package/dist/types/mcp-types.js +5 -0
  139. package/dist/types/stream-types.d.ts +30 -18
  140. package/dist/types/universal-provider-options.d.ts +87 -0
  141. package/dist/types/universal-provider-options.js +53 -0
  142. package/package.json +15 -10
  143. package/dist/lib/providers/agent-enhanced-provider.d.ts +0 -93
  144. package/dist/lib/providers/agent-enhanced-provider.js +0 -605
  145. package/dist/lib/providers/amazonBedrock.d.ts +0 -28
  146. package/dist/lib/providers/amazonBedrock.js +0 -364
  147. package/dist/lib/providers/azureOpenAI.d.ts +0 -42
  148. package/dist/lib/providers/azureOpenAI.js +0 -347
  149. package/dist/lib/providers/googleAIStudio.d.ts +0 -42
  150. package/dist/lib/providers/googleAIStudio.js +0 -364
  151. package/dist/lib/providers/googleVertexAI.d.ts +0 -34
  152. package/dist/lib/providers/googleVertexAI.js +0 -547
  153. package/dist/lib/providers/mistralAI.d.ts +0 -37
  154. package/dist/lib/providers/mistralAI.js +0 -325
  155. package/dist/providers/agent-enhanced-provider.d.ts +0 -93
  156. package/dist/providers/agent-enhanced-provider.js +0 -606
  157. package/dist/providers/amazonBedrock.d.ts +0 -28
  158. package/dist/providers/amazonBedrock.js +0 -364
  159. package/dist/providers/azureOpenAI.d.ts +0 -42
  160. package/dist/providers/azureOpenAI.js +0 -348
  161. package/dist/providers/googleAIStudio.d.ts +0 -42
  162. package/dist/providers/googleAIStudio.js +0 -364
  163. package/dist/providers/googleVertexAI.d.ts +0 -34
  164. package/dist/providers/googleVertexAI.js +0 -547
  165. package/dist/providers/mistralAI.d.ts +0 -37
  166. package/dist/providers/mistralAI.js +0 -325
@@ -1,470 +1,136 @@
1
- import { HfInference } from "@huggingface/inference";
2
- import { streamText, generateText, Output, } from "ai";
1
+ import { createOpenAI } from "@ai-sdk/openai";
2
+ import { streamText, Output } from "ai";
3
+ import { BaseProvider } from "../core/base-provider.js";
3
4
  import { logger } from "../utils/logger.js";
4
5
  import { createTimeoutController, TimeoutError, getDefaultTimeout, } from "../utils/timeout.js";
5
6
  import { DEFAULT_MAX_TOKENS } from "../core/constants.js";
6
- import { evaluateResponse } from "../core/evaluation.js";
7
- // Default system context
8
- const DEFAULT_SYSTEM_CONTEXT = {
9
- systemPrompt: "You are a helpful AI assistant.",
10
- };
11
7
  // Configuration helpers
12
8
  const getHuggingFaceApiKey = () => {
13
9
  const apiKey = process.env.HUGGINGFACE_API_KEY || process.env.HF_TOKEN;
14
10
  if (!apiKey) {
15
- throw new Error("HUGGINGFACE_API_KEY environment variable is not set");
11
+ throw new Error(`❌ HuggingFace Provider Configuration Error\n\nMissing required environment variables: HUGGINGFACE_API_KEY\n\n🔧 Step 1: Get Credentials\n1. Visit: https://huggingface.co/settings/tokens\n2. Create new API token\n3. Copy the token\n\n🔧 Step 2: Set Environment Variable\nAdd to your .env file:\nHUGGINGFACE_API_KEY=your_token_here\n\n🔧 Step 3: Restart Application\nRestart your application to load the new environment variables.`);
16
12
  }
17
13
  return apiKey;
18
14
  };
19
- const getHuggingFaceModelId = () => {
15
+ const getDefaultHuggingFaceModel = () => {
20
16
  return process.env.HUGGINGFACE_MODEL || "microsoft/DialoGPT-medium";
21
17
  };
22
- const hasValidAuth = () => {
18
+ const hasHuggingFaceCredentials = () => {
23
19
  return !!(process.env.HUGGINGFACE_API_KEY || process.env.HF_TOKEN);
24
20
  };
25
- // Lazy initialization cache
26
- let _hfClient = null;
27
- function getHuggingFaceClient() {
28
- if (!_hfClient) {
21
+ /**
22
+ * HuggingFace Provider - BaseProvider Implementation
23
+ * Using AI SDK with HuggingFace's OpenAI-compatible endpoint
24
+ */
25
+ export class HuggingFaceProvider extends BaseProvider {
26
+ model;
27
+ constructor(modelName) {
28
+ super(modelName, "huggingface");
29
+ // Get API key and validate
29
30
  const apiKey = getHuggingFaceApiKey();
30
- _hfClient = new HfInference(apiKey);
31
- }
32
- return _hfClient;
33
- }
34
- // Retry configuration for model loading
35
- const RETRY_CONFIG = {
36
- maxRetries: 3,
37
- baseDelay: 2000, // 2 seconds
38
- maxDelay: 30000, // 30 seconds
39
- backoffMultiplier: 2,
40
- };
41
- // Helper function for exponential backoff retry
42
- async function retryWithBackoff(operation, retryConfig = RETRY_CONFIG) {
43
- let lastError;
44
- for (let attempt = 0; attempt <= retryConfig.maxRetries; attempt++) {
45
- try {
46
- return await operation();
47
- }
48
- catch (error) {
49
- lastError = error;
50
- // Check if it's a model loading error (503 status)
51
- if (error instanceof Error && error.message.includes("503")) {
52
- if (attempt < retryConfig.maxRetries) {
53
- const delay = Math.min(retryConfig.baseDelay *
54
- Math.pow(retryConfig.backoffMultiplier, attempt), retryConfig.maxDelay);
55
- logger.debug("HuggingFace model loading, retrying...", {
56
- attempt: attempt + 1,
57
- maxRetries: retryConfig.maxRetries,
58
- delayMs: delay,
59
- error: error.message,
60
- });
61
- await new Promise((resolve) => setTimeout(resolve, delay));
62
- continue;
63
- }
64
- }
65
- // For non-503 errors or final attempt, throw immediately
66
- throw error;
67
- }
68
- }
69
- throw lastError;
70
- }
71
- // Custom LanguageModelV1 implementation for Hugging Face
72
- class HuggingFaceLanguageModel {
73
- specificationVersion = "v1";
74
- provider = "huggingface";
75
- modelId;
76
- maxTokens;
77
- supportsStreaming = true;
78
- defaultObjectGenerationMode = "json";
79
- client;
80
- constructor(modelId, client) {
81
- this.modelId = modelId;
82
- this.client = client;
83
- }
84
- estimateTokens(text) {
85
- return Math.ceil(text.length / 4); // Rough estimation: 4 characters per token
86
- }
87
- convertMessagesToPrompt(messages) {
88
- return messages
89
- .map((msg) => {
90
- if (typeof msg.content === "string") {
91
- return `${msg.role}: ${msg.content}`;
92
- }
93
- else if (Array.isArray(msg.content)) {
94
- // Handle multi-part content (text, images, etc.)
95
- return `${msg.role}: ${msg.content
96
- .filter((part) => part.type === "text")
97
- .map((part) => part.text)
98
- .join(" ")}`;
99
- }
100
- return "";
101
- })
102
- .join("\n");
103
- }
104
- async doGenerate(options) {
105
- const prompt = this.convertMessagesToPrompt(options.prompt);
106
- const response = await retryWithBackoff(async () => {
107
- return await this.client.textGeneration({
108
- model: this.modelId,
109
- inputs: prompt,
110
- parameters: {
111
- temperature: options.temperature || 0.7,
112
- max_new_tokens: options.maxTokens ?? DEFAULT_MAX_TOKENS,
113
- return_full_text: false,
114
- do_sample: (options.temperature || 0.7) > 0,
115
- },
116
- });
31
+ // Create HuggingFace provider using unified router endpoint (2025)
32
+ const huggingface = createOpenAI({
33
+ apiKey: apiKey,
34
+ baseURL: "https://router.huggingface.co/v1",
117
35
  });
118
- const generatedText = response.generated_text || "";
119
- const promptTokens = this.estimateTokens(prompt);
120
- const completionTokens = this.estimateTokens(generatedText);
121
- return {
122
- text: generatedText,
123
- usage: {
124
- promptTokens,
125
- completionTokens,
126
- totalTokens: promptTokens + completionTokens,
127
- },
128
- finishReason: "stop",
129
- logprobs: undefined,
130
- rawCall: { rawPrompt: prompt, rawSettings: options },
131
- rawResponse: { headers: {} },
132
- };
133
- }
134
- async doStream(options) {
135
- const prompt = this.convertMessagesToPrompt(options.prompt);
136
- // HuggingFace Inference API doesn't support true streaming
137
- // We'll simulate streaming by generating the full text and chunking it
138
- const response = await this.doGenerate(options);
139
- // Create a ReadableStream that chunks the response
140
- const stream = new ReadableStream({
141
- start(controller) {
142
- const text = response.text || "";
143
- const chunkSize = Math.max(1, Math.floor(text.length / 10)); // 10 chunks
144
- let index = 0;
145
- const pushChunk = () => {
146
- if (index < text.length) {
147
- const chunk = text.slice(index, index + chunkSize);
148
- controller.enqueue({
149
- type: "text-delta",
150
- textDelta: chunk,
151
- });
152
- index += chunkSize;
153
- // Add delay to simulate streaming
154
- setTimeout(pushChunk, 50);
155
- }
156
- else {
157
- // Send finish event
158
- controller.enqueue({
159
- type: "finish",
160
- finishReason: response.finishReason,
161
- usage: response.usage,
162
- logprobs: response.logprobs,
163
- });
164
- controller.close();
165
- }
166
- };
167
- pushChunk();
168
- },
36
+ // Initialize model
37
+ this.model = huggingface(this.modelName);
38
+ logger.debug("HuggingFaceProvider initialized", {
39
+ model: this.modelName,
40
+ provider: this.providerName,
169
41
  });
170
- return {
171
- stream,
172
- rawCall: response.rawCall,
173
- rawResponse: response.rawResponse,
174
- };
175
- }
176
- }
177
- // Hugging Face class with enhanced error handling
178
- export class HuggingFace {
179
- modelName;
180
- client;
181
- /**
182
- * Initializes a new instance of HuggingFace
183
- * @param modelName - Optional model name to override the default from config
184
- */
185
- constructor(modelName) {
186
- const functionTag = "HuggingFace.constructor";
187
- this.modelName = modelName || getHuggingFaceModelId();
188
- try {
189
- this.client = getHuggingFaceClient();
190
- logger.debug(`[${functionTag}] Initialization started`, {
191
- modelName: this.modelName,
192
- hasApiKey: hasValidAuth(),
193
- });
194
- logger.debug(`[${functionTag}] Initialization completed`, {
195
- modelName: this.modelName,
196
- success: true,
197
- });
198
- }
199
- catch (err) {
200
- logger.error(`[${functionTag}] Initialization failed`, {
201
- message: "Error in initializing Hugging Face",
202
- modelName: this.modelName,
203
- error: err instanceof Error ? err.message : String(err),
204
- stack: err instanceof Error ? err.stack : undefined,
205
- });
206
- throw err;
207
- }
208
42
  }
43
+ // ===================
44
+ // ABSTRACT METHOD IMPLEMENTATIONS
45
+ // ===================
209
46
  /**
210
- * Gets the appropriate model instance
211
- * @private
47
+ * HuggingFace models currently don't properly support tool/function calling
48
+ *
49
+ * **Tested Models & Issues:**
50
+ * - microsoft/DialoGPT-medium: Describes tools instead of executing them
51
+ * - Most HF models via router endpoint: Function schema passed but not executed
52
+ * - Issue: Models treat tool definitions as conversation context rather than executable functions
53
+ *
54
+ * **Known Limitations:**
55
+ * - Tools are visible to model but treated as descriptive text
56
+ * - No proper function call response format handling
57
+ * - HuggingFace router endpoint doesn't enforce OpenAI-compatible tool execution
58
+ *
59
+ * @returns false to disable tools by default until proper implementation
212
60
  */
213
- getModel() {
214
- logger.debug("HuggingFace.getModel - Hugging Face model selected", {
215
- modelName: this.modelName,
216
- });
217
- return new HuggingFaceLanguageModel(this.modelName, this.client);
61
+ supportsTools() {
62
+ // TODO: Implement proper HuggingFace tool calling support
63
+ // Requires: Custom tool schema formatting, response parsing, execution flow
64
+ // Track models that support function calling: CodeLlama, Llama variants
65
+ return false;
218
66
  }
219
- /**
220
- * PRIMARY METHOD: Stream content using AI (recommended for new code)
221
- * Future-ready for multi-modal capabilities with current text focus
222
- */
223
- async stream(optionsOrPrompt, analysisSchema) {
224
- const functionTag = "HuggingFace.stream";
225
- const provider = "huggingface";
226
- let chunkCount = 0;
227
- const startTime = Date.now();
67
+ // executeGenerate removed - BaseProvider handles all generation with tools
68
+ async executeStream(options, analysisSchema) {
69
+ this.validateStreamOptions(options);
70
+ const timeout = this.getTimeout(options);
71
+ const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
228
72
  try {
229
- // Parse parameters - support both string and options object
230
- const options = typeof optionsOrPrompt === "string"
231
- ? { input: { text: optionsOrPrompt } }
232
- : optionsOrPrompt;
233
- // Validate input
234
- if (!options?.input?.text ||
235
- typeof options.input.text !== "string" ||
236
- options.input.text.trim() === "") {
237
- throw new Error("Stream options must include input.text as a non-empty string");
238
- }
239
- // Convert StreamOptions for internal use
240
- const convertedOptions = {
73
+ const result = await streamText({
74
+ model: this.model,
241
75
  prompt: options.input.text,
242
- provider: options.provider,
243
- model: options.model,
76
+ system: options.systemPrompt,
244
77
  temperature: options.temperature,
245
- maxTokens: options.maxTokens,
246
- systemPrompt: options.systemPrompt,
247
- timeout: options.timeout,
248
- schema: options.schema,
78
+ maxTokens: options.maxTokens || DEFAULT_MAX_TOKENS,
249
79
  tools: options.tools,
250
- };
251
- const { prompt, temperature = 0.7, maxTokens = DEFAULT_MAX_TOKENS, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema, timeout = getDefaultTimeout(provider, "stream"), } = convertedOptions;
252
- // Use schema from options or fallback parameter
253
- const finalSchema = schema || analysisSchema;
254
- logger.debug(`[${functionTag}] Stream request started`, {
255
- provider,
256
- modelName: this.modelName,
257
- promptLength: prompt.length,
258
- temperature,
259
- maxTokens,
260
- hasSchema: !!finalSchema,
261
- timeout,
80
+ toolChoice: "auto",
81
+ abortSignal: timeoutController?.controller.signal,
262
82
  });
263
- const model = this.getModel();
264
- // Create timeout controller if timeout is specified
265
- const timeoutController = createTimeoutController(timeout, provider, "stream");
266
- const streamOptions = {
267
- model: model,
268
- prompt: prompt,
269
- system: systemPrompt,
270
- temperature,
271
- maxTokens,
272
- // Add abort signal if available
273
- ...(timeoutController && {
274
- abortSignal: timeoutController.controller.signal,
275
- }),
276
- onError: (event) => {
277
- const error = event.error;
278
- const errorMessage = error instanceof Error ? error.message : String(error);
279
- const errorStack = error instanceof Error ? error.stack : undefined;
280
- logger.error(`[${functionTag}] Stream error`, {
281
- provider,
282
- modelName: this.modelName,
283
- error: errorMessage,
284
- stack: errorStack,
285
- promptLength: prompt.length,
286
- chunkCount,
287
- });
288
- },
289
- onFinish: (event) => {
290
- logger.debug(`[${functionTag}] Stream finished`, {
291
- provider,
292
- modelName: this.modelName,
293
- finishReason: event.finishReason,
294
- usage: event.usage,
295
- totalChunks: chunkCount,
296
- promptLength: prompt.length,
297
- responseLength: event.text?.length || 0,
298
- });
299
- },
300
- onChunk: (event) => {
301
- chunkCount++;
302
- logger.debug(`[${functionTag}] Stream chunk`, {
303
- provider,
304
- modelName: this.modelName,
305
- chunkNumber: chunkCount,
306
- chunkLength: event.chunk.text?.length || 0,
307
- chunkType: event.chunk.type,
308
- });
309
- },
83
+ timeoutController?.cleanup();
84
+ // Transform stream to match StreamResult interface
85
+ const transformedStream = async function* () {
86
+ for await (const chunk of result.textStream) {
87
+ yield { content: chunk };
88
+ }
310
89
  };
311
- if (finalSchema) {
312
- streamOptions.experimental_output = Output.object({
313
- schema: finalSchema,
314
- });
315
- }
316
- const result = streamText(streamOptions);
317
- // Convert to StreamResult format
318
90
  return {
319
- stream: (async function* () {
320
- for await (const chunk of result.textStream) {
321
- yield { content: chunk };
322
- }
323
- })(),
324
- provider: "huggingface",
91
+ stream: transformedStream(),
92
+ provider: this.providerName,
325
93
  model: this.modelName,
326
- metadata: {
327
- streamId: `huggingface-${Date.now()}`,
328
- startTime,
329
- },
330
94
  };
331
95
  }
332
- catch (err) {
333
- // Log timeout errors specifically
334
- if (err instanceof TimeoutError) {
335
- logger.error(`[${functionTag}] Timeout error`, {
336
- provider,
337
- modelName: this.modelName,
338
- timeout: err.timeout,
339
- message: err.message,
340
- });
341
- }
342
- else {
343
- logger.error(`[${functionTag}] Exception`, {
344
- provider,
345
- modelName: this.modelName,
346
- message: "Error in streaming content",
347
- err: String(err),
348
- promptLength: typeof optionsOrPrompt === "string"
349
- ? optionsOrPrompt.length
350
- : optionsOrPrompt.input?.text?.length || 0,
351
- });
352
- }
353
- throw err; // Re-throw error to trigger fallback
96
+ catch (error) {
97
+ timeoutController?.cleanup();
98
+ throw this.handleProviderError(error);
354
99
  }
355
100
  }
101
+ getProviderName() {
102
+ return "huggingface";
103
+ }
104
+ getDefaultModel() {
105
+ return getDefaultHuggingFaceModel();
106
+ }
356
107
  /**
357
- * Processes text using non-streaming approach with optional schema validation
358
- * @param prompt - The input text prompt to analyze
359
- * @param analysisSchema - Optional Zod schema or Schema object for output validation
360
- * @returns Promise resolving to GenerateResult or null if operation fails
108
+ * Returns the Vercel AI SDK model instance for HuggingFace
361
109
  */
362
- async generate(optionsOrPrompt, analysisSchema) {
363
- const functionTag = "HuggingFace.generate";
364
- const provider = "huggingface";
365
- const startTime = Date.now();
366
- try {
367
- // Parse parameters - support both string and options object
368
- const options = typeof optionsOrPrompt === "string"
369
- ? { prompt: optionsOrPrompt }
370
- : optionsOrPrompt;
371
- const { prompt, temperature = 0.7, maxTokens = DEFAULT_MAX_TOKENS, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema, timeout = getDefaultTimeout(provider, "generate"), } = options;
372
- // Use schema from options or fallback parameter
373
- const finalSchema = schema || analysisSchema;
374
- logger.debug(`[${functionTag}] Generate request started`, {
375
- provider,
376
- modelName: this.modelName,
377
- promptLength: prompt.length,
378
- temperature,
379
- maxTokens,
380
- timeout,
381
- });
382
- const model = this.getModel();
383
- // Create timeout controller if timeout is specified
384
- const timeoutController = createTimeoutController(timeout, provider, "generate");
385
- const generateOptions = {
386
- model: model,
387
- prompt: prompt,
388
- system: systemPrompt,
389
- temperature,
390
- maxTokens,
391
- // Add abort signal if available
392
- ...(timeoutController && {
393
- abortSignal: timeoutController.controller.signal,
394
- }),
395
- };
396
- if (finalSchema) {
397
- generateOptions.experimental_output = Output.object({
398
- schema: finalSchema,
399
- });
400
- }
401
- try {
402
- const result = await generateText(generateOptions);
403
- // Clean up timeout if successful
404
- timeoutController?.cleanup();
405
- logger.debug(`[${functionTag}] Generate text completed`, {
406
- provider,
407
- modelName: this.modelName,
408
- usage: result.usage,
409
- finishReason: result.finishReason,
410
- responseLength: result.text?.length || 0,
411
- timeout,
412
- });
413
- // Add analytics if enabled
414
- if (options.enableAnalytics) {
415
- result.analytics = {
416
- provider,
417
- model: this.modelName,
418
- tokens: result.usage,
419
- responseTime: Date.now() - startTime,
420
- context: options.context,
421
- };
422
- }
423
- // Add evaluation if enabled
424
- if (options.enableEvaluation) {
425
- result.evaluation = await evaluateResponse(prompt, result.text, options.context);
426
- }
427
- return {
428
- content: result.text,
429
- provider: "huggingface",
430
- model: this.modelName,
431
- usage: result.usage
432
- ? {
433
- inputTokens: result.usage.promptTokens,
434
- outputTokens: result.usage.completionTokens,
435
- totalTokens: result.usage.totalTokens,
436
- }
437
- : undefined,
438
- responseTime: Date.now() - startTime,
439
- };
440
- }
441
- finally {
442
- // Always cleanup timeout
443
- timeoutController?.cleanup();
444
- }
110
+ getAISDKModel() {
111
+ return this.model;
112
+ }
113
+ handleProviderError(error) {
114
+ if (error instanceof TimeoutError) {
115
+ return new Error(`HuggingFace request timed out: ${error.message}`);
445
116
  }
446
- catch (err) {
447
- // Log timeout errors specifically
448
- if (err instanceof TimeoutError) {
449
- logger.error(`[${functionTag}] Timeout error`, {
450
- provider,
451
- modelName: this.modelName,
452
- timeout: err.timeout,
453
- message: err.message,
454
- });
455
- }
456
- else {
457
- logger.error(`[${functionTag}] Exception`, {
458
- provider,
459
- modelName: this.modelName,
460
- message: "Error in generating text",
461
- err: String(err),
462
- });
463
- }
464
- throw err; // Re-throw error to trigger fallback
117
+ if (error?.message?.includes("API_TOKEN_INVALID") ||
118
+ error?.message?.includes("Invalid token")) {
119
+ return new Error("Invalid HuggingFace API token. Please check your HUGGING_FACE_API_KEY environment variable.");
465
120
  }
121
+ if (error?.message?.includes("rate limit")) {
122
+ return new Error("HuggingFace rate limit exceeded. Please try again later.");
123
+ }
124
+ return new Error(`HuggingFace error: ${error?.message || "Unknown error"}`);
466
125
  }
467
- async gen(optionsOrPrompt, analysisSchema) {
468
- return this.generate(optionsOrPrompt, analysisSchema);
126
+ // ===================
127
+ // PRIVATE VALIDATION METHODS
128
+ // ===================
129
+ validateStreamOptions(options) {
130
+ if (!options.input?.text || options.input.text.trim().length === 0) {
131
+ throw new Error("Input text is required and cannot be empty");
132
+ }
469
133
  }
470
134
  }
135
+ // Export for factory registration
136
+ export default HuggingFaceProvider;
@@ -2,15 +2,15 @@
2
2
  * Provider exports for Vercel AI SDK integration
3
3
  * This file centralizes all AI provider classes for easy import and usage
4
4
  */
5
- export { GoogleVertexAI } from "./googleVertexAI.js";
6
- export { AmazonBedrock } from "./amazonBedrock.js";
7
- export { OpenAI } from "./openAI.js";
8
- export { AnthropicProvider } from "./anthropic.js";
9
- export { AzureOpenAIProvider } from "./azureOpenAI.js";
10
- export { GoogleAIStudio } from "./googleAIStudio.js";
11
- export { HuggingFace } from "./huggingFace.js";
12
- export { Ollama } from "./ollama.js";
13
- export { MistralAI } from "./mistralAI.js";
5
+ export { GoogleVertexProvider as GoogleVertexAI } from "./google-vertex.js";
6
+ export { AmazonBedrockProvider as AmazonBedrock } from "./amazon-bedrock.js";
7
+ export { OpenAIProvider as OpenAI } from "./openAI.js";
8
+ export { AnthropicProvider as AnthropicProvider } from "./anthropic.js";
9
+ export { AzureOpenAIProvider } from "./azure-openai.js";
10
+ export { GoogleAIStudioProvider as GoogleAIStudio } from "./google-ai-studio.js";
11
+ export { HuggingFaceProvider as HuggingFace } from "./huggingFace.js";
12
+ export { OllamaProvider as Ollama } from "./ollama.js";
13
+ export { MistralProvider as MistralAI } from "./mistral.js";
14
14
  export type { AIProvider } from "../core/types.js";
15
15
  /**
16
16
  * Provider registry for dynamic provider instantiation
@@ -2,15 +2,15 @@
2
2
  * Provider exports for Vercel AI SDK integration
3
3
  * This file centralizes all AI provider classes for easy import and usage
4
4
  */
5
- export { GoogleVertexAI } from "./googleVertexAI.js";
6
- export { AmazonBedrock } from "./amazonBedrock.js";
7
- export { OpenAI } from "./openAI.js";
8
- export { AnthropicProvider } from "./anthropic.js";
9
- export { AzureOpenAIProvider } from "./azureOpenAI.js";
10
- export { GoogleAIStudio } from "./googleAIStudio.js";
11
- export { HuggingFace } from "./huggingFace.js";
12
- export { Ollama } from "./ollama.js";
13
- export { MistralAI } from "./mistralAI.js";
5
+ export { GoogleVertexProvider as GoogleVertexAI } from "./google-vertex.js";
6
+ export { AmazonBedrockProvider as AmazonBedrock } from "./amazon-bedrock.js";
7
+ export { OpenAIProvider as OpenAI } from "./openAI.js";
8
+ export { AnthropicProvider as AnthropicProvider } from "./anthropic.js";
9
+ export { AzureOpenAIProvider } from "./azure-openai.js";
10
+ export { GoogleAIStudioProvider as GoogleAIStudio } from "./google-ai-studio.js";
11
+ export { HuggingFaceProvider as HuggingFace } from "./huggingFace.js";
12
+ export { OllamaProvider as Ollama } from "./ollama.js";
13
+ export { MistralProvider as MistralAI } from "./mistral.js";
14
14
  /**
15
15
  * Provider registry for dynamic provider instantiation
16
16
  */
@@ -123,6 +123,10 @@ export class MCPAwareProvider {
123
123
  const options = typeof optionsOrPrompt === "string"
124
124
  ? { prompt: optionsOrPrompt }
125
125
  : optionsOrPrompt;
126
+ // Validate prompt is provided
127
+ if (!options.prompt || options.prompt.trim() === "") {
128
+ throw new Error("MCP Provider requires a valid prompt. Please provide a non-empty prompt string.");
129
+ }
126
130
  // Check if prompt requests tool usage
127
131
  const needsTools = this.detectToolRequest(options.prompt);
128
132
  if (needsTools && this.mcpInitialized) {
@@ -0,0 +1,42 @@
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
+ * Mistral AI Provider v2 - BaseProvider Implementation
8
+ *
9
+ * PHASE 3.6: Simple BaseProvider wrap around existing @ai-sdk/mistral implementation
10
+ *
11
+ * Features:
12
+ * - Extends BaseProvider for shared functionality
13
+ * - Uses pre-configured Mistral instance for efficiency
14
+ * - Enhanced error handling with setup guidance
15
+ * - Supports all Mistral models (mistral-small, mistral-medium, mistral-large)
16
+ */
17
+ export declare class MistralProvider extends BaseProvider {
18
+ private mistral;
19
+ private model;
20
+ constructor(modelName?: string, sdk?: any);
21
+ protected getProviderName(): AIProviderName;
22
+ protected getDefaultModel(): string;
23
+ /**
24
+ * Returns the Vercel AI SDK model instance for Mistral
25
+ */
26
+ protected getAISDKModel(): LanguageModelV1;
27
+ protected executeStream(options: StreamOptions, analysisSchema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>): Promise<StreamResult>;
28
+ protected handleProviderError(error: any): Error;
29
+ private validateStreamOptions;
30
+ /**
31
+ * Check available Mistral models
32
+ * @returns Array of available model names
33
+ */
34
+ getAvailableModels(): string[];
35
+ /**
36
+ * Get recommended model based on use case
37
+ * @param useCase - The intended use case
38
+ * @returns Recommended model name
39
+ */
40
+ getRecommendedModel(useCase: "speed" | "balanced" | "quality"): string;
41
+ }
42
+ export default MistralProvider;