@juspay/neurolink 7.6.0 → 7.7.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 +14 -2
- package/README.md +79 -4
- package/dist/cli/commands/config.d.ts +275 -3
- package/dist/cli/commands/config.js +121 -0
- package/dist/cli/commands/mcp.js +77 -28
- package/dist/cli/factories/commandFactory.js +359 -6
- package/dist/core/analytics.js +7 -27
- package/dist/core/baseProvider.js +43 -4
- package/dist/core/constants.d.ts +46 -0
- package/dist/core/constants.js +47 -0
- package/dist/core/dynamicModels.d.ts +16 -4
- package/dist/core/dynamicModels.js +130 -26
- package/dist/core/evaluation.js +5 -1
- package/dist/core/evaluationProviders.d.ts +6 -2
- package/dist/core/evaluationProviders.js +41 -125
- package/dist/core/factory.d.ts +5 -0
- package/dist/core/factory.js +62 -50
- package/dist/core/modelConfiguration.d.ts +246 -0
- package/dist/core/modelConfiguration.js +775 -0
- package/dist/core/types.d.ts +22 -3
- package/dist/core/types.js +5 -1
- package/dist/factories/providerRegistry.js +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/core/analytics.js +7 -27
- package/dist/lib/core/baseProvider.js +43 -4
- package/dist/lib/core/constants.d.ts +46 -0
- package/dist/lib/core/constants.js +47 -0
- package/dist/lib/core/dynamicModels.d.ts +16 -4
- package/dist/lib/core/dynamicModels.js +130 -26
- package/dist/lib/core/evaluation.js +5 -1
- package/dist/lib/core/evaluationProviders.d.ts +6 -2
- package/dist/lib/core/evaluationProviders.js +41 -125
- package/dist/lib/core/factory.d.ts +5 -0
- package/dist/lib/core/factory.js +63 -50
- package/dist/lib/core/modelConfiguration.d.ts +246 -0
- package/dist/lib/core/modelConfiguration.js +775 -0
- package/dist/lib/core/types.d.ts +22 -3
- package/dist/lib/core/types.js +5 -1
- package/dist/lib/factories/providerRegistry.js +3 -3
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.js +1 -1
- package/dist/lib/mcp/factory.d.ts +5 -5
- package/dist/lib/mcp/factory.js +2 -2
- package/dist/lib/mcp/servers/utilities/utilityServer.d.ts +1 -1
- package/dist/lib/mcp/servers/utilities/utilityServer.js +1 -1
- package/dist/lib/mcp/toolRegistry.js +2 -2
- package/dist/lib/neurolink.d.ts +168 -12
- package/dist/lib/neurolink.js +685 -123
- package/dist/lib/providers/anthropic.js +52 -2
- package/dist/lib/providers/googleAiStudio.js +4 -0
- package/dist/lib/providers/googleVertex.d.ts +75 -9
- package/dist/lib/providers/googleVertex.js +365 -46
- package/dist/lib/providers/huggingFace.d.ts +52 -11
- package/dist/lib/providers/huggingFace.js +180 -42
- package/dist/lib/providers/litellm.d.ts +9 -9
- package/dist/lib/providers/litellm.js +103 -16
- package/dist/lib/providers/ollama.d.ts +52 -17
- package/dist/lib/providers/ollama.js +276 -68
- package/dist/lib/sdk/toolRegistration.d.ts +42 -0
- package/dist/lib/sdk/toolRegistration.js +269 -27
- package/dist/lib/telemetry/telemetryService.d.ts +6 -0
- package/dist/lib/telemetry/telemetryService.js +38 -3
- package/dist/lib/types/contextTypes.d.ts +75 -11
- package/dist/lib/types/contextTypes.js +227 -1
- package/dist/lib/types/domainTypes.d.ts +62 -0
- package/dist/lib/types/domainTypes.js +5 -0
- package/dist/lib/types/generateTypes.d.ts +52 -0
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/lib/types/mcpTypes.d.ts +1 -1
- package/dist/lib/types/mcpTypes.js +1 -1
- package/dist/lib/types/streamTypes.d.ts +14 -0
- package/dist/lib/types/universalProviderOptions.d.ts +1 -1
- package/dist/lib/utils/errorHandling.d.ts +142 -0
- package/dist/lib/utils/errorHandling.js +316 -0
- package/dist/lib/utils/factoryProcessing.d.ts +74 -0
- package/dist/lib/utils/factoryProcessing.js +588 -0
- package/dist/lib/utils/optionsConversion.d.ts +54 -0
- package/dist/lib/utils/optionsConversion.js +126 -0
- package/dist/lib/utils/optionsUtils.d.ts +246 -0
- package/dist/lib/utils/optionsUtils.js +960 -0
- package/dist/lib/utils/providerHealth.d.ts +107 -0
- package/dist/lib/utils/providerHealth.js +507 -0
- package/dist/lib/utils/providerUtils.d.ts +17 -0
- package/dist/lib/utils/providerUtils.js +271 -16
- package/dist/lib/utils/timeout.js +1 -1
- package/dist/lib/utils/tokenLimits.d.ts +33 -0
- package/dist/lib/utils/tokenLimits.js +118 -0
- package/dist/mcp/factory.d.ts +5 -5
- package/dist/mcp/factory.js +2 -2
- package/dist/mcp/servers/utilities/utilityServer.d.ts +1 -1
- package/dist/mcp/servers/utilities/utilityServer.js +1 -1
- package/dist/mcp/toolRegistry.js +2 -2
- package/dist/neurolink.d.ts +168 -12
- package/dist/neurolink.js +685 -123
- package/dist/providers/anthropic.js +52 -2
- package/dist/providers/googleAiStudio.js +4 -0
- package/dist/providers/googleVertex.d.ts +75 -9
- package/dist/providers/googleVertex.js +365 -46
- package/dist/providers/huggingFace.d.ts +52 -11
- package/dist/providers/huggingFace.js +181 -43
- package/dist/providers/litellm.d.ts +9 -9
- package/dist/providers/litellm.js +103 -16
- package/dist/providers/ollama.d.ts +52 -17
- package/dist/providers/ollama.js +276 -68
- package/dist/sdk/toolRegistration.d.ts +42 -0
- package/dist/sdk/toolRegistration.js +269 -27
- package/dist/telemetry/telemetryService.d.ts +6 -0
- package/dist/telemetry/telemetryService.js +38 -3
- package/dist/types/contextTypes.d.ts +75 -11
- package/dist/types/contextTypes.js +227 -2
- package/dist/types/domainTypes.d.ts +62 -0
- package/dist/types/domainTypes.js +5 -0
- package/dist/types/generateTypes.d.ts +52 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/mcpTypes.d.ts +1 -1
- package/dist/types/mcpTypes.js +1 -1
- package/dist/types/streamTypes.d.ts +14 -0
- package/dist/types/universalProviderOptions.d.ts +1 -1
- package/dist/types/universalProviderOptions.js +0 -1
- package/dist/utils/errorHandling.d.ts +142 -0
- package/dist/utils/errorHandling.js +316 -0
- package/dist/utils/factoryProcessing.d.ts +74 -0
- package/dist/utils/factoryProcessing.js +588 -0
- package/dist/utils/optionsConversion.d.ts +54 -0
- package/dist/utils/optionsConversion.js +126 -0
- package/dist/utils/optionsUtils.d.ts +246 -0
- package/dist/utils/optionsUtils.js +960 -0
- package/dist/utils/providerHealth.d.ts +107 -0
- package/dist/utils/providerHealth.js +507 -0
- package/dist/utils/providerUtils.d.ts +17 -0
- package/dist/utils/providerUtils.js +271 -16
- package/dist/utils/timeout.js +1 -1
- package/dist/utils/tokenLimits.d.ts +33 -0
- package/dist/utils/tokenLimits.js +118 -0
- package/package.json +2 -2
|
@@ -11,6 +11,56 @@ import { logger } from "../utils/logger.js";
|
|
|
11
11
|
*/
|
|
12
12
|
const envValue = parseInt(process.env.NEUROLINK_TOOL_DESCRIPTION_MAX_LENGTH || "200", 10);
|
|
13
13
|
const DEFAULT_DESCRIPTION_MAX_LENGTH = Number.isInteger(envValue) && envValue > 0 ? envValue : 200;
|
|
14
|
+
/**
|
|
15
|
+
* Enhanced validation configuration
|
|
16
|
+
*/
|
|
17
|
+
const VALIDATION_CONFIG = {
|
|
18
|
+
// Tool name constraints
|
|
19
|
+
NAME_MIN_LENGTH: 2,
|
|
20
|
+
NAME_MAX_LENGTH: 50,
|
|
21
|
+
// Description constraints
|
|
22
|
+
DESCRIPTION_MIN_LENGTH: 10,
|
|
23
|
+
DESCRIPTION_MAX_LENGTH: DEFAULT_DESCRIPTION_MAX_LENGTH,
|
|
24
|
+
// Reserved tool names that cannot be used
|
|
25
|
+
RESERVED_NAMES: new Set([
|
|
26
|
+
"system",
|
|
27
|
+
"internal",
|
|
28
|
+
"core",
|
|
29
|
+
"ai",
|
|
30
|
+
"assistant",
|
|
31
|
+
"help",
|
|
32
|
+
"debug",
|
|
33
|
+
"test",
|
|
34
|
+
"mock",
|
|
35
|
+
"default",
|
|
36
|
+
"config",
|
|
37
|
+
"admin",
|
|
38
|
+
"root",
|
|
39
|
+
"neurolink",
|
|
40
|
+
]),
|
|
41
|
+
// Recommended tool name patterns
|
|
42
|
+
RECOMMENDED_PATTERNS: [
|
|
43
|
+
"get_data",
|
|
44
|
+
"fetch_info",
|
|
45
|
+
"calculate_value",
|
|
46
|
+
"send_message",
|
|
47
|
+
"create_item",
|
|
48
|
+
"update_record",
|
|
49
|
+
"delete_file",
|
|
50
|
+
"validate_input",
|
|
51
|
+
],
|
|
52
|
+
// Pre-compiled regex patterns for performance optimization
|
|
53
|
+
COMPILED_PATTERN_REGEXES: [
|
|
54
|
+
"get_data",
|
|
55
|
+
"fetch_info",
|
|
56
|
+
"calculate_value",
|
|
57
|
+
"send_message",
|
|
58
|
+
"create_item",
|
|
59
|
+
"update_record",
|
|
60
|
+
"delete_file",
|
|
61
|
+
"validate_input",
|
|
62
|
+
].map((pattern) => new RegExp(pattern.replace(/_/g, "[_-]"), "i")),
|
|
63
|
+
};
|
|
14
64
|
/**
|
|
15
65
|
* Converts a SimpleTool to Vercel AI SDK format
|
|
16
66
|
*/
|
|
@@ -89,50 +139,147 @@ export function createTool(config) {
|
|
|
89
139
|
return config;
|
|
90
140
|
}
|
|
91
141
|
/**
|
|
92
|
-
* Helper to create a tool with
|
|
142
|
+
* Helper to create a validated tool with suggested improvements
|
|
93
143
|
*/
|
|
94
|
-
export function
|
|
95
|
-
|
|
144
|
+
export function createValidatedTool(name, config, options = {}) {
|
|
145
|
+
const { strict = true, suggestions = true } = options;
|
|
146
|
+
try {
|
|
147
|
+
// Validate the tool
|
|
148
|
+
validateTool(name, config);
|
|
149
|
+
// Provide helpful suggestions if enabled
|
|
150
|
+
if (suggestions) {
|
|
151
|
+
provideToolSuggestions(name, config);
|
|
152
|
+
}
|
|
153
|
+
logger.debug(`Tool '${name}' created and validated successfully`);
|
|
154
|
+
return config;
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
if (strict) {
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
// Log warning but continue in non-strict mode
|
|
161
|
+
logger.warn(`Tool '${name}' validation failed in non-strict mode`, {
|
|
162
|
+
error: error instanceof Error ? error.message : String(error),
|
|
163
|
+
});
|
|
164
|
+
return config;
|
|
165
|
+
}
|
|
96
166
|
}
|
|
97
167
|
/**
|
|
98
|
-
*
|
|
168
|
+
* Provide helpful suggestions for tool improvement
|
|
99
169
|
*/
|
|
100
|
-
function
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
170
|
+
function provideToolSuggestions(name, tool) {
|
|
171
|
+
const suggestions = [];
|
|
172
|
+
// Check for common improvements
|
|
173
|
+
if (!tool.parameters) {
|
|
174
|
+
suggestions.push("Consider adding a parameters schema using Zod for better type safety and validation");
|
|
175
|
+
}
|
|
176
|
+
if (!tool.metadata?.category) {
|
|
177
|
+
suggestions.push("Adding a category in metadata helps organize tools: { metadata: { category: 'data' } }");
|
|
178
|
+
}
|
|
179
|
+
if (!tool.metadata?.version) {
|
|
180
|
+
suggestions.push("Adding a version helps track tool updates: { metadata: { version: '1.0.0' } }");
|
|
181
|
+
}
|
|
182
|
+
// Check description quality
|
|
183
|
+
const description = tool.description.toLowerCase();
|
|
184
|
+
if (!description.includes("return") && !description.includes("result")) {
|
|
185
|
+
suggestions.push("Consider describing what the tool returns for better AI understanding");
|
|
186
|
+
}
|
|
187
|
+
if (suggestions.length > 0) {
|
|
188
|
+
logger.debug(`Tool '${name}' suggestions for improvement:`, {
|
|
189
|
+
suggestions: suggestions.slice(0, 3), // Limit to avoid spam
|
|
190
|
+
});
|
|
109
191
|
}
|
|
110
192
|
}
|
|
111
193
|
/**
|
|
112
|
-
*
|
|
194
|
+
* Helper to create a tool with typed parameters
|
|
113
195
|
*/
|
|
114
|
-
export function
|
|
115
|
-
|
|
196
|
+
export function createTypedTool(config) {
|
|
197
|
+
return config;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Enhanced tool name validation
|
|
201
|
+
*/
|
|
202
|
+
function validateToolName(name) {
|
|
203
|
+
// Basic validation
|
|
116
204
|
if (!name || typeof name !== "string" || name.trim() === "") {
|
|
117
205
|
throw new Error(`Invalid tool name: must be a non-empty string. Received: ${name}`);
|
|
118
206
|
}
|
|
119
|
-
|
|
207
|
+
const trimmedName = name.trim();
|
|
208
|
+
// Length validation
|
|
209
|
+
if (trimmedName.length < VALIDATION_CONFIG.NAME_MIN_LENGTH) {
|
|
210
|
+
throw new Error(`Tool name too short: '${name}' (${trimmedName.length} chars). ` +
|
|
211
|
+
`Minimum length: ${VALIDATION_CONFIG.NAME_MIN_LENGTH} characters. ` +
|
|
212
|
+
`Example: 'get_data', 'send_email'`);
|
|
213
|
+
}
|
|
214
|
+
if (trimmedName.length > VALIDATION_CONFIG.NAME_MAX_LENGTH) {
|
|
215
|
+
throw new Error(`Tool name too long: '${name}' (${trimmedName.length} chars). ` +
|
|
216
|
+
`Maximum length: ${VALIDATION_CONFIG.NAME_MAX_LENGTH} characters. ` +
|
|
217
|
+
`Consider shortening: '${trimmedName.substring(0, 20)}...'`);
|
|
218
|
+
}
|
|
219
|
+
// Format validation (alphanumeric, hyphens, underscores only)
|
|
120
220
|
const validNamePattern = /^[a-zA-Z0-9_-]+$/;
|
|
121
|
-
if (!validNamePattern.test(
|
|
221
|
+
if (!validNamePattern.test(trimmedName)) {
|
|
122
222
|
throw new Error(`Invalid tool name format: '${name}'. Tool names must contain only alphanumeric characters, hyphens, and underscores. ` +
|
|
123
223
|
`Examples: 'calculate-tax', 'get_weather', 'sendEmail123'`);
|
|
124
224
|
}
|
|
125
|
-
//
|
|
126
|
-
if (
|
|
127
|
-
throw new Error(`Tool '${name}'
|
|
225
|
+
// Reserved name validation
|
|
226
|
+
if (VALIDATION_CONFIG.RESERVED_NAMES.has(trimmedName.toLowerCase())) {
|
|
227
|
+
throw new Error(`Tool name '${name}' is reserved and cannot be used. ` +
|
|
228
|
+
`Reserved names include: ${Array.from(VALIDATION_CONFIG.RESERVED_NAMES).slice(0, 5).join(", ")}... ` +
|
|
229
|
+
`Try variations like: '${trimmedName}_tool', 'custom_${trimmedName}', '${trimmedName}_helper'`);
|
|
230
|
+
}
|
|
231
|
+
// Naming convention suggestions using pre-compiled patterns for performance
|
|
232
|
+
const hasGoodPattern = VALIDATION_CONFIG.COMPILED_PATTERN_REGEXES.some((patternRegex) => {
|
|
233
|
+
return patternRegex.test(trimmedName);
|
|
234
|
+
});
|
|
235
|
+
if (!hasGoodPattern && trimmedName.length > 10) {
|
|
236
|
+
logger.debug(`Tool name '${name}' could follow recommended patterns for better clarity. ` +
|
|
237
|
+
`Consider patterns like: ${VALIDATION_CONFIG.RECOMMENDED_PATTERNS.slice(0, 4).join(", ")}`);
|
|
128
238
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Enhanced description validation
|
|
242
|
+
*/
|
|
243
|
+
function validateToolDescription(name, description) {
|
|
244
|
+
if (!description ||
|
|
245
|
+
typeof description !== "string" ||
|
|
246
|
+
description.trim() === "") {
|
|
133
247
|
throw new Error(`Tool '${name}' must have a non-empty description string. ` +
|
|
134
248
|
`Example: { description: "Calculates mathematical expressions", execute: async (params) => {...} }`);
|
|
135
249
|
}
|
|
250
|
+
const trimmedDescription = description.trim();
|
|
251
|
+
// Length validation
|
|
252
|
+
if (trimmedDescription.length < VALIDATION_CONFIG.DESCRIPTION_MIN_LENGTH) {
|
|
253
|
+
throw new Error(`Tool '${name}' description too short: ${trimmedDescription.length} characters. ` +
|
|
254
|
+
`Minimum length: ${VALIDATION_CONFIG.DESCRIPTION_MIN_LENGTH} characters. ` +
|
|
255
|
+
`The description should clearly explain what the tool does and when to use it. ` +
|
|
256
|
+
`Example: "Fetches current weather data for a specified location using coordinates or city name"`);
|
|
257
|
+
}
|
|
258
|
+
if (trimmedDescription.length > VALIDATION_CONFIG.DESCRIPTION_MAX_LENGTH) {
|
|
259
|
+
throw new Error(`Tool '${name}' description too long: ${trimmedDescription.length} characters. ` +
|
|
260
|
+
`Maximum length: ${VALIDATION_CONFIG.DESCRIPTION_MAX_LENGTH} characters. ` +
|
|
261
|
+
`Current description: "${trimmedDescription.substring(0, 50)}..." ` +
|
|
262
|
+
`Try to be more concise while keeping the essential information.`);
|
|
263
|
+
}
|
|
264
|
+
// Quality suggestions
|
|
265
|
+
const hasActionWord = /^(get|fetch|calculate|send|create|update|delete|validate|process|generate|parse|convert)/i.test(trimmedDescription);
|
|
266
|
+
if (!hasActionWord) {
|
|
267
|
+
logger.debug(`Tool '${name}' description could start with an action word (get, fetch, calculate, etc.) for better clarity: "${trimmedDescription.substring(0, 30)}..."`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Validate tool configuration with detailed error messages
|
|
272
|
+
*/
|
|
273
|
+
export function validateTool(name, tool) {
|
|
274
|
+
// Enhanced tool name validation
|
|
275
|
+
validateToolName(name);
|
|
276
|
+
// Validate tool object
|
|
277
|
+
if (!tool || typeof tool !== "object") {
|
|
278
|
+
throw new Error(`Tool '${name}' must be an object with description and execute properties. Received: ${typeof tool}. ` +
|
|
279
|
+
`Expected format: { description: "Tool description", execute: async (params) => { ... } }`);
|
|
280
|
+
}
|
|
281
|
+
// Enhanced description validation
|
|
282
|
+
validateToolDescription(name, tool.description);
|
|
136
283
|
// Validate execute function with signature guidance
|
|
137
284
|
if (typeof tool.execute !== "function") {
|
|
138
285
|
throw new Error(`Tool '${name}' must have an execute function. ` +
|
|
@@ -181,6 +328,101 @@ export function validateTool(name, tool) {
|
|
|
181
328
|
throw new Error(errorMessage);
|
|
182
329
|
}
|
|
183
330
|
}
|
|
184
|
-
// Validate
|
|
185
|
-
|
|
331
|
+
// Validate metadata if provided
|
|
332
|
+
if (tool.metadata) {
|
|
333
|
+
if (typeof tool.metadata !== "object" || Array.isArray(tool.metadata)) {
|
|
334
|
+
throw new Error(`Tool '${name}' metadata must be an object. Received: ${typeof tool.metadata}. ` +
|
|
335
|
+
`Example: { category: "data", version: "1.0.0", author: "team@company.com" }`);
|
|
336
|
+
}
|
|
337
|
+
// Validate metadata fields
|
|
338
|
+
if (tool.metadata.version && typeof tool.metadata.version !== "string") {
|
|
339
|
+
throw new Error(`Tool '${name}' metadata.version must be a string. Received: ${typeof tool.metadata.version}. ` +
|
|
340
|
+
`Example: "1.0.0", "2.1.3-beta"`);
|
|
341
|
+
}
|
|
342
|
+
if (tool.metadata.category && typeof tool.metadata.category !== "string") {
|
|
343
|
+
throw new Error(`Tool '${name}' metadata.category must be a string. Received: ${typeof tool.metadata.category}. ` +
|
|
344
|
+
`Example: "data", "communication", "utility"`);
|
|
345
|
+
}
|
|
346
|
+
if (tool.metadata.tags && !Array.isArray(tool.metadata.tags)) {
|
|
347
|
+
throw new Error(`Tool '${name}' metadata.tags must be an array of strings. Received: ${typeof tool.metadata.tags}. ` +
|
|
348
|
+
`Example: ["api", "external", "web"]`);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
// Success feedback for debugging
|
|
352
|
+
logger.debug(`Tool '${name}' validation passed`, {
|
|
353
|
+
nameLength: name.length,
|
|
354
|
+
descriptionLength: tool.description.length,
|
|
355
|
+
hasParameters: !!tool.parameters,
|
|
356
|
+
hasMetadata: !!tool.metadata,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Utility to validate multiple tools at once
|
|
361
|
+
*/
|
|
362
|
+
export function validateTools(tools) {
|
|
363
|
+
const valid = [];
|
|
364
|
+
const invalid = [];
|
|
365
|
+
for (const [name, tool] of Object.entries(tools)) {
|
|
366
|
+
try {
|
|
367
|
+
validateTool(name, tool);
|
|
368
|
+
valid.push(name);
|
|
369
|
+
}
|
|
370
|
+
catch (error) {
|
|
371
|
+
invalid.push({
|
|
372
|
+
name,
|
|
373
|
+
error: error instanceof Error ? error.message : String(error),
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
logger.debug(`Bulk validation completed`, {
|
|
378
|
+
validCount: valid.length,
|
|
379
|
+
invalidCount: invalid.length,
|
|
380
|
+
totalTools: Object.keys(tools).length,
|
|
381
|
+
});
|
|
382
|
+
return { valid, invalid };
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Get validation configuration for external inspection
|
|
386
|
+
*/
|
|
387
|
+
export function getValidationConfig() {
|
|
388
|
+
return { ...VALIDATION_CONFIG };
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Check if a tool name is available (not reserved)
|
|
392
|
+
*/
|
|
393
|
+
export function isToolNameAvailable(name) {
|
|
394
|
+
if (!name || typeof name !== "string") {
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
397
|
+
const trimmedName = name.trim().toLowerCase();
|
|
398
|
+
return (trimmedName.length >= VALIDATION_CONFIG.NAME_MIN_LENGTH &&
|
|
399
|
+
trimmedName.length <= VALIDATION_CONFIG.NAME_MAX_LENGTH &&
|
|
400
|
+
!VALIDATION_CONFIG.RESERVED_NAMES.has(trimmedName) &&
|
|
401
|
+
/^[a-zA-Z0-9_-]+$/.test(trimmedName));
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Suggest alternative tool names if the provided name is invalid
|
|
405
|
+
*/
|
|
406
|
+
export function suggestToolNames(baseName) {
|
|
407
|
+
if (!baseName || typeof baseName !== "string") {
|
|
408
|
+
return VALIDATION_CONFIG.RECOMMENDED_PATTERNS.slice(0, 3);
|
|
409
|
+
}
|
|
410
|
+
const cleanBase = baseName.toLowerCase().replace(/[^a-z0-9]/g, "_");
|
|
411
|
+
const suggestions = [];
|
|
412
|
+
// Add suffixes if the name is reserved
|
|
413
|
+
if (VALIDATION_CONFIG.RESERVED_NAMES.has(cleanBase)) {
|
|
414
|
+
suggestions.push(`${cleanBase}_tool`, `custom_${cleanBase}`, `${cleanBase}_helper`);
|
|
415
|
+
}
|
|
416
|
+
// Add pattern-based suggestions
|
|
417
|
+
const patterns = ["get_", "fetch_", "create_", "update_"];
|
|
418
|
+
patterns.forEach((pattern) => {
|
|
419
|
+
if (!cleanBase.startsWith(pattern.slice(0, -1))) {
|
|
420
|
+
suggestions.push(`${pattern}${cleanBase}`);
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
// Add recommended patterns if no good suggestions
|
|
424
|
+
if (suggestions.length === 0) {
|
|
425
|
+
suggestions.push(...VALIDATION_CONFIG.RECOMMENDED_PATTERNS.slice(0, 3));
|
|
426
|
+
}
|
|
427
|
+
return suggestions.slice(0, 5); // Limit to 5 suggestions
|
|
186
428
|
}
|
|
@@ -19,6 +19,11 @@ export declare class TelemetryService {
|
|
|
19
19
|
private mcpToolCalls?;
|
|
20
20
|
private connectionCounter?;
|
|
21
21
|
private responseTimeHistogram?;
|
|
22
|
+
private activeConnectionCount;
|
|
23
|
+
private errorCount;
|
|
24
|
+
private requestCount;
|
|
25
|
+
private totalResponseTime;
|
|
26
|
+
private responseTimeCount;
|
|
22
27
|
private constructor();
|
|
23
28
|
static getInstance(): TelemetryService;
|
|
24
29
|
private isTelemetryEnabled;
|
|
@@ -30,6 +35,7 @@ export declare class TelemetryService {
|
|
|
30
35
|
recordAIError(provider: string, error: Error): void;
|
|
31
36
|
recordMCPToolCall(toolName: string, duration: number, success: boolean): void;
|
|
32
37
|
recordConnection(type: "websocket" | "sse" | "http"): void;
|
|
38
|
+
recordConnectionClosed(type: "websocket" | "sse" | "http"): void;
|
|
33
39
|
recordResponseTime(endpoint: string, method: string, duration: number): void;
|
|
34
40
|
recordCustomMetric(name: string, value: number, labels?: Record<string, string>): void;
|
|
35
41
|
recordCustomHistogram(name: string, value: number, labels?: Record<string, string>): void;
|
|
@@ -21,6 +21,12 @@ export class TelemetryService {
|
|
|
21
21
|
mcpToolCalls;
|
|
22
22
|
connectionCounter;
|
|
23
23
|
responseTimeHistogram;
|
|
24
|
+
// Runtime metrics tracking
|
|
25
|
+
activeConnectionCount = 0;
|
|
26
|
+
errorCount = 0;
|
|
27
|
+
requestCount = 0;
|
|
28
|
+
totalResponseTime = 0;
|
|
29
|
+
responseTimeCount = 0;
|
|
24
30
|
constructor() {
|
|
25
31
|
// Check if telemetry is enabled
|
|
26
32
|
this.enabled = this.isTelemetryEnabled();
|
|
@@ -135,6 +141,10 @@ export class TelemetryService {
|
|
|
135
141
|
}
|
|
136
142
|
// Metrics Recording (NO-OP when disabled)
|
|
137
143
|
recordAIRequest(provider, model, tokens, duration) {
|
|
144
|
+
// Track runtime metrics
|
|
145
|
+
this.requestCount++;
|
|
146
|
+
this.totalResponseTime += duration;
|
|
147
|
+
this.responseTimeCount++;
|
|
138
148
|
if (!this.enabled || !this.aiRequestCounter) {
|
|
139
149
|
return;
|
|
140
150
|
}
|
|
@@ -144,6 +154,8 @@ export class TelemetryService {
|
|
|
144
154
|
this.aiTokensUsed?.add(tokens, labels);
|
|
145
155
|
}
|
|
146
156
|
recordAIError(provider, error) {
|
|
157
|
+
// Track runtime metrics
|
|
158
|
+
this.errorCount++;
|
|
147
159
|
if (!this.enabled || !this.aiProviderErrors) {
|
|
148
160
|
return;
|
|
149
161
|
}
|
|
@@ -164,12 +176,29 @@ export class TelemetryService {
|
|
|
164
176
|
});
|
|
165
177
|
}
|
|
166
178
|
recordConnection(type) {
|
|
179
|
+
// Track runtime metrics
|
|
180
|
+
this.activeConnectionCount++;
|
|
167
181
|
if (!this.enabled || !this.connectionCounter) {
|
|
168
182
|
return;
|
|
169
183
|
}
|
|
170
184
|
this.connectionCounter.add(1, { connection_type: type });
|
|
171
185
|
}
|
|
186
|
+
recordConnectionClosed(type) {
|
|
187
|
+
// Track runtime metrics
|
|
188
|
+
this.activeConnectionCount = Math.max(0, this.activeConnectionCount - 1);
|
|
189
|
+
if (!this.enabled || !this.connectionCounter) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
// Optionally record disconnection metrics if needed
|
|
193
|
+
this.connectionCounter.add(-1, {
|
|
194
|
+
connection_type: type,
|
|
195
|
+
event: "disconnect",
|
|
196
|
+
});
|
|
197
|
+
}
|
|
172
198
|
recordResponseTime(endpoint, method, duration) {
|
|
199
|
+
// Track runtime metrics
|
|
200
|
+
this.totalResponseTime += duration;
|
|
201
|
+
this.responseTimeCount++;
|
|
173
202
|
if (!this.enabled || !this.responseTimeHistogram) {
|
|
174
203
|
return;
|
|
175
204
|
}
|
|
@@ -201,13 +230,19 @@ export class TelemetryService {
|
|
|
201
230
|
// Health Checks
|
|
202
231
|
async getHealthMetrics() {
|
|
203
232
|
const memoryUsage = process.memoryUsage();
|
|
233
|
+
// Calculate error rate as percentage of errors vs total requests
|
|
234
|
+
const errorRate = this.requestCount > 0 ? (this.errorCount / this.requestCount) * 100 : 0;
|
|
235
|
+
// Calculate average response time
|
|
236
|
+
const averageResponseTime = this.responseTimeCount > 0
|
|
237
|
+
? this.totalResponseTime / this.responseTimeCount
|
|
238
|
+
: 0;
|
|
204
239
|
return {
|
|
205
240
|
timestamp: Date.now(),
|
|
206
241
|
memoryUsage,
|
|
207
242
|
uptime: process.uptime(),
|
|
208
|
-
activeConnections:
|
|
209
|
-
errorRate:
|
|
210
|
-
averageResponseTime:
|
|
243
|
+
activeConnections: this.activeConnectionCount,
|
|
244
|
+
errorRate: Math.round(errorRate * 100) / 100, // Round to 2 decimal places
|
|
245
|
+
averageResponseTime: Math.round(averageResponseTime * 100) / 100, // Round to 2 decimal places
|
|
211
246
|
};
|
|
212
247
|
}
|
|
213
248
|
// Telemetry Status
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Context Types for NeuroLink - Factory Pattern Implementation
|
|
3
3
|
* Provides type-safe context integration for AI generation
|
|
4
4
|
*/
|
|
5
|
-
import { JsonObject } from "./common.js";
|
|
5
|
+
import type { JsonObject } from "./common.js";
|
|
6
6
|
/**
|
|
7
7
|
* Base context interface for all AI operations
|
|
8
8
|
*/
|
|
@@ -26,7 +26,7 @@ export interface BaseContext {
|
|
|
26
26
|
/**
|
|
27
27
|
* Context integration mode types
|
|
28
28
|
*/
|
|
29
|
-
|
|
29
|
+
type ContextIntegrationMode = "prompt_prefix" | "prompt_suffix" | "system_prompt" | "metadata_only" | "structured_prompt" | "none";
|
|
30
30
|
/**
|
|
31
31
|
* Context configuration for AI generation
|
|
32
32
|
*/
|
|
@@ -41,7 +41,7 @@ export interface ContextConfig {
|
|
|
41
41
|
/**
|
|
42
42
|
* Context processing result
|
|
43
43
|
*/
|
|
44
|
-
|
|
44
|
+
interface ProcessedContext {
|
|
45
45
|
originalContext: BaseContext;
|
|
46
46
|
processedContext: string | null;
|
|
47
47
|
config: ContextConfig;
|
|
@@ -52,10 +52,58 @@ export interface ProcessedContext {
|
|
|
52
52
|
mode: ContextIntegrationMode;
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Configuration for framework fields exclusion
|
|
57
|
+
* Can be customized per application or environment
|
|
58
|
+
*/
|
|
59
|
+
export interface FrameworkFieldsConfig {
|
|
60
|
+
defaultFields: string[];
|
|
61
|
+
additionalFields?: string[];
|
|
62
|
+
overrideFields?: string[];
|
|
63
|
+
includeFields?: string[];
|
|
64
|
+
}
|
|
55
65
|
/**
|
|
56
66
|
* Factory for context processing
|
|
57
67
|
*/
|
|
58
68
|
export declare class ContextFactory {
|
|
69
|
+
/**
|
|
70
|
+
* Default framework fields configuration
|
|
71
|
+
*/
|
|
72
|
+
static readonly DEFAULT_FRAMEWORK_FIELDS: FrameworkFieldsConfig;
|
|
73
|
+
/**
|
|
74
|
+
* Current framework fields configuration
|
|
75
|
+
*/
|
|
76
|
+
private static frameworkFieldsConfig;
|
|
77
|
+
/**
|
|
78
|
+
* Flag to track if framework fields have been initialized
|
|
79
|
+
*/
|
|
80
|
+
private static isFrameworkFieldsInitialized;
|
|
81
|
+
/**
|
|
82
|
+
* Configure framework fields for exclusion from custom data
|
|
83
|
+
*/
|
|
84
|
+
static configureFrameworkFields(config: Partial<FrameworkFieldsConfig>): void;
|
|
85
|
+
/**
|
|
86
|
+
* Get current framework fields configuration
|
|
87
|
+
* Ensures lazy initialization if not already loaded
|
|
88
|
+
*/
|
|
89
|
+
static getFrameworkFieldsConfig(): FrameworkFieldsConfig;
|
|
90
|
+
/**
|
|
91
|
+
* Reset framework fields configuration to default
|
|
92
|
+
*/
|
|
93
|
+
static resetFrameworkFieldsConfig(): void;
|
|
94
|
+
/**
|
|
95
|
+
* Load framework fields configuration from environment variables
|
|
96
|
+
* Supports NEUROLINK_CONTEXT_EXCLUDE_FIELDS and NEUROLINK_CONTEXT_INCLUDE_FIELDS
|
|
97
|
+
*/
|
|
98
|
+
static loadFrameworkFieldsFromEnv(): void;
|
|
99
|
+
/**
|
|
100
|
+
* Add additional fields to exclude
|
|
101
|
+
*/
|
|
102
|
+
static addFrameworkFieldsToExclude(fields: string[]): void;
|
|
103
|
+
/**
|
|
104
|
+
* Add fields to include (override exclusion)
|
|
105
|
+
*/
|
|
106
|
+
static addFrameworkFieldsToInclude(fields: string[]): void;
|
|
59
107
|
/**
|
|
60
108
|
* Default context configuration
|
|
61
109
|
*/
|
|
@@ -98,13 +146,29 @@ export declare class ContextFactory {
|
|
|
98
146
|
static extractEvaluationContext(context: BaseContext): JsonObject;
|
|
99
147
|
}
|
|
100
148
|
/**
|
|
101
|
-
*
|
|
149
|
+
* Context conversion utilities for domain-specific data
|
|
150
|
+
* Replaces hardcoded business context with generic domain context
|
|
102
151
|
*/
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
152
|
+
import type { ExecutionContext } from "../mcp/contracts/mcpContract.js";
|
|
153
|
+
interface ContextConversionOptions {
|
|
154
|
+
preserveLegacyFields?: boolean;
|
|
155
|
+
validateDomainData?: boolean;
|
|
156
|
+
includeMetadata?: boolean;
|
|
157
|
+
}
|
|
158
|
+
export declare class ContextConverter {
|
|
159
|
+
/**
|
|
160
|
+
* Convert legacy business context to generic domain context
|
|
161
|
+
* Based on business context patterns
|
|
162
|
+
*/
|
|
163
|
+
static convertBusinessContext(legacyContext: Record<string, unknown>, domainType: string, options?: ContextConversionOptions): ExecutionContext;
|
|
164
|
+
/**
|
|
165
|
+
* Create execution context for any domain
|
|
166
|
+
*/
|
|
167
|
+
static createDomainContext(domainType: string, domainData: Record<string, unknown>, sessionInfo?: {
|
|
168
|
+
sessionId?: string;
|
|
169
|
+
userId?: string;
|
|
170
|
+
}): ExecutionContext;
|
|
171
|
+
private static inferProvider;
|
|
172
|
+
private static extractCustomData;
|
|
110
173
|
}
|
|
174
|
+
export {};
|