@juspay/neurolink 8.2.0 → 8.4.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 +12 -0
- package/README.md +13 -3
- package/dist/adapters/providerImageAdapter.d.ts +1 -1
- package/dist/adapters/providerImageAdapter.js +62 -0
- package/dist/agent/directTools.d.ts +0 -72
- package/dist/agent/directTools.js +3 -74
- package/dist/cli/commands/config.d.ts +18 -18
- package/dist/cli/factories/commandFactory.js +1 -0
- package/dist/cli/loop/conversationSelector.js +4 -0
- package/dist/cli/loop/session.js +27 -15
- package/dist/constants/enums.d.ts +1 -0
- package/dist/constants/enums.js +3 -1
- package/dist/constants/tokens.d.ts +3 -0
- package/dist/constants/tokens.js +3 -0
- package/dist/core/baseProvider.d.ts +56 -53
- package/dist/core/baseProvider.js +107 -1095
- package/dist/core/constants.d.ts +3 -0
- package/dist/core/constants.js +6 -3
- package/dist/core/modelConfiguration.js +10 -0
- package/dist/core/modules/GenerationHandler.d.ts +63 -0
- package/dist/core/modules/GenerationHandler.js +230 -0
- package/dist/core/modules/MessageBuilder.d.ts +39 -0
- package/dist/core/modules/MessageBuilder.js +179 -0
- package/dist/core/modules/StreamHandler.d.ts +52 -0
- package/dist/core/modules/StreamHandler.js +103 -0
- package/dist/core/modules/TelemetryHandler.d.ts +64 -0
- package/dist/core/modules/TelemetryHandler.js +170 -0
- package/dist/core/modules/ToolsManager.d.ts +98 -0
- package/dist/core/modules/ToolsManager.js +521 -0
- package/dist/core/modules/Utilities.d.ts +88 -0
- package/dist/core/modules/Utilities.js +329 -0
- package/dist/factories/providerRegistry.js +1 -1
- package/dist/lib/adapters/providerImageAdapter.d.ts +1 -1
- package/dist/lib/adapters/providerImageAdapter.js +62 -0
- package/dist/lib/agent/directTools.d.ts +0 -72
- package/dist/lib/agent/directTools.js +3 -74
- package/dist/lib/constants/enums.d.ts +1 -0
- package/dist/lib/constants/enums.js +3 -1
- package/dist/lib/constants/tokens.d.ts +3 -0
- package/dist/lib/constants/tokens.js +3 -0
- package/dist/lib/core/baseProvider.d.ts +56 -53
- package/dist/lib/core/baseProvider.js +107 -1095
- package/dist/lib/core/constants.d.ts +3 -0
- package/dist/lib/core/constants.js +6 -3
- package/dist/lib/core/modelConfiguration.js +10 -0
- package/dist/lib/core/modules/GenerationHandler.d.ts +63 -0
- package/dist/lib/core/modules/GenerationHandler.js +231 -0
- package/dist/lib/core/modules/MessageBuilder.d.ts +39 -0
- package/dist/lib/core/modules/MessageBuilder.js +180 -0
- package/dist/lib/core/modules/StreamHandler.d.ts +52 -0
- package/dist/lib/core/modules/StreamHandler.js +104 -0
- package/dist/lib/core/modules/TelemetryHandler.d.ts +64 -0
- package/dist/lib/core/modules/TelemetryHandler.js +171 -0
- package/dist/lib/core/modules/ToolsManager.d.ts +98 -0
- package/dist/lib/core/modules/ToolsManager.js +522 -0
- package/dist/lib/core/modules/Utilities.d.ts +88 -0
- package/dist/lib/core/modules/Utilities.js +330 -0
- package/dist/lib/factories/providerRegistry.js +1 -1
- package/dist/lib/mcp/servers/agent/directToolsServer.js +0 -1
- package/dist/lib/models/modelRegistry.js +44 -0
- package/dist/lib/neurolink.js +35 -3
- package/dist/lib/providers/amazonBedrock.js +59 -10
- package/dist/lib/providers/anthropic.js +2 -30
- package/dist/lib/providers/azureOpenai.js +2 -24
- package/dist/lib/providers/googleAiStudio.js +2 -24
- package/dist/lib/providers/googleVertex.js +2 -45
- package/dist/lib/providers/huggingFace.js +3 -31
- package/dist/lib/providers/litellm.d.ts +1 -1
- package/dist/lib/providers/litellm.js +110 -44
- package/dist/lib/providers/mistral.js +5 -32
- package/dist/lib/providers/ollama.d.ts +1 -0
- package/dist/lib/providers/ollama.js +476 -129
- package/dist/lib/providers/openAI.js +2 -28
- package/dist/lib/providers/openaiCompatible.js +3 -31
- package/dist/lib/types/content.d.ts +16 -113
- package/dist/lib/types/content.js +16 -2
- package/dist/lib/types/conversation.d.ts +3 -17
- package/dist/lib/types/generateTypes.d.ts +2 -2
- package/dist/lib/types/index.d.ts +2 -0
- package/dist/lib/types/index.js +2 -0
- package/dist/lib/types/multimodal.d.ts +282 -0
- package/dist/lib/types/multimodal.js +101 -0
- package/dist/lib/types/streamTypes.d.ts +2 -2
- package/dist/lib/utils/imageProcessor.d.ts +1 -1
- package/dist/lib/utils/messageBuilder.js +25 -2
- package/dist/lib/utils/multimodalOptionsBuilder.d.ts +1 -1
- package/dist/lib/utils/pdfProcessor.d.ts +9 -0
- package/dist/lib/utils/pdfProcessor.js +67 -9
- package/dist/mcp/servers/agent/directToolsServer.js +0 -1
- package/dist/models/modelRegistry.js +44 -0
- package/dist/neurolink.js +35 -3
- package/dist/providers/amazonBedrock.js +59 -10
- package/dist/providers/anthropic.js +2 -30
- package/dist/providers/azureOpenai.js +2 -24
- package/dist/providers/googleAiStudio.js +2 -24
- package/dist/providers/googleVertex.js +2 -45
- package/dist/providers/huggingFace.js +3 -31
- package/dist/providers/litellm.d.ts +1 -1
- package/dist/providers/litellm.js +110 -44
- package/dist/providers/mistral.js +5 -32
- package/dist/providers/ollama.d.ts +1 -0
- package/dist/providers/ollama.js +476 -129
- package/dist/providers/openAI.js +2 -28
- package/dist/providers/openaiCompatible.js +3 -31
- package/dist/types/content.d.ts +16 -113
- package/dist/types/content.js +16 -2
- package/dist/types/conversation.d.ts +3 -17
- package/dist/types/generateTypes.d.ts +2 -2
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +2 -0
- package/dist/types/multimodal.d.ts +282 -0
- package/dist/types/multimodal.js +100 -0
- package/dist/types/streamTypes.d.ts +2 -2
- package/dist/utils/imageProcessor.d.ts +1 -1
- package/dist/utils/messageBuilder.js +25 -2
- package/dist/utils/multimodalOptionsBuilder.d.ts +1 -1
- package/dist/utils/pdfProcessor.d.ts +9 -0
- package/dist/utils/pdfProcessor.js +67 -9
- package/package.json +5 -2
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities Module
|
|
3
|
+
*
|
|
4
|
+
* Handles validation, normalization, schema conversion, and error handling utilities.
|
|
5
|
+
* Extracted from BaseProvider to follow Single Responsibility Principle.
|
|
6
|
+
*
|
|
7
|
+
* Responsibilities:
|
|
8
|
+
* - Options validation (text generation and stream options)
|
|
9
|
+
* - Options normalization (string to object conversion)
|
|
10
|
+
* - Provider information formatting
|
|
11
|
+
* - Timeout parsing and calculation
|
|
12
|
+
* - Schema utilities (Zod detection, permissive schema creation, OpenAI strict mode fixes)
|
|
13
|
+
* - Tool result conversion
|
|
14
|
+
* - Middleware options extraction
|
|
15
|
+
* - Common error pattern handling
|
|
16
|
+
*
|
|
17
|
+
* @module core/modules/Utilities
|
|
18
|
+
*/
|
|
19
|
+
import { z } from "zod";
|
|
20
|
+
import { logger } from "../../utils/logger.js";
|
|
21
|
+
import { getSafeMaxTokens } from "../../utils/tokenLimits.js";
|
|
22
|
+
import { TimeoutError } from "../../utils/timeout.js";
|
|
23
|
+
import { validateStreamOptions as validateStreamOpts, validateTextGenerationOptions, ValidationError, createValidationSummary, } from "../../utils/parameterValidation.js";
|
|
24
|
+
import { STEP_LIMITS } from "../constants.js";
|
|
25
|
+
/**
|
|
26
|
+
* Utilities class - Provides validation, normalization, and utility methods
|
|
27
|
+
*/
|
|
28
|
+
export class Utilities {
|
|
29
|
+
providerName;
|
|
30
|
+
modelName;
|
|
31
|
+
defaultTimeout;
|
|
32
|
+
middlewareOptions;
|
|
33
|
+
constructor(providerName, modelName, defaultTimeout = 30000, middlewareOptions) {
|
|
34
|
+
this.providerName = providerName;
|
|
35
|
+
this.modelName = modelName;
|
|
36
|
+
this.defaultTimeout = defaultTimeout;
|
|
37
|
+
this.middlewareOptions = middlewareOptions;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Validate text generation options
|
|
41
|
+
*/
|
|
42
|
+
validateOptions(options) {
|
|
43
|
+
const validation = validateTextGenerationOptions(options);
|
|
44
|
+
if (!validation.isValid) {
|
|
45
|
+
const summary = createValidationSummary(validation);
|
|
46
|
+
throw new ValidationError(`Text generation options validation failed: ${summary}`, "options", "VALIDATION_FAILED", validation.suggestions);
|
|
47
|
+
}
|
|
48
|
+
// Log warnings if any
|
|
49
|
+
if (validation.warnings.length > 0) {
|
|
50
|
+
logger.warn("Text generation options validation warnings:", validation.warnings);
|
|
51
|
+
}
|
|
52
|
+
// Additional BaseProvider-specific validation
|
|
53
|
+
if (options.maxSteps !== undefined) {
|
|
54
|
+
if (options.maxSteps < STEP_LIMITS.min ||
|
|
55
|
+
options.maxSteps > STEP_LIMITS.max) {
|
|
56
|
+
throw new ValidationError(`maxSteps must be between ${STEP_LIMITS.min} and ${STEP_LIMITS.max}`, "maxSteps", "OUT_OF_RANGE", [
|
|
57
|
+
`Use a value between ${STEP_LIMITS.min} and ${STEP_LIMITS.max} for optimal performance`,
|
|
58
|
+
]);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Validate stream options
|
|
64
|
+
*/
|
|
65
|
+
validateStreamOptions(options) {
|
|
66
|
+
const validation = validateStreamOpts(options);
|
|
67
|
+
if (!validation.isValid) {
|
|
68
|
+
const summary = createValidationSummary(validation);
|
|
69
|
+
throw new ValidationError(`Stream options validation failed: ${summary}`, "options", "VALIDATION_FAILED", validation.suggestions);
|
|
70
|
+
}
|
|
71
|
+
// Log warnings if any
|
|
72
|
+
if (validation.warnings.length > 0) {
|
|
73
|
+
logger.warn("Stream options validation warnings:", validation.warnings);
|
|
74
|
+
}
|
|
75
|
+
// Additional BaseProvider-specific validation
|
|
76
|
+
if (options.maxSteps !== undefined) {
|
|
77
|
+
if (options.maxSteps < STEP_LIMITS.min ||
|
|
78
|
+
options.maxSteps > STEP_LIMITS.max) {
|
|
79
|
+
throw new ValidationError(`maxSteps must be between ${STEP_LIMITS.min} and ${STEP_LIMITS.max}`, "maxSteps", "OUT_OF_RANGE", [
|
|
80
|
+
`Use a value between ${STEP_LIMITS.min} and ${STEP_LIMITS.max} for optimal performance`,
|
|
81
|
+
]);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Normalize text generation options from string or object
|
|
87
|
+
*/
|
|
88
|
+
normalizeTextOptions(optionsOrPrompt) {
|
|
89
|
+
if (typeof optionsOrPrompt === "string") {
|
|
90
|
+
const safeMaxTokens = getSafeMaxTokens(this.providerName, this.modelName);
|
|
91
|
+
return {
|
|
92
|
+
prompt: optionsOrPrompt,
|
|
93
|
+
provider: this.providerName,
|
|
94
|
+
model: this.modelName,
|
|
95
|
+
maxTokens: safeMaxTokens,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// Handle both prompt and input.text formats
|
|
99
|
+
const prompt = optionsOrPrompt.prompt || optionsOrPrompt.input?.text || "";
|
|
100
|
+
const modelName = optionsOrPrompt.model || this.modelName;
|
|
101
|
+
const providerName = optionsOrPrompt.provider || this.providerName;
|
|
102
|
+
// Apply safe maxTokens based on provider and model
|
|
103
|
+
const safeMaxTokens = getSafeMaxTokens(providerName, modelName, optionsOrPrompt.maxTokens);
|
|
104
|
+
// CRITICAL FIX: Preserve the entire input object for multimodal support
|
|
105
|
+
// This ensures images and content arrays are not lost during normalization
|
|
106
|
+
const normalizedOptions = {
|
|
107
|
+
...optionsOrPrompt,
|
|
108
|
+
prompt,
|
|
109
|
+
provider: providerName,
|
|
110
|
+
model: modelName,
|
|
111
|
+
maxTokens: safeMaxTokens,
|
|
112
|
+
};
|
|
113
|
+
// Ensure input object is preserved if it exists (for multimodal support)
|
|
114
|
+
if (optionsOrPrompt.input) {
|
|
115
|
+
normalizedOptions.input = {
|
|
116
|
+
...optionsOrPrompt.input,
|
|
117
|
+
text: prompt, // Ensure text is consistent
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
return normalizedOptions;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Normalize stream options from string or object
|
|
124
|
+
*/
|
|
125
|
+
normalizeStreamOptions(optionsOrPrompt) {
|
|
126
|
+
if (typeof optionsOrPrompt === "string") {
|
|
127
|
+
const safeMaxTokens = getSafeMaxTokens(this.providerName, this.modelName);
|
|
128
|
+
return {
|
|
129
|
+
input: { text: optionsOrPrompt },
|
|
130
|
+
provider: this.providerName,
|
|
131
|
+
model: this.modelName,
|
|
132
|
+
maxTokens: safeMaxTokens,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
const modelName = optionsOrPrompt.model || this.modelName;
|
|
136
|
+
const providerName = optionsOrPrompt.provider || this.providerName;
|
|
137
|
+
// Apply safe maxTokens based on provider and model
|
|
138
|
+
const safeMaxTokens = getSafeMaxTokens(providerName, modelName, optionsOrPrompt.maxTokens);
|
|
139
|
+
return {
|
|
140
|
+
...optionsOrPrompt,
|
|
141
|
+
provider: providerName,
|
|
142
|
+
model: modelName,
|
|
143
|
+
maxTokens: safeMaxTokens,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Get provider information
|
|
148
|
+
*/
|
|
149
|
+
getProviderInfo() {
|
|
150
|
+
return {
|
|
151
|
+
provider: this.providerName,
|
|
152
|
+
model: this.modelName,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Get timeout value in milliseconds from options
|
|
157
|
+
* Supports number or string formats (e.g., '30s', '2m', '1h')
|
|
158
|
+
*/
|
|
159
|
+
getTimeout(options) {
|
|
160
|
+
if (!options.timeout) {
|
|
161
|
+
return this.defaultTimeout;
|
|
162
|
+
}
|
|
163
|
+
if (typeof options.timeout === "number") {
|
|
164
|
+
return options.timeout;
|
|
165
|
+
}
|
|
166
|
+
// Parse string timeout (e.g., '30s', '2m', '1h')
|
|
167
|
+
const timeoutStr = options.timeout.toLowerCase();
|
|
168
|
+
const value = parseInt(timeoutStr);
|
|
169
|
+
if (timeoutStr.includes("h")) {
|
|
170
|
+
return value * 60 * 60 * 1000;
|
|
171
|
+
}
|
|
172
|
+
else if (timeoutStr.includes("m")) {
|
|
173
|
+
return value * 60 * 1000;
|
|
174
|
+
}
|
|
175
|
+
else if (timeoutStr.includes("s")) {
|
|
176
|
+
return value * 1000;
|
|
177
|
+
}
|
|
178
|
+
return this.defaultTimeout;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Check if a schema is a Zod schema
|
|
182
|
+
*/
|
|
183
|
+
isZodSchema(schema) {
|
|
184
|
+
return (typeof schema === "object" &&
|
|
185
|
+
schema !== null &&
|
|
186
|
+
// Most Zod schemas have an internal _def and a parse method
|
|
187
|
+
typeof schema.parse === "function");
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Convert tool execution result from MCP format to standard format
|
|
191
|
+
* Handles tool failures gracefully to prevent stream termination
|
|
192
|
+
*/
|
|
193
|
+
async convertToolResult(result) {
|
|
194
|
+
// Handle MCP-style results
|
|
195
|
+
if (result && typeof result === "object" && "success" in result) {
|
|
196
|
+
const mcpResult = result;
|
|
197
|
+
if (mcpResult.success) {
|
|
198
|
+
return mcpResult.data;
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
// Instead of throwing, return a structured error result
|
|
202
|
+
// This prevents tool failures from terminating streams
|
|
203
|
+
const errorMsg = typeof mcpResult.error === "string"
|
|
204
|
+
? mcpResult.error
|
|
205
|
+
: "Tool execution failed";
|
|
206
|
+
// Log the error for debugging but don't throw
|
|
207
|
+
logger.warn(`Tool execution failed: ${errorMsg}`);
|
|
208
|
+
// Return error as structured data that can be processed by the AI
|
|
209
|
+
return {
|
|
210
|
+
isError: true,
|
|
211
|
+
error: errorMsg,
|
|
212
|
+
content: [
|
|
213
|
+
{
|
|
214
|
+
type: "text",
|
|
215
|
+
text: `Tool execution failed: ${errorMsg}`,
|
|
216
|
+
},
|
|
217
|
+
],
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return result;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Create a permissive Zod schema that accepts all parameters as-is
|
|
225
|
+
*/
|
|
226
|
+
createPermissiveZodSchema() {
|
|
227
|
+
// Create a permissive record that accepts any object structure
|
|
228
|
+
// This allows all parameters to pass through without validation issues
|
|
229
|
+
return z.record(z.unknown()).transform((data) => {
|
|
230
|
+
// Return the data as-is to preserve all parameter information
|
|
231
|
+
return data;
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Recursively fix JSON Schema for OpenAI strict mode compatibility
|
|
236
|
+
* OpenAI requires additionalProperties: false at ALL levels and preserves required array
|
|
237
|
+
*/
|
|
238
|
+
fixSchemaForOpenAIStrictMode(schema) {
|
|
239
|
+
const fixedSchema = JSON.parse(JSON.stringify(schema));
|
|
240
|
+
if (fixedSchema.type === "object" &&
|
|
241
|
+
fixedSchema.properties &&
|
|
242
|
+
typeof fixedSchema.properties === "object") {
|
|
243
|
+
const allPropertyNames = Object.keys(fixedSchema.properties);
|
|
244
|
+
if (!fixedSchema.required || !Array.isArray(fixedSchema.required)) {
|
|
245
|
+
fixedSchema.required = [];
|
|
246
|
+
}
|
|
247
|
+
fixedSchema.additionalProperties = false;
|
|
248
|
+
for (const propName of allPropertyNames) {
|
|
249
|
+
const propValue = fixedSchema.properties[propName];
|
|
250
|
+
if (propValue && typeof propValue === "object") {
|
|
251
|
+
if (propValue.type === "object") {
|
|
252
|
+
fixedSchema.properties[propName] =
|
|
253
|
+
this.fixSchemaForOpenAIStrictMode(propValue);
|
|
254
|
+
}
|
|
255
|
+
else if (propValue.type === "array" &&
|
|
256
|
+
propValue.items &&
|
|
257
|
+
typeof propValue.items === "object") {
|
|
258
|
+
fixedSchema.properties[propName].items =
|
|
259
|
+
this.fixSchemaForOpenAIStrictMode(propValue.items);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return fixedSchema;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Extract middleware options from generation/stream options
|
|
268
|
+
* This is the single source of truth for deciding if middleware should be applied
|
|
269
|
+
*/
|
|
270
|
+
extractMiddlewareOptions(options) {
|
|
271
|
+
// 1. Determine effective middleware config: per-request overrides global.
|
|
272
|
+
const middlewareOpts = options.middleware ??
|
|
273
|
+
this.middlewareOptions;
|
|
274
|
+
if (!middlewareOpts) {
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
// 2. The middleware property must be an object with configuration.
|
|
278
|
+
if (typeof middlewareOpts !== "object" ||
|
|
279
|
+
middlewareOpts === null ||
|
|
280
|
+
middlewareOpts instanceof Date ||
|
|
281
|
+
middlewareOpts instanceof RegExp) {
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
// 3. Check if the middleware object has any actual configuration keys.
|
|
285
|
+
const fullOpts = middlewareOpts;
|
|
286
|
+
const hasArray = (arr) => Array.isArray(arr) && arr.length > 0;
|
|
287
|
+
const hasConfig = !!fullOpts.middlewareConfig ||
|
|
288
|
+
hasArray(fullOpts.enabledMiddleware) ||
|
|
289
|
+
hasArray(fullOpts.disabledMiddleware) ||
|
|
290
|
+
!!fullOpts.preset ||
|
|
291
|
+
hasArray(fullOpts.middleware);
|
|
292
|
+
if (!hasConfig) {
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
// 4. Return the formatted options if configuration is present.
|
|
296
|
+
return {
|
|
297
|
+
...fullOpts,
|
|
298
|
+
global: {
|
|
299
|
+
collectStats: true,
|
|
300
|
+
continueOnError: true,
|
|
301
|
+
...(fullOpts.global || {}),
|
|
302
|
+
},
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Handle common error patterns across providers
|
|
307
|
+
* Returns transformed error or null if not a common pattern
|
|
308
|
+
*/
|
|
309
|
+
handleCommonErrors(error) {
|
|
310
|
+
if (error instanceof TimeoutError) {
|
|
311
|
+
return new Error(`${this.providerName} request timed out after ${error.timeout}ms. Consider increasing timeout or using a lighter model.`);
|
|
312
|
+
}
|
|
313
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
314
|
+
// Common API key errors
|
|
315
|
+
if (message.includes("API_KEY_INVALID") ||
|
|
316
|
+
message.includes("Invalid API key") ||
|
|
317
|
+
message.includes("authentication") ||
|
|
318
|
+
message.includes("unauthorized")) {
|
|
319
|
+
return new Error(`Invalid API key for ${this.providerName}. Please check your API key environment variable.`);
|
|
320
|
+
}
|
|
321
|
+
// Common rate limit errors
|
|
322
|
+
if (message.includes("rate limit") ||
|
|
323
|
+
message.includes("quota") ||
|
|
324
|
+
message.includes("429")) {
|
|
325
|
+
return new Error(`Rate limit exceeded for ${this.providerName}. Please wait before making more requests.`);
|
|
326
|
+
}
|
|
327
|
+
return null; // Not a common error, let provider handle it
|
|
328
|
+
}
|
|
329
|
+
}
|
|
@@ -24,7 +24,7 @@ export class ProviderRegistry {
|
|
|
24
24
|
ProviderFactory.registerProvider(AIProviderName.GOOGLE_AI, async (modelName, _providerName, sdk) => {
|
|
25
25
|
const { GoogleAIStudioProvider } = await import("../providers/googleAiStudio.js");
|
|
26
26
|
return new GoogleAIStudioProvider(modelName, sdk);
|
|
27
|
-
}, GoogleAIModels.GEMINI_2_5_FLASH, ["googleAiStudio", "google", "gemini", "google-ai"]);
|
|
27
|
+
}, GoogleAIModels.GEMINI_2_5_FLASH, ["googleAiStudio", "google", "gemini", "google-ai", "google-ai-studio"]);
|
|
28
28
|
// Register OpenAI provider
|
|
29
29
|
ProviderFactory.registerProvider(AIProviderName.OPENAI, async (modelName, _providerName, sdk) => {
|
|
30
30
|
const { OpenAIProvider } = await import("../providers/openAI.js");
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Provider Image Adapter - Smart routing for multimodal content
|
|
3
3
|
* Handles provider-specific image formatting and vision capability validation
|
|
4
4
|
*/
|
|
5
|
-
import type { Content } from "../types/
|
|
5
|
+
import type { Content } from "../types/multimodal.js";
|
|
6
6
|
/**
|
|
7
7
|
* Simplified logger for essential error reporting only
|
|
8
8
|
*/
|
|
@@ -53,6 +53,7 @@ const VISION_CAPABILITIES = {
|
|
|
53
53
|
anthropic: [
|
|
54
54
|
"claude-3-7-sonnet",
|
|
55
55
|
"claude-3-5-sonnet",
|
|
56
|
+
"claude-haiku-4-5",
|
|
56
57
|
"claude-3-opus",
|
|
57
58
|
"claude-3-sonnet",
|
|
58
59
|
"claude-3-haiku",
|
|
@@ -82,6 +83,7 @@ const VISION_CAPABILITIES = {
|
|
|
82
83
|
"gemini-1.5-flash",
|
|
83
84
|
// Claude 4.x models (versioned format)
|
|
84
85
|
"claude-sonnet-4-5@",
|
|
86
|
+
"claude-haiku-4-5",
|
|
85
87
|
"claude-sonnet-4@",
|
|
86
88
|
"claude-opus-4-1@",
|
|
87
89
|
"claude-opus-4@",
|
|
@@ -100,9 +102,12 @@ const VISION_CAPABILITIES = {
|
|
|
100
102
|
"claude-sonnet-3",
|
|
101
103
|
"claude-opus-3",
|
|
102
104
|
"claude-haiku-3",
|
|
105
|
+
"claude-haiku-4",
|
|
103
106
|
// Additional patterns for compatibility
|
|
104
107
|
"claude-3.5-sonnet",
|
|
105
108
|
"claude-3.5-haiku",
|
|
109
|
+
"claude-4.5-haiku",
|
|
110
|
+
"claude-haiku-4-5",
|
|
106
111
|
"claude-3.0-sonnet",
|
|
107
112
|
"claude-3.0-opus",
|
|
108
113
|
],
|
|
@@ -118,6 +123,25 @@ const VISION_CAPABILITIES = {
|
|
|
118
123
|
"gpt-4.1",
|
|
119
124
|
"gpt-5",
|
|
120
125
|
],
|
|
126
|
+
mistral: [
|
|
127
|
+
// Mistral Small 3.2 (vision support for images: PNG, JPEG, WEBP, GIF)
|
|
128
|
+
"mistral-small",
|
|
129
|
+
"mistral-small-latest",
|
|
130
|
+
"mistral-small-3.2",
|
|
131
|
+
"mistral-small-2506",
|
|
132
|
+
// Mistral Medium 3.1 (vision support)
|
|
133
|
+
"mistral-medium",
|
|
134
|
+
"mistral-medium-latest",
|
|
135
|
+
"mistral-medium-3.1",
|
|
136
|
+
// Magistral models (vision support)
|
|
137
|
+
"magistral-small",
|
|
138
|
+
"magistral-medium",
|
|
139
|
+
// Pixtral models (specialized vision models)
|
|
140
|
+
"pixtral-12b",
|
|
141
|
+
"pixtral-12b-latest",
|
|
142
|
+
"pixtral-large",
|
|
143
|
+
"pixtral-large-latest",
|
|
144
|
+
],
|
|
121
145
|
ollama: [
|
|
122
146
|
// Llama 4 family (May 2025 - Best vision + tool calling)
|
|
123
147
|
"llama4:scout",
|
|
@@ -137,6 +161,44 @@ const VISION_CAPABILITIES = {
|
|
|
137
161
|
// LLaVA (vision-focused)
|
|
138
162
|
"llava",
|
|
139
163
|
],
|
|
164
|
+
bedrock: [
|
|
165
|
+
// Claude Sonnet 4.5 family (supports vision, PDFs, images)
|
|
166
|
+
"claude-sonnet-4-5",
|
|
167
|
+
"claude-sonnet-4.5",
|
|
168
|
+
"anthropic.claude-sonnet-4-5",
|
|
169
|
+
// Claude Haiku 4.5 family (supports vision, PDFs, images)
|
|
170
|
+
"claude-haiku-4-5",
|
|
171
|
+
"claude-haiku-4.5",
|
|
172
|
+
"anthropic.claude-haiku-4-5",
|
|
173
|
+
// Claude Sonnet 4 family
|
|
174
|
+
"claude-sonnet-4",
|
|
175
|
+
"claude-sonnet-4@",
|
|
176
|
+
"anthropic.claude-sonnet-4",
|
|
177
|
+
// Claude Opus 4 family
|
|
178
|
+
"claude-opus-4",
|
|
179
|
+
"claude-opus-4-1",
|
|
180
|
+
"claude-opus-4@",
|
|
181
|
+
"anthropic.claude-opus-4",
|
|
182
|
+
// Claude 3.7 Sonnet
|
|
183
|
+
"claude-3-7-sonnet",
|
|
184
|
+
"claude-3.7-sonnet",
|
|
185
|
+
"anthropic.claude-3-7-sonnet",
|
|
186
|
+
// Claude 3.5 Sonnet
|
|
187
|
+
"claude-3-5-sonnet",
|
|
188
|
+
"claude-3.5-sonnet",
|
|
189
|
+
"anthropic.claude-3-5-sonnet",
|
|
190
|
+
// Claude 3 Opus
|
|
191
|
+
"claude-3-opus",
|
|
192
|
+
"anthropic.claude-3-opus",
|
|
193
|
+
// Claude 3 Sonnet
|
|
194
|
+
"claude-3-sonnet",
|
|
195
|
+
"anthropic.claude-3-sonnet",
|
|
196
|
+
// Claude 3 Haiku
|
|
197
|
+
"claude-3-haiku",
|
|
198
|
+
"anthropic.claude-3-haiku",
|
|
199
|
+
// Generic anthropic.claude prefix (catches all Claude models)
|
|
200
|
+
"anthropic.claude",
|
|
201
|
+
],
|
|
140
202
|
};
|
|
141
203
|
/**
|
|
142
204
|
* Provider Image Adapter - Smart routing and formatting
|
|
@@ -275,77 +275,6 @@ export declare const directAgentTools: {
|
|
|
275
275
|
written?: undefined;
|
|
276
276
|
}>;
|
|
277
277
|
};
|
|
278
|
-
searchFiles: import("ai").Tool<z.ZodObject<{
|
|
279
|
-
directory: z.ZodString;
|
|
280
|
-
pattern: z.ZodString;
|
|
281
|
-
recursive: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
282
|
-
}, "strip", z.ZodTypeAny, {
|
|
283
|
-
directory: string;
|
|
284
|
-
pattern: string;
|
|
285
|
-
recursive: boolean;
|
|
286
|
-
}, {
|
|
287
|
-
directory: string;
|
|
288
|
-
pattern: string;
|
|
289
|
-
recursive?: boolean | undefined;
|
|
290
|
-
}>, {
|
|
291
|
-
success: boolean;
|
|
292
|
-
error: string;
|
|
293
|
-
directory?: undefined;
|
|
294
|
-
pattern?: undefined;
|
|
295
|
-
matches?: undefined;
|
|
296
|
-
count?: undefined;
|
|
297
|
-
} | {
|
|
298
|
-
success: boolean;
|
|
299
|
-
directory: string;
|
|
300
|
-
pattern: string;
|
|
301
|
-
matches: {
|
|
302
|
-
name: string;
|
|
303
|
-
path: string;
|
|
304
|
-
size: number;
|
|
305
|
-
lastModified: string;
|
|
306
|
-
}[];
|
|
307
|
-
count: number;
|
|
308
|
-
error?: undefined;
|
|
309
|
-
} | {
|
|
310
|
-
success: boolean;
|
|
311
|
-
error: string;
|
|
312
|
-
directory: string;
|
|
313
|
-
pattern: string;
|
|
314
|
-
matches?: undefined;
|
|
315
|
-
count?: undefined;
|
|
316
|
-
}> & {
|
|
317
|
-
execute: (args: {
|
|
318
|
-
directory: string;
|
|
319
|
-
pattern: string;
|
|
320
|
-
recursive: boolean;
|
|
321
|
-
}, options: import("ai").ToolExecutionOptions) => PromiseLike<{
|
|
322
|
-
success: boolean;
|
|
323
|
-
error: string;
|
|
324
|
-
directory?: undefined;
|
|
325
|
-
pattern?: undefined;
|
|
326
|
-
matches?: undefined;
|
|
327
|
-
count?: undefined;
|
|
328
|
-
} | {
|
|
329
|
-
success: boolean;
|
|
330
|
-
directory: string;
|
|
331
|
-
pattern: string;
|
|
332
|
-
matches: {
|
|
333
|
-
name: string;
|
|
334
|
-
path: string;
|
|
335
|
-
size: number;
|
|
336
|
-
lastModified: string;
|
|
337
|
-
}[];
|
|
338
|
-
count: number;
|
|
339
|
-
error?: undefined;
|
|
340
|
-
} | {
|
|
341
|
-
success: boolean;
|
|
342
|
-
error: string;
|
|
343
|
-
directory: string;
|
|
344
|
-
pattern: string;
|
|
345
|
-
matches?: undefined;
|
|
346
|
-
count?: undefined;
|
|
347
|
-
}>;
|
|
348
|
-
};
|
|
349
278
|
analyzeCSV: import("ai").Tool<z.ZodObject<{
|
|
350
279
|
filePath: z.ZodEffects<z.ZodString, string, string>;
|
|
351
280
|
operation: z.ZodEnum<["count_by_column", "sum_by_column", "average_by_column", "min_max_by_column", "describe"]>;
|
|
@@ -546,7 +475,6 @@ export type FilesystemToolsMap = {
|
|
|
546
475
|
readFile: typeof directAgentTools.readFile;
|
|
547
476
|
listDirectory: typeof directAgentTools.listDirectory;
|
|
548
477
|
writeFile: typeof directAgentTools.writeFile;
|
|
549
|
-
searchFiles: typeof directAgentTools.searchFiles;
|
|
550
478
|
};
|
|
551
479
|
export type UtilityToolsMap = {
|
|
552
480
|
getCurrentTime: typeof directAgentTools.getCurrentTime;
|
|
@@ -264,79 +264,9 @@ export const directAgentTools = {
|
|
|
264
264
|
}
|
|
265
265
|
},
|
|
266
266
|
}),
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
directory: z.string().describe("Directory to search in"),
|
|
271
|
-
pattern: z
|
|
272
|
-
.string()
|
|
273
|
-
.describe("File name pattern to search for (supports wildcards like *.js)"),
|
|
274
|
-
recursive: z
|
|
275
|
-
.boolean()
|
|
276
|
-
.optional()
|
|
277
|
-
.default(true)
|
|
278
|
-
.describe("Search recursively in subdirectories"),
|
|
279
|
-
}),
|
|
280
|
-
execute: async ({ directory, pattern, recursive }) => {
|
|
281
|
-
try {
|
|
282
|
-
const resolvedDir = path.resolve(directory);
|
|
283
|
-
if (!fs.existsSync(resolvedDir)) {
|
|
284
|
-
return {
|
|
285
|
-
success: false,
|
|
286
|
-
error: `Directory does not exist: ${resolvedDir}`,
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
const matches = [];
|
|
290
|
-
const searchDir = (dir, depth = 0) => {
|
|
291
|
-
if (!recursive && depth > 0) {
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
const items = fs.readdirSync(dir);
|
|
295
|
-
for (const item of items) {
|
|
296
|
-
const itemPath = path.join(dir, item);
|
|
297
|
-
const stats = fs.statSync(itemPath);
|
|
298
|
-
if (stats.isDirectory()) {
|
|
299
|
-
if (recursive && depth < 10) {
|
|
300
|
-
// Prevent infinite recursion
|
|
301
|
-
searchDir(itemPath, depth + 1);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
else if (stats.isFile()) {
|
|
305
|
-
// Simple pattern matching (convert * to regex)
|
|
306
|
-
const regexPattern = pattern
|
|
307
|
-
.replace(/\*/g, ".*")
|
|
308
|
-
.replace(/\?/g, ".");
|
|
309
|
-
const regex = new RegExp(`^${regexPattern}$`, "i");
|
|
310
|
-
if (regex.test(item)) {
|
|
311
|
-
matches.push({
|
|
312
|
-
name: item,
|
|
313
|
-
path: itemPath,
|
|
314
|
-
size: stats.size,
|
|
315
|
-
lastModified: stats.mtime.toISOString(),
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
};
|
|
321
|
-
searchDir(resolvedDir);
|
|
322
|
-
return {
|
|
323
|
-
success: true,
|
|
324
|
-
directory: resolvedDir,
|
|
325
|
-
pattern,
|
|
326
|
-
matches,
|
|
327
|
-
count: matches.length,
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
catch (error) {
|
|
331
|
-
return {
|
|
332
|
-
success: false,
|
|
333
|
-
error: error instanceof Error ? error.message : String(error),
|
|
334
|
-
directory,
|
|
335
|
-
pattern,
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
},
|
|
339
|
-
}),
|
|
267
|
+
// NOTE: searchFiles was removed to avoid naming conflict with external MCP 'search_files' tool
|
|
268
|
+
// from @modelcontextprotocol/server-filesystem which provides the same functionality
|
|
269
|
+
// with parameters {path, pattern, excludePatterns}
|
|
340
270
|
analyzeCSV: tool({
|
|
341
271
|
description: "Analyze CSV file for accurate counting, aggregation, and statistical analysis. Use this for precise data operations like counting rows by column, calculating sums/averages, finding min/max values, etc. The tool reads the file directly - do NOT pass CSV content.",
|
|
342
272
|
parameters: z.object({
|
|
@@ -740,7 +670,6 @@ export function getToolsForCategory(category = "all") {
|
|
|
740
670
|
readFile: directAgentTools.readFile,
|
|
741
671
|
listDirectory: directAgentTools.listDirectory,
|
|
742
672
|
writeFile: directAgentTools.writeFile,
|
|
743
|
-
searchFiles: directAgentTools.searchFiles,
|
|
744
673
|
};
|
|
745
674
|
case "utility":
|
|
746
675
|
return {
|
|
@@ -72,6 +72,7 @@ export declare enum GoogleAIModels {
|
|
|
72
72
|
* Supported Models for Anthropic (Direct API)
|
|
73
73
|
*/
|
|
74
74
|
export declare enum AnthropicModels {
|
|
75
|
+
CLAUDE_4_5_HAIKU = "claude-haiku-4-5-20251001",
|
|
75
76
|
CLAUDE_3_5_SONNET = "claude-3-5-sonnet-20241022",
|
|
76
77
|
CLAUDE_3_5_HAIKU = "claude-3-5-haiku-20241022",
|
|
77
78
|
CLAUDE_3_SONNET = "claude-3-sonnet-20240229",
|
|
@@ -91,7 +91,9 @@ export var GoogleAIModels;
|
|
|
91
91
|
*/
|
|
92
92
|
export var AnthropicModels;
|
|
93
93
|
(function (AnthropicModels) {
|
|
94
|
-
// Claude
|
|
94
|
+
// Claude 4.5 Series (Latest - October 2025)
|
|
95
|
+
AnthropicModels["CLAUDE_4_5_HAIKU"] = "claude-haiku-4-5-20251001";
|
|
96
|
+
// Claude 3.5 Series
|
|
95
97
|
AnthropicModels["CLAUDE_3_5_SONNET"] = "claude-3-5-sonnet-20241022";
|
|
96
98
|
AnthropicModels["CLAUDE_3_5_HAIKU"] = "claude-3-5-haiku-20241022";
|
|
97
99
|
// Claude 3 Series (Legacy support)
|
|
@@ -63,6 +63,7 @@ export declare const PROVIDER_TOKEN_LIMITS: {
|
|
|
63
63
|
readonly "claude-3-5-sonnet-20241022": 4096;
|
|
64
64
|
readonly "claude-3-opus-20240229": 4096;
|
|
65
65
|
readonly "claude-3-5-haiku-20241022": 4096;
|
|
66
|
+
readonly "claude-haiku-4-5-20251001": 8192;
|
|
66
67
|
readonly "claude-3-sonnet-20240229": 4096;
|
|
67
68
|
readonly default: 4096;
|
|
68
69
|
};
|
|
@@ -100,6 +101,7 @@ export declare const PROVIDER_TOKEN_LIMITS: {
|
|
|
100
101
|
readonly "claude-opus-4@20250514": 4096;
|
|
101
102
|
readonly "claude-3-5-sonnet-20241022": 4096;
|
|
102
103
|
readonly "claude-3-5-haiku-20241022": 4096;
|
|
104
|
+
readonly "claude-haiku-4-5-20251001": 8192;
|
|
103
105
|
readonly "claude-3-sonnet-20240229": 4096;
|
|
104
106
|
readonly "claude-3-haiku-20240307": 4096;
|
|
105
107
|
readonly "claude-3-opus-20240229": 4096;
|
|
@@ -111,6 +113,7 @@ export declare const PROVIDER_TOKEN_LIMITS: {
|
|
|
111
113
|
readonly "anthropic.claude-3-haiku-20240307-v1:0": 4096;
|
|
112
114
|
readonly "anthropic.claude-3-5-sonnet-20240620-v1:0": 4096;
|
|
113
115
|
readonly "anthropic.claude-3-opus-20240229-v1:0": 4096;
|
|
116
|
+
readonly "anthropic.claude-haiku-4-5-20251001-v1:0": 8192;
|
|
114
117
|
readonly "arn:aws:bedrock:us-east-2:225681119357:inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0": 4096;
|
|
115
118
|
readonly default: 4096;
|
|
116
119
|
};
|