@juspay/neurolink 7.14.1 → 7.14.3
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/dist/cli/commands/config.d.ts +66 -66
- package/dist/core/baseProvider.d.ts +12 -7
- package/dist/core/baseProvider.js +118 -125
- package/dist/core/constants.d.ts +5 -0
- package/dist/core/constants.js +6 -0
- package/dist/core/dynamicModels.d.ts +4 -4
- package/dist/core/factory.d.ts +2 -4
- package/dist/core/types.d.ts +8 -22
- package/dist/index.d.ts +19 -4
- package/dist/index.js +21 -0
- package/dist/lib/core/baseProvider.d.ts +12 -7
- package/dist/lib/core/baseProvider.js +118 -125
- package/dist/lib/core/constants.d.ts +5 -0
- package/dist/lib/core/constants.js +6 -0
- package/dist/lib/core/dynamicModels.d.ts +8 -8
- package/dist/lib/core/factory.d.ts +2 -4
- package/dist/lib/core/types.d.ts +8 -22
- package/dist/lib/index.d.ts +19 -4
- package/dist/lib/index.js +21 -0
- package/dist/lib/mcp/contracts/mcpContract.d.ts +6 -19
- package/dist/lib/mcp/externalServerManager.d.ts +2 -4
- package/dist/lib/mcp/externalServerManager.js +7 -8
- package/dist/lib/mcp/factory.d.ts +61 -7
- package/dist/lib/mcp/factory.js +36 -23
- package/dist/lib/mcp/mcpClientFactory.d.ts +2 -1
- package/dist/lib/mcp/mcpClientFactory.js +73 -26
- package/dist/lib/mcp/registry.d.ts +1 -1
- package/dist/lib/mcp/toolDiscoveryService.d.ts +1 -1
- package/dist/lib/mcp/toolDiscoveryService.js +50 -19
- package/dist/lib/mcp/toolRegistry.d.ts +23 -1
- package/dist/lib/mcp/toolRegistry.js +108 -17
- package/dist/lib/models/modelResolver.js +2 -1
- package/dist/lib/neurolink.d.ts +12 -8
- package/dist/lib/neurolink.js +130 -134
- package/dist/lib/providers/amazonBedrock.d.ts +2 -2
- package/dist/lib/providers/anthropic.d.ts +3 -3
- package/dist/lib/providers/googleAiStudio.d.ts +2 -2
- package/dist/lib/providers/mistral.d.ts +3 -3
- package/dist/lib/providers/ollama.d.ts +2 -2
- package/dist/lib/providers/openAI.d.ts +3 -3
- package/dist/lib/providers/openaiCompatible.d.ts +2 -2
- package/dist/lib/providers/sagemaker/client.d.ts +2 -5
- package/dist/lib/providers/sagemaker/language-model.d.ts +4 -6
- package/dist/lib/providers/sagemaker/parsers.js +5 -4
- package/dist/lib/sdk/toolRegistration.d.ts +6 -6
- package/dist/lib/sdk/toolRegistration.js +17 -56
- package/dist/lib/types/generateTypes.d.ts +9 -9
- package/dist/lib/types/streamTypes.d.ts +4 -4
- package/dist/lib/types/tools.d.ts +15 -7
- package/dist/lib/types/typeAliases.d.ts +412 -0
- package/dist/lib/types/typeAliases.js +48 -0
- package/dist/lib/utils/factoryProcessing.d.ts +2 -1
- package/dist/lib/utils/factoryProcessing.js +4 -3
- package/dist/lib/utils/parameterValidation.d.ts +97 -0
- package/dist/lib/utils/parameterValidation.js +452 -0
- package/dist/lib/utils/transformationUtils.d.ts +204 -0
- package/dist/lib/utils/transformationUtils.js +334 -0
- package/dist/lib/utils/typeUtils.d.ts +77 -0
- package/dist/lib/utils/typeUtils.js +97 -0
- package/dist/mcp/contracts/mcpContract.d.ts +6 -19
- package/dist/mcp/externalServerManager.d.ts +2 -4
- package/dist/mcp/externalServerManager.js +7 -8
- package/dist/mcp/factory.d.ts +61 -7
- package/dist/mcp/factory.js +36 -23
- package/dist/mcp/mcpClientFactory.d.ts +2 -1
- package/dist/mcp/mcpClientFactory.js +73 -26
- package/dist/mcp/registry.d.ts +1 -1
- package/dist/mcp/toolDiscoveryService.d.ts +1 -1
- package/dist/mcp/toolDiscoveryService.js +50 -19
- package/dist/mcp/toolRegistry.d.ts +23 -1
- package/dist/mcp/toolRegistry.js +108 -17
- package/dist/models/modelResolver.js +2 -1
- package/dist/neurolink.d.ts +12 -8
- package/dist/neurolink.js +130 -134
- package/dist/providers/amazonBedrock.d.ts +2 -2
- package/dist/providers/anthropic.d.ts +3 -3
- package/dist/providers/googleAiStudio.d.ts +2 -2
- package/dist/providers/mistral.d.ts +3 -3
- package/dist/providers/ollama.d.ts +2 -2
- package/dist/providers/openAI.d.ts +3 -3
- package/dist/providers/openaiCompatible.d.ts +2 -2
- package/dist/providers/sagemaker/client.d.ts +2 -5
- package/dist/providers/sagemaker/language-model.d.ts +4 -6
- package/dist/providers/sagemaker/parsers.js +5 -4
- package/dist/sdk/toolRegistration.d.ts +6 -6
- package/dist/sdk/toolRegistration.js +17 -56
- package/dist/types/generateTypes.d.ts +9 -9
- package/dist/types/streamTypes.d.ts +4 -4
- package/dist/types/tools.d.ts +15 -7
- package/dist/types/typeAliases.d.ts +412 -0
- package/dist/types/typeAliases.js +48 -0
- package/dist/utils/factoryProcessing.d.ts +2 -1
- package/dist/utils/factoryProcessing.js +4 -3
- package/dist/utils/parameterValidation.d.ts +97 -0
- package/dist/utils/parameterValidation.js +452 -0
- package/dist/utils/transformationUtils.d.ts +204 -0
- package/dist/utils/transformationUtils.js +334 -0
- package/dist/utils/typeUtils.d.ts +77 -0
- package/dist/utils/typeUtils.js +97 -0
- package/package.json +1 -1
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameter Validation Utilities
|
|
3
|
+
* Provides consistent parameter validation across all tool interfaces
|
|
4
|
+
*/
|
|
5
|
+
import { SYSTEM_LIMITS } from "../core/constants.js";
|
|
6
|
+
import { isNonNullObject } from "./typeUtils.js";
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// VALIDATION ERROR TYPES
|
|
9
|
+
// ============================================================================
|
|
10
|
+
/**
|
|
11
|
+
* Custom error class for parameter validation failures
|
|
12
|
+
* Provides detailed information about validation errors including field context and suggestions
|
|
13
|
+
*/
|
|
14
|
+
export class ValidationError extends Error {
|
|
15
|
+
field;
|
|
16
|
+
code;
|
|
17
|
+
suggestions;
|
|
18
|
+
/**
|
|
19
|
+
* Creates a new ValidationError
|
|
20
|
+
* @param message - Human-readable error message
|
|
21
|
+
* @param field - Name of the field that failed validation (optional)
|
|
22
|
+
* @param code - Error code for programmatic handling (optional)
|
|
23
|
+
* @param suggestions - Array of suggested fixes (optional)
|
|
24
|
+
*/
|
|
25
|
+
constructor(message, field, code, suggestions) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.field = field;
|
|
28
|
+
this.code = code;
|
|
29
|
+
this.suggestions = suggestions;
|
|
30
|
+
this.name = "ValidationError";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// BASIC PARAMETER VALIDATORS
|
|
35
|
+
// ============================================================================
|
|
36
|
+
/**
|
|
37
|
+
* Validate that a string parameter is present and non-empty
|
|
38
|
+
*/
|
|
39
|
+
export function validateRequiredString(value, fieldName, minLength = 1) {
|
|
40
|
+
if (value === undefined || value === null) {
|
|
41
|
+
return new ValidationError(`${fieldName} is required`, fieldName, "REQUIRED_FIELD", [`Provide a valid ${fieldName.toLowerCase()}`]);
|
|
42
|
+
}
|
|
43
|
+
if (typeof value !== "string") {
|
|
44
|
+
return new ValidationError(`${fieldName} must be a string, received ${typeof value}`, fieldName, "INVALID_TYPE", [`Convert ${fieldName.toLowerCase()} to string format`]);
|
|
45
|
+
}
|
|
46
|
+
if (value.trim().length < minLength) {
|
|
47
|
+
return new ValidationError(`${fieldName} must be at least ${minLength} character${minLength > 1 ? "s" : ""} long`, fieldName, "MIN_LENGTH", [`Provide a meaningful ${fieldName.toLowerCase()}`]);
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Validate that a number parameter is within acceptable range
|
|
53
|
+
*/
|
|
54
|
+
export function validateNumberRange(value, fieldName, min, max, required = false) {
|
|
55
|
+
if (value === undefined || value === null) {
|
|
56
|
+
if (required) {
|
|
57
|
+
return new ValidationError(`${fieldName} is required`, fieldName, "REQUIRED_FIELD", [`Provide a number between ${min} and ${max}`]);
|
|
58
|
+
}
|
|
59
|
+
return null; // Optional field
|
|
60
|
+
}
|
|
61
|
+
if (typeof value !== "number" || isNaN(value)) {
|
|
62
|
+
return new ValidationError(`${fieldName} must be a valid number, received ${typeof value}`, fieldName, "INVALID_TYPE", [`Provide a number between ${min} and ${max}`]);
|
|
63
|
+
}
|
|
64
|
+
if (value < min || value > max) {
|
|
65
|
+
return new ValidationError(`${fieldName} must be between ${min} and ${max}, received ${value}`, fieldName, "OUT_OF_RANGE", [`Use a value between ${min} and ${max}`]);
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Validate that a function parameter is async and has correct signature
|
|
71
|
+
*/
|
|
72
|
+
export function validateAsyncFunction(value, fieldName, expectedParams = []) {
|
|
73
|
+
if (typeof value !== "function") {
|
|
74
|
+
return new ValidationError(`${fieldName} must be a function, received ${typeof value}`, fieldName, "INVALID_TYPE", [
|
|
75
|
+
"Provide an async function",
|
|
76
|
+
`Expected signature: async (${expectedParams.join(", ")}) => Promise<unknown>`,
|
|
77
|
+
]);
|
|
78
|
+
}
|
|
79
|
+
// Check if function appears to be async
|
|
80
|
+
const funcStr = value.toString();
|
|
81
|
+
const isAsync = funcStr.includes("async") || funcStr.includes("Promise");
|
|
82
|
+
if (!isAsync) {
|
|
83
|
+
return new ValidationError(`${fieldName} must be an async function that returns a Promise`, fieldName, "NOT_ASYNC", [
|
|
84
|
+
"Add 'async' keyword to function declaration",
|
|
85
|
+
"Return a Promise from the function",
|
|
86
|
+
`Example: async (${expectedParams.join(", ")}) => { return result; }`,
|
|
87
|
+
]);
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Validate object structure with required properties
|
|
93
|
+
*/
|
|
94
|
+
export function validateObjectStructure(value, fieldName, requiredProperties, optionalProperties = []) {
|
|
95
|
+
if (!isNonNullObject(value)) {
|
|
96
|
+
return new ValidationError(`${fieldName} must be an object, received ${typeof value}`, fieldName, "INVALID_TYPE", [
|
|
97
|
+
`Provide an object with properties: ${requiredProperties.join(", ")}`,
|
|
98
|
+
...(optionalProperties.length > 0
|
|
99
|
+
? [`Optional properties: ${optionalProperties.join(", ")}`]
|
|
100
|
+
: []),
|
|
101
|
+
]);
|
|
102
|
+
}
|
|
103
|
+
const obj = value;
|
|
104
|
+
const missingProps = requiredProperties.filter((prop) => !(prop in obj));
|
|
105
|
+
if (missingProps.length > 0) {
|
|
106
|
+
return new ValidationError(`${fieldName} is missing required properties: ${missingProps.join(", ")}`, fieldName, "MISSING_PROPERTIES", [`Add missing properties: ${missingProps.join(", ")}`]);
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
// ============================================================================
|
|
111
|
+
// TOOL-SPECIFIC VALIDATORS
|
|
112
|
+
// ============================================================================
|
|
113
|
+
/**
|
|
114
|
+
* Validate tool name according to naming conventions
|
|
115
|
+
*/
|
|
116
|
+
export function validateToolName(name) {
|
|
117
|
+
const error = validateRequiredString(name, "Tool name", 1);
|
|
118
|
+
if (error) {
|
|
119
|
+
return error;
|
|
120
|
+
}
|
|
121
|
+
const toolName = name;
|
|
122
|
+
// Check naming conventions
|
|
123
|
+
if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(toolName)) {
|
|
124
|
+
return new ValidationError("Tool name must start with a letter and contain only letters, numbers, underscores, and hyphens", "name", "INVALID_FORMAT", [
|
|
125
|
+
"Use alphanumeric characters, underscores, and hyphens only",
|
|
126
|
+
"Start with a letter",
|
|
127
|
+
"Examples: 'calculateSum', 'data_processor', 'api-client'",
|
|
128
|
+
]);
|
|
129
|
+
}
|
|
130
|
+
if (toolName.length > 64) {
|
|
131
|
+
return new ValidationError(`Tool name too long: ${toolName.length} characters (max: 64)`, "name", "MAX_LENGTH", ["Use a shorter, more concise name"]);
|
|
132
|
+
}
|
|
133
|
+
// Reserved names check
|
|
134
|
+
const reservedNames = ["execute", "validate", "setup", "init", "config"];
|
|
135
|
+
if (reservedNames.includes(toolName.toLowerCase())) {
|
|
136
|
+
return new ValidationError(`Tool name '${toolName}' is reserved`, "name", "RESERVED_NAME", ["Choose a different name", "Add a prefix or suffix to make it unique"]);
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Validate tool description for clarity and usefulness
|
|
142
|
+
*/
|
|
143
|
+
export function validateToolDescription(description) {
|
|
144
|
+
const error = validateRequiredString(description, "Tool description", 10);
|
|
145
|
+
if (error) {
|
|
146
|
+
return error;
|
|
147
|
+
}
|
|
148
|
+
const desc = description;
|
|
149
|
+
if (desc.length > 500) {
|
|
150
|
+
return new ValidationError(`Tool description too long: ${desc.length} characters (max: 500)`, "description", "MAX_LENGTH", ["Keep description concise and focused", "Use under 500 characters"]);
|
|
151
|
+
}
|
|
152
|
+
// Check for meaningful content
|
|
153
|
+
const meaningfulWords = desc.split(/\s+/).filter((word) => word.length > 2);
|
|
154
|
+
if (meaningfulWords.length < 3) {
|
|
155
|
+
return new ValidationError("Tool description should be more descriptive", "description", "TOO_BRIEF", [
|
|
156
|
+
"Explain what the tool does",
|
|
157
|
+
"Include expected parameters",
|
|
158
|
+
"Describe the return value",
|
|
159
|
+
]);
|
|
160
|
+
}
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Validate MCP tool structure comprehensively
|
|
165
|
+
*/
|
|
166
|
+
export function validateMCPTool(tool) {
|
|
167
|
+
const errors = [];
|
|
168
|
+
const warnings = [];
|
|
169
|
+
const suggestions = [];
|
|
170
|
+
if (!isNonNullObject(tool)) {
|
|
171
|
+
errors.push(new ValidationError("Tool must be an object", "tool", "INVALID_TYPE", [
|
|
172
|
+
"Provide a valid tool object with name, description, and execute properties",
|
|
173
|
+
]));
|
|
174
|
+
return { isValid: false, errors, warnings, suggestions };
|
|
175
|
+
}
|
|
176
|
+
const mcpTool = tool;
|
|
177
|
+
// Validate name
|
|
178
|
+
const nameError = validateToolName(mcpTool.name);
|
|
179
|
+
if (nameError) {
|
|
180
|
+
errors.push(nameError);
|
|
181
|
+
}
|
|
182
|
+
// Validate description
|
|
183
|
+
const descError = validateToolDescription(mcpTool.description);
|
|
184
|
+
if (descError) {
|
|
185
|
+
errors.push(descError);
|
|
186
|
+
}
|
|
187
|
+
// Validate execute function
|
|
188
|
+
const execError = validateAsyncFunction(mcpTool.execute, "execute function", [
|
|
189
|
+
"params",
|
|
190
|
+
"context",
|
|
191
|
+
]);
|
|
192
|
+
if (execError) {
|
|
193
|
+
errors.push(execError);
|
|
194
|
+
}
|
|
195
|
+
// Additional MCP-specific validation
|
|
196
|
+
if (mcpTool.execute) {
|
|
197
|
+
try {
|
|
198
|
+
// Test execute function with mock data
|
|
199
|
+
const mockParams = {};
|
|
200
|
+
const mockContext = {
|
|
201
|
+
sessionId: "validation-test",
|
|
202
|
+
userId: "validation-user",
|
|
203
|
+
};
|
|
204
|
+
const result = mcpTool.execute(mockParams, mockContext);
|
|
205
|
+
const returnsPromise = result && typeof result === "object" && "then" in result;
|
|
206
|
+
if (!returnsPromise) {
|
|
207
|
+
errors.push(new ValidationError("Execute function must return a Promise", "execute", "NOT_PROMISE", [
|
|
208
|
+
"Ensure function returns a Promise<ToolResult>",
|
|
209
|
+
"Use async/await pattern",
|
|
210
|
+
"Return a result object with success property",
|
|
211
|
+
]));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
warnings.push(`Execute function validation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// Check optional properties
|
|
219
|
+
if (mcpTool.inputSchema && !isNonNullObject(mcpTool.inputSchema)) {
|
|
220
|
+
warnings.push("inputSchema should be an object if provided");
|
|
221
|
+
suggestions.push("Provide a valid JSON schema or Zod schema for input validation");
|
|
222
|
+
}
|
|
223
|
+
if (mcpTool.outputSchema && !isNonNullObject(mcpTool.outputSchema)) {
|
|
224
|
+
warnings.push("outputSchema should be an object if provided");
|
|
225
|
+
suggestions.push("Provide a valid JSON schema or Zod schema for output validation");
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
isValid: errors.length === 0,
|
|
229
|
+
errors,
|
|
230
|
+
warnings,
|
|
231
|
+
suggestions,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
// ============================================================================
|
|
235
|
+
// OPTIONS VALIDATORS
|
|
236
|
+
// ============================================================================
|
|
237
|
+
/**
|
|
238
|
+
* Validate text generation options
|
|
239
|
+
*/
|
|
240
|
+
export function validateTextGenerationOptions(options) {
|
|
241
|
+
const errors = [];
|
|
242
|
+
const warnings = [];
|
|
243
|
+
const suggestions = [];
|
|
244
|
+
if (!isNonNullObject(options)) {
|
|
245
|
+
errors.push(new ValidationError("Options must be an object", "options", "INVALID_TYPE"));
|
|
246
|
+
return { isValid: false, errors, warnings, suggestions };
|
|
247
|
+
}
|
|
248
|
+
const opts = options;
|
|
249
|
+
// Validate prompt
|
|
250
|
+
const promptError = validateRequiredString(opts.prompt, "prompt", 1);
|
|
251
|
+
if (promptError) {
|
|
252
|
+
errors.push(promptError);
|
|
253
|
+
}
|
|
254
|
+
if (opts.prompt && opts.prompt.length > SYSTEM_LIMITS.MAX_PROMPT_LENGTH) {
|
|
255
|
+
errors.push(new ValidationError(`Prompt too large: ${opts.prompt.length} characters (max: ${SYSTEM_LIMITS.MAX_PROMPT_LENGTH})`, "prompt", "MAX_LENGTH", [
|
|
256
|
+
"Break prompt into smaller chunks",
|
|
257
|
+
"Use summarization for long content",
|
|
258
|
+
"Consider using streaming for large inputs",
|
|
259
|
+
]));
|
|
260
|
+
}
|
|
261
|
+
// Validate temperature
|
|
262
|
+
const tempError = validateNumberRange(opts.temperature, "temperature", 0, 2);
|
|
263
|
+
if (tempError) {
|
|
264
|
+
errors.push(tempError);
|
|
265
|
+
}
|
|
266
|
+
// Validate maxTokens
|
|
267
|
+
const tokensError = validateNumberRange(opts.maxTokens, "maxTokens", 1, 200000);
|
|
268
|
+
if (tokensError) {
|
|
269
|
+
errors.push(tokensError);
|
|
270
|
+
}
|
|
271
|
+
// Validate timeout
|
|
272
|
+
if (opts.timeout !== undefined) {
|
|
273
|
+
if (typeof opts.timeout === "string") {
|
|
274
|
+
// Parse string timeouts like "30s", "2m", "1h"
|
|
275
|
+
if (!/^\d+[smh]?$/.test(opts.timeout)) {
|
|
276
|
+
errors.push(new ValidationError("Invalid timeout format. Use number (ms) or string like '30s', '2m', '1h'", "timeout", "INVALID_FORMAT", ["Use format: 30000 (ms), '30s', '2m', or '1h'"]));
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
else if (typeof opts.timeout === "number") {
|
|
280
|
+
if (opts.timeout < 1000 || opts.timeout > 600000) {
|
|
281
|
+
warnings.push("Timeout outside recommended range (1s - 10m)");
|
|
282
|
+
suggestions.push("Use timeout between 1000ms (1s) and 600000ms (10m)");
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
errors.push(new ValidationError("Timeout must be a number (ms) or string", "timeout", "INVALID_TYPE"));
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return { isValid: errors.length === 0, errors, warnings, suggestions };
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Validate stream options
|
|
293
|
+
*/
|
|
294
|
+
export function validateStreamOptions(options) {
|
|
295
|
+
const errors = [];
|
|
296
|
+
const warnings = [];
|
|
297
|
+
const suggestions = [];
|
|
298
|
+
if (!isNonNullObject(options)) {
|
|
299
|
+
errors.push(new ValidationError("Options must be an object", "options", "INVALID_TYPE"));
|
|
300
|
+
return { isValid: false, errors, warnings, suggestions };
|
|
301
|
+
}
|
|
302
|
+
const opts = options;
|
|
303
|
+
// Validate input
|
|
304
|
+
if (!opts.input || !isNonNullObject(opts.input)) {
|
|
305
|
+
errors.push(new ValidationError("input is required and must be an object with text property", "input", "REQUIRED_FIELD", ["Provide input: { text: 'your prompt here' }"]));
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
const inputError = validateRequiredString(opts.input.text, "input.text", 1);
|
|
309
|
+
if (inputError) {
|
|
310
|
+
errors.push(inputError);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
// Validate temperature
|
|
314
|
+
const tempError = validateNumberRange(opts.temperature, "temperature", 0, 2);
|
|
315
|
+
if (tempError) {
|
|
316
|
+
errors.push(tempError);
|
|
317
|
+
}
|
|
318
|
+
// Validate maxTokens
|
|
319
|
+
const tokensError = validateNumberRange(opts.maxTokens, "maxTokens", 1, 200000);
|
|
320
|
+
if (tokensError) {
|
|
321
|
+
errors.push(tokensError);
|
|
322
|
+
}
|
|
323
|
+
return { isValid: errors.length === 0, errors, warnings, suggestions };
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Validate generate options (unified interface)
|
|
327
|
+
*/
|
|
328
|
+
export function validateGenerateOptions(options) {
|
|
329
|
+
const errors = [];
|
|
330
|
+
const warnings = [];
|
|
331
|
+
const suggestions = [];
|
|
332
|
+
if (!isNonNullObject(options)) {
|
|
333
|
+
errors.push(new ValidationError("Options must be an object", "options", "INVALID_TYPE"));
|
|
334
|
+
return { isValid: false, errors, warnings, suggestions };
|
|
335
|
+
}
|
|
336
|
+
const opts = options;
|
|
337
|
+
// Validate input
|
|
338
|
+
if (!opts.input || !isNonNullObject(opts.input)) {
|
|
339
|
+
errors.push(new ValidationError("input is required and must be an object with text property", "input", "REQUIRED_FIELD", ["Provide input: { text: 'your prompt here' }"]));
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
const inputError = validateRequiredString(opts.input.text, "input.text", 1);
|
|
343
|
+
if (inputError) {
|
|
344
|
+
errors.push(inputError);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
// Common validation for temperature and maxTokens
|
|
348
|
+
const tempError = validateNumberRange(opts.temperature, "temperature", 0, 2);
|
|
349
|
+
if (tempError) {
|
|
350
|
+
errors.push(tempError);
|
|
351
|
+
}
|
|
352
|
+
const tokensError = validateNumberRange(opts.maxTokens, "maxTokens", 1, 200000);
|
|
353
|
+
if (tokensError) {
|
|
354
|
+
errors.push(tokensError);
|
|
355
|
+
}
|
|
356
|
+
// Validate factory config if present
|
|
357
|
+
if (opts.factoryConfig && !isNonNullObject(opts.factoryConfig)) {
|
|
358
|
+
warnings.push("factoryConfig should be an object if provided");
|
|
359
|
+
suggestions.push("Provide valid factory configuration or remove the property");
|
|
360
|
+
}
|
|
361
|
+
return { isValid: errors.length === 0, errors, warnings, suggestions };
|
|
362
|
+
}
|
|
363
|
+
// ============================================================================
|
|
364
|
+
// PARAMETER TRANSFORMATION VALIDATORS
|
|
365
|
+
// ============================================================================
|
|
366
|
+
/**
|
|
367
|
+
* Validate tool execution parameters
|
|
368
|
+
*/
|
|
369
|
+
export function validateToolExecutionParams(toolName, params, expectedSchema) {
|
|
370
|
+
const errors = [];
|
|
371
|
+
const warnings = [];
|
|
372
|
+
const suggestions = [];
|
|
373
|
+
// Basic parameter validation
|
|
374
|
+
if (params !== undefined && params !== null && !isNonNullObject(params)) {
|
|
375
|
+
errors.push(new ValidationError(`Parameters for tool '${toolName}' must be an object`, "params", "INVALID_TYPE", ["Provide parameters as an object: { key: value, ... }"]));
|
|
376
|
+
return { isValid: false, errors, warnings, suggestions };
|
|
377
|
+
}
|
|
378
|
+
// Schema validation (if provided)
|
|
379
|
+
if (expectedSchema && params) {
|
|
380
|
+
try {
|
|
381
|
+
// This is a placeholder for actual schema validation
|
|
382
|
+
// In practice, you would use Zod or JSON schema validation here
|
|
383
|
+
warnings.push("Schema validation not yet implemented");
|
|
384
|
+
suggestions.push("Implement Zod schema validation for tool parameters");
|
|
385
|
+
}
|
|
386
|
+
catch (error) {
|
|
387
|
+
errors.push(new ValidationError(`Parameter validation failed: ${error instanceof Error ? error.message : String(error)}`, "params", "SCHEMA_VALIDATION", ["Check parameter format against tool schema"]));
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return { isValid: errors.length === 0, errors, warnings, suggestions };
|
|
391
|
+
}
|
|
392
|
+
// ============================================================================
|
|
393
|
+
// BATCH VALIDATION UTILITIES
|
|
394
|
+
// ============================================================================
|
|
395
|
+
/**
|
|
396
|
+
* Validate multiple tools at once
|
|
397
|
+
*/
|
|
398
|
+
export function validateToolBatch(tools) {
|
|
399
|
+
const validTools = [];
|
|
400
|
+
const invalidTools = [];
|
|
401
|
+
const results = {};
|
|
402
|
+
for (const [name, tool] of Object.entries(tools)) {
|
|
403
|
+
const nameValidation = validateToolName(name);
|
|
404
|
+
const toolValidation = validateMCPTool(tool);
|
|
405
|
+
const combinedResult = {
|
|
406
|
+
isValid: !nameValidation && toolValidation.isValid,
|
|
407
|
+
errors: nameValidation
|
|
408
|
+
? [nameValidation, ...toolValidation.errors]
|
|
409
|
+
: toolValidation.errors,
|
|
410
|
+
warnings: toolValidation.warnings,
|
|
411
|
+
suggestions: toolValidation.suggestions,
|
|
412
|
+
};
|
|
413
|
+
results[name] = combinedResult;
|
|
414
|
+
if (combinedResult.isValid) {
|
|
415
|
+
validTools.push(name);
|
|
416
|
+
}
|
|
417
|
+
else {
|
|
418
|
+
invalidTools.push(name);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return {
|
|
422
|
+
isValid: invalidTools.length === 0,
|
|
423
|
+
validTools,
|
|
424
|
+
invalidTools,
|
|
425
|
+
results,
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
// ============================================================================
|
|
429
|
+
// HELPER FUNCTIONS
|
|
430
|
+
// ============================================================================
|
|
431
|
+
/**
|
|
432
|
+
* Create a validation error summary for logging
|
|
433
|
+
*/
|
|
434
|
+
export function createValidationSummary(result) {
|
|
435
|
+
const parts = [];
|
|
436
|
+
if (result.errors.length > 0) {
|
|
437
|
+
parts.push(`Errors: ${result.errors.map((e) => e.message).join("; ")}`);
|
|
438
|
+
}
|
|
439
|
+
if (result.warnings.length > 0) {
|
|
440
|
+
parts.push(`Warnings: ${result.warnings.join("; ")}`);
|
|
441
|
+
}
|
|
442
|
+
if (result.suggestions.length > 0) {
|
|
443
|
+
parts.push(`Suggestions: ${result.suggestions.join("; ")}`);
|
|
444
|
+
}
|
|
445
|
+
return parts.join(" | ");
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Check if validation result has only warnings (no errors)
|
|
449
|
+
*/
|
|
450
|
+
export function hasOnlyWarnings(result) {
|
|
451
|
+
return result.errors.length === 0 && result.warnings.length > 0;
|
|
452
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Object Transformation Utilities
|
|
3
|
+
* Centralizes repeated object transformation patterns to improve code reuse and maintainability
|
|
4
|
+
*/
|
|
5
|
+
import type { StandardRecord, StringArray } from "../types/typeAliases.js";
|
|
6
|
+
/**
|
|
7
|
+
* Transform tool execution results from AI SDK format to NeuroLink GenerateResult format
|
|
8
|
+
* Handles both single execution and array formats with robust type checking
|
|
9
|
+
*
|
|
10
|
+
* @param toolExecutions - Array of tool execution results from AI SDK (optional)
|
|
11
|
+
* @returns Array of standardized tool execution objects with name, input, output, and duration
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const executions = transformToolExecutions([
|
|
16
|
+
* { name: "calculator", input: { a: 5, b: 3 }, output: 8, duration: 150 }
|
|
17
|
+
* ]);
|
|
18
|
+
* // Returns: [{ name: "calculator", input: { a: 5, b: 3 }, output: 8, duration: 150 }]
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function transformToolExecutions(toolExecutions?: unknown[]): Array<{
|
|
22
|
+
name: string;
|
|
23
|
+
input: StandardRecord;
|
|
24
|
+
output: unknown;
|
|
25
|
+
duration: number;
|
|
26
|
+
}>;
|
|
27
|
+
/**
|
|
28
|
+
* Transform tool execution results from AI SDK format to internal format (for MCP generation)
|
|
29
|
+
* Used in tryMCPGeneration method
|
|
30
|
+
*/
|
|
31
|
+
export declare function transformToolExecutionsForMCP(toolExecutions?: unknown[]): Array<{
|
|
32
|
+
toolName: string;
|
|
33
|
+
executionTime: number;
|
|
34
|
+
success: boolean;
|
|
35
|
+
serverId?: string;
|
|
36
|
+
}>;
|
|
37
|
+
/**
|
|
38
|
+
* Transform available tools from internal format to GenerateResult format
|
|
39
|
+
* Ensures consistent tool information structure across the API with schema normalization
|
|
40
|
+
*
|
|
41
|
+
* @param availableTools - Array of tool definitions from various sources (MCP servers, builtin tools, etc.)
|
|
42
|
+
* @returns Array of normalized tool descriptions with consistent schema format
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const tools = transformAvailableTools([
|
|
47
|
+
* { name: "calculator", description: "Math tool", server: "builtin", inputSchema: {...} }
|
|
48
|
+
* ]);
|
|
49
|
+
* // Returns: [{ name: "calculator", description: "Math tool", serverId: "builtin", schema: {...} }]
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare function transformAvailableTools(availableTools?: Array<{
|
|
53
|
+
name: string;
|
|
54
|
+
description: string;
|
|
55
|
+
server: string;
|
|
56
|
+
category?: string;
|
|
57
|
+
inputSchema?: StandardRecord;
|
|
58
|
+
parameters?: StandardRecord;
|
|
59
|
+
schema?: StandardRecord;
|
|
60
|
+
}>): Array<{
|
|
61
|
+
name: string;
|
|
62
|
+
description: string;
|
|
63
|
+
server: string;
|
|
64
|
+
parameters: StandardRecord;
|
|
65
|
+
}>;
|
|
66
|
+
/**
|
|
67
|
+
* Transform tools for MCP generation format
|
|
68
|
+
* Simple transformation for internal MCP tool lists
|
|
69
|
+
*/
|
|
70
|
+
export declare function transformToolsForMCP(availableTools: Array<{
|
|
71
|
+
name: string;
|
|
72
|
+
description: string;
|
|
73
|
+
server: string;
|
|
74
|
+
category?: string;
|
|
75
|
+
}>): Array<{
|
|
76
|
+
name: string;
|
|
77
|
+
description: string;
|
|
78
|
+
server: string;
|
|
79
|
+
category?: string;
|
|
80
|
+
}>;
|
|
81
|
+
/**
|
|
82
|
+
* Transform tools to expected format with required properties
|
|
83
|
+
* Used in getAllAvailableTools method for final output
|
|
84
|
+
*/
|
|
85
|
+
export declare function transformToolsToExpectedFormat(tools: Array<{
|
|
86
|
+
name: string;
|
|
87
|
+
description?: string;
|
|
88
|
+
serverId?: string;
|
|
89
|
+
category?: string;
|
|
90
|
+
inputSchema?: StandardRecord;
|
|
91
|
+
}>): Array<{
|
|
92
|
+
name: string;
|
|
93
|
+
description: string;
|
|
94
|
+
server: string;
|
|
95
|
+
category?: string;
|
|
96
|
+
inputSchema?: StandardRecord;
|
|
97
|
+
}>;
|
|
98
|
+
/**
|
|
99
|
+
* Extract tool names from tool objects
|
|
100
|
+
* Common pattern for creating arrays of tool names
|
|
101
|
+
*/
|
|
102
|
+
export declare function extractToolNames<T extends {
|
|
103
|
+
name: string;
|
|
104
|
+
}>(tools: T[]): StringArray;
|
|
105
|
+
/**
|
|
106
|
+
* Extract object keys as a comma-separated string
|
|
107
|
+
* Common pattern for logging and debugging
|
|
108
|
+
*/
|
|
109
|
+
export declare function getKeysAsString(obj: StandardRecord, fallback?: string): string;
|
|
110
|
+
/**
|
|
111
|
+
* Count object properties
|
|
112
|
+
* Common pattern for metrics and logging
|
|
113
|
+
*/
|
|
114
|
+
export declare function getKeyCount(obj: StandardRecord): number;
|
|
115
|
+
/**
|
|
116
|
+
* Transform schema properties to parameter descriptions
|
|
117
|
+
* Used in tool-aware system prompt generation
|
|
118
|
+
*/
|
|
119
|
+
export declare function transformSchemaToParameterDescription(schema: {
|
|
120
|
+
properties?: StandardRecord;
|
|
121
|
+
required?: string[];
|
|
122
|
+
}): string;
|
|
123
|
+
/**
|
|
124
|
+
* Transform tools to tool descriptions for system prompts
|
|
125
|
+
* Consolidated pattern for creating tool-aware prompts
|
|
126
|
+
*/
|
|
127
|
+
export declare function transformToolsToDescriptions(availableTools: Array<{
|
|
128
|
+
name: string;
|
|
129
|
+
description: string;
|
|
130
|
+
server: string;
|
|
131
|
+
inputSchema?: StandardRecord;
|
|
132
|
+
}>): string;
|
|
133
|
+
/**
|
|
134
|
+
* Transform parameters for validation
|
|
135
|
+
* Common pattern when logging or checking parameter structures
|
|
136
|
+
*/
|
|
137
|
+
export declare function transformParamsForLogging(params: unknown): string;
|
|
138
|
+
/**
|
|
139
|
+
* Safe property extraction from unknown objects
|
|
140
|
+
* Common pattern for safely accessing properties from unknown structures
|
|
141
|
+
*/
|
|
142
|
+
export declare function safeExtractProperty<T = unknown>(obj: unknown, key: string, fallback: T): T;
|
|
143
|
+
/**
|
|
144
|
+
* Safe extraction of string properties
|
|
145
|
+
* Specialized version for string properties with fallback
|
|
146
|
+
*/
|
|
147
|
+
export declare function safeExtractString(obj: unknown, key: string, fallback?: string): string;
|
|
148
|
+
/**
|
|
149
|
+
* Safe extraction of number properties
|
|
150
|
+
* Specialized version for number properties with fallback
|
|
151
|
+
*/
|
|
152
|
+
export declare function safeExtractNumber(obj: unknown, key: string, fallback?: number): number;
|
|
153
|
+
/**
|
|
154
|
+
* Safe extraction of boolean properties
|
|
155
|
+
* Specialized version for boolean properties with fallback
|
|
156
|
+
*/
|
|
157
|
+
export declare function safeExtractBoolean(obj: unknown, key: string, fallback?: boolean): boolean;
|
|
158
|
+
/**
|
|
159
|
+
* Transform Map to array of values
|
|
160
|
+
* Common pattern for converting tool maps to arrays
|
|
161
|
+
*/
|
|
162
|
+
export declare function mapToArray<T>(map: Map<string, T>): T[];
|
|
163
|
+
/**
|
|
164
|
+
* Transform Map to array of key-value pairs
|
|
165
|
+
* Common pattern for processing map entries
|
|
166
|
+
*/
|
|
167
|
+
export declare function mapToEntries<T>(map: Map<string, T>): Array<[string, T]>;
|
|
168
|
+
/**
|
|
169
|
+
* Group array items by a key
|
|
170
|
+
* Common pattern for organizing tools or other objects by category
|
|
171
|
+
*/
|
|
172
|
+
export declare function groupBy<T>(items: T[], keyFn: (item: T) => string): Map<string, T[]>;
|
|
173
|
+
/**
|
|
174
|
+
* Remove undefined properties from objects
|
|
175
|
+
* Common pattern for cleaning up object structures
|
|
176
|
+
*/
|
|
177
|
+
export declare function removeUndefinedProperties<T extends StandardRecord>(obj: T): T;
|
|
178
|
+
/**
|
|
179
|
+
* Merge objects with undefined handling
|
|
180
|
+
* Common pattern for combining configuration objects
|
|
181
|
+
*/
|
|
182
|
+
export declare function mergeWithUndefinedHandling<T extends StandardRecord>(target: T, ...sources: Partial<T>[]): T;
|
|
183
|
+
/**
|
|
184
|
+
* Optimize tool information for collection with minimal object creation
|
|
185
|
+
* Consolidates repeated optimization patterns across different tool sources
|
|
186
|
+
*
|
|
187
|
+
* @param tool - Tool information to optimize
|
|
188
|
+
* @param defaults - Default values to apply if missing
|
|
189
|
+
* @returns Optimized tool with minimal object creation
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* ```typescript
|
|
193
|
+
* const optimized = optimizeToolForCollection(tool, {
|
|
194
|
+
* serverId: "builtin",
|
|
195
|
+
* category: "math"
|
|
196
|
+
* });
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
export declare function optimizeToolForCollection<T extends Record<string, unknown>>(tool: T, defaults: {
|
|
200
|
+
description?: string;
|
|
201
|
+
serverId?: string;
|
|
202
|
+
category?: string;
|
|
203
|
+
inputSchema?: StandardRecord;
|
|
204
|
+
}): T;
|