@juspay/neurolink 7.6.1 → 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 +9 -4
- package/README.md +78 -3
- 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
|
@@ -10,6 +10,56 @@ import { logger } from "../utils/logger.js";
|
|
|
10
10
|
*/
|
|
11
11
|
const envValue = parseInt(process.env.NEUROLINK_TOOL_DESCRIPTION_MAX_LENGTH || "200", 10);
|
|
12
12
|
const DEFAULT_DESCRIPTION_MAX_LENGTH = Number.isInteger(envValue) && envValue > 0 ? envValue : 200;
|
|
13
|
+
/**
|
|
14
|
+
* Enhanced validation configuration
|
|
15
|
+
*/
|
|
16
|
+
const VALIDATION_CONFIG = {
|
|
17
|
+
// Tool name constraints
|
|
18
|
+
NAME_MIN_LENGTH: 2,
|
|
19
|
+
NAME_MAX_LENGTH: 50,
|
|
20
|
+
// Description constraints
|
|
21
|
+
DESCRIPTION_MIN_LENGTH: 10,
|
|
22
|
+
DESCRIPTION_MAX_LENGTH: DEFAULT_DESCRIPTION_MAX_LENGTH,
|
|
23
|
+
// Reserved tool names that cannot be used
|
|
24
|
+
RESERVED_NAMES: new Set([
|
|
25
|
+
"system",
|
|
26
|
+
"internal",
|
|
27
|
+
"core",
|
|
28
|
+
"ai",
|
|
29
|
+
"assistant",
|
|
30
|
+
"help",
|
|
31
|
+
"debug",
|
|
32
|
+
"test",
|
|
33
|
+
"mock",
|
|
34
|
+
"default",
|
|
35
|
+
"config",
|
|
36
|
+
"admin",
|
|
37
|
+
"root",
|
|
38
|
+
"neurolink",
|
|
39
|
+
]),
|
|
40
|
+
// Recommended tool name patterns
|
|
41
|
+
RECOMMENDED_PATTERNS: [
|
|
42
|
+
"get_data",
|
|
43
|
+
"fetch_info",
|
|
44
|
+
"calculate_value",
|
|
45
|
+
"send_message",
|
|
46
|
+
"create_item",
|
|
47
|
+
"update_record",
|
|
48
|
+
"delete_file",
|
|
49
|
+
"validate_input",
|
|
50
|
+
],
|
|
51
|
+
// Pre-compiled regex patterns for performance optimization
|
|
52
|
+
COMPILED_PATTERN_REGEXES: [
|
|
53
|
+
"get_data",
|
|
54
|
+
"fetch_info",
|
|
55
|
+
"calculate_value",
|
|
56
|
+
"send_message",
|
|
57
|
+
"create_item",
|
|
58
|
+
"update_record",
|
|
59
|
+
"delete_file",
|
|
60
|
+
"validate_input",
|
|
61
|
+
].map((pattern) => new RegExp(pattern.replace(/_/g, "[_-]"), "i")),
|
|
62
|
+
};
|
|
13
63
|
/**
|
|
14
64
|
* Converts a SimpleTool to Vercel AI SDK format
|
|
15
65
|
*/
|
|
@@ -88,50 +138,147 @@ export function createTool(config) {
|
|
|
88
138
|
return config;
|
|
89
139
|
}
|
|
90
140
|
/**
|
|
91
|
-
* Helper to create a tool with
|
|
141
|
+
* Helper to create a validated tool with suggested improvements
|
|
92
142
|
*/
|
|
93
|
-
export function
|
|
94
|
-
|
|
143
|
+
export function createValidatedTool(name, config, options = {}) {
|
|
144
|
+
const { strict = true, suggestions = true } = options;
|
|
145
|
+
try {
|
|
146
|
+
// Validate the tool
|
|
147
|
+
validateTool(name, config);
|
|
148
|
+
// Provide helpful suggestions if enabled
|
|
149
|
+
if (suggestions) {
|
|
150
|
+
provideToolSuggestions(name, config);
|
|
151
|
+
}
|
|
152
|
+
logger.debug(`Tool '${name}' created and validated successfully`);
|
|
153
|
+
return config;
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
if (strict) {
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
// Log warning but continue in non-strict mode
|
|
160
|
+
logger.warn(`Tool '${name}' validation failed in non-strict mode`, {
|
|
161
|
+
error: error instanceof Error ? error.message : String(error),
|
|
162
|
+
});
|
|
163
|
+
return config;
|
|
164
|
+
}
|
|
95
165
|
}
|
|
96
166
|
/**
|
|
97
|
-
*
|
|
167
|
+
* Provide helpful suggestions for tool improvement
|
|
98
168
|
*/
|
|
99
|
-
function
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
169
|
+
function provideToolSuggestions(name, tool) {
|
|
170
|
+
const suggestions = [];
|
|
171
|
+
// Check for common improvements
|
|
172
|
+
if (!tool.parameters) {
|
|
173
|
+
suggestions.push("Consider adding a parameters schema using Zod for better type safety and validation");
|
|
174
|
+
}
|
|
175
|
+
if (!tool.metadata?.category) {
|
|
176
|
+
suggestions.push("Adding a category in metadata helps organize tools: { metadata: { category: 'data' } }");
|
|
177
|
+
}
|
|
178
|
+
if (!tool.metadata?.version) {
|
|
179
|
+
suggestions.push("Adding a version helps track tool updates: { metadata: { version: '1.0.0' } }");
|
|
180
|
+
}
|
|
181
|
+
// Check description quality
|
|
182
|
+
const description = tool.description.toLowerCase();
|
|
183
|
+
if (!description.includes("return") && !description.includes("result")) {
|
|
184
|
+
suggestions.push("Consider describing what the tool returns for better AI understanding");
|
|
185
|
+
}
|
|
186
|
+
if (suggestions.length > 0) {
|
|
187
|
+
logger.debug(`Tool '${name}' suggestions for improvement:`, {
|
|
188
|
+
suggestions: suggestions.slice(0, 3), // Limit to avoid spam
|
|
189
|
+
});
|
|
108
190
|
}
|
|
109
191
|
}
|
|
110
192
|
/**
|
|
111
|
-
*
|
|
193
|
+
* Helper to create a tool with typed parameters
|
|
112
194
|
*/
|
|
113
|
-
export function
|
|
114
|
-
|
|
195
|
+
export function createTypedTool(config) {
|
|
196
|
+
return config;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Enhanced tool name validation
|
|
200
|
+
*/
|
|
201
|
+
function validateToolName(name) {
|
|
202
|
+
// Basic validation
|
|
115
203
|
if (!name || typeof name !== "string" || name.trim() === "") {
|
|
116
204
|
throw new Error(`Invalid tool name: must be a non-empty string. Received: ${name}`);
|
|
117
205
|
}
|
|
118
|
-
|
|
206
|
+
const trimmedName = name.trim();
|
|
207
|
+
// Length validation
|
|
208
|
+
if (trimmedName.length < VALIDATION_CONFIG.NAME_MIN_LENGTH) {
|
|
209
|
+
throw new Error(`Tool name too short: '${name}' (${trimmedName.length} chars). ` +
|
|
210
|
+
`Minimum length: ${VALIDATION_CONFIG.NAME_MIN_LENGTH} characters. ` +
|
|
211
|
+
`Example: 'get_data', 'send_email'`);
|
|
212
|
+
}
|
|
213
|
+
if (trimmedName.length > VALIDATION_CONFIG.NAME_MAX_LENGTH) {
|
|
214
|
+
throw new Error(`Tool name too long: '${name}' (${trimmedName.length} chars). ` +
|
|
215
|
+
`Maximum length: ${VALIDATION_CONFIG.NAME_MAX_LENGTH} characters. ` +
|
|
216
|
+
`Consider shortening: '${trimmedName.substring(0, 20)}...'`);
|
|
217
|
+
}
|
|
218
|
+
// Format validation (alphanumeric, hyphens, underscores only)
|
|
119
219
|
const validNamePattern = /^[a-zA-Z0-9_-]+$/;
|
|
120
|
-
if (!validNamePattern.test(
|
|
220
|
+
if (!validNamePattern.test(trimmedName)) {
|
|
121
221
|
throw new Error(`Invalid tool name format: '${name}'. Tool names must contain only alphanumeric characters, hyphens, and underscores. ` +
|
|
122
222
|
`Examples: 'calculate-tax', 'get_weather', 'sendEmail123'`);
|
|
123
223
|
}
|
|
124
|
-
//
|
|
125
|
-
if (
|
|
126
|
-
throw new Error(`Tool '${name}'
|
|
224
|
+
// Reserved name validation
|
|
225
|
+
if (VALIDATION_CONFIG.RESERVED_NAMES.has(trimmedName.toLowerCase())) {
|
|
226
|
+
throw new Error(`Tool name '${name}' is reserved and cannot be used. ` +
|
|
227
|
+
`Reserved names include: ${Array.from(VALIDATION_CONFIG.RESERVED_NAMES).slice(0, 5).join(", ")}... ` +
|
|
228
|
+
`Try variations like: '${trimmedName}_tool', 'custom_${trimmedName}', '${trimmedName}_helper'`);
|
|
229
|
+
}
|
|
230
|
+
// Naming convention suggestions using pre-compiled patterns for performance
|
|
231
|
+
const hasGoodPattern = VALIDATION_CONFIG.COMPILED_PATTERN_REGEXES.some((patternRegex) => {
|
|
232
|
+
return patternRegex.test(trimmedName);
|
|
233
|
+
});
|
|
234
|
+
if (!hasGoodPattern && trimmedName.length > 10) {
|
|
235
|
+
logger.debug(`Tool name '${name}' could follow recommended patterns for better clarity. ` +
|
|
236
|
+
`Consider patterns like: ${VALIDATION_CONFIG.RECOMMENDED_PATTERNS.slice(0, 4).join(", ")}`);
|
|
127
237
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Enhanced description validation
|
|
241
|
+
*/
|
|
242
|
+
function validateToolDescription(name, description) {
|
|
243
|
+
if (!description ||
|
|
244
|
+
typeof description !== "string" ||
|
|
245
|
+
description.trim() === "") {
|
|
132
246
|
throw new Error(`Tool '${name}' must have a non-empty description string. ` +
|
|
133
247
|
`Example: { description: "Calculates mathematical expressions", execute: async (params) => {...} }`);
|
|
134
248
|
}
|
|
249
|
+
const trimmedDescription = description.trim();
|
|
250
|
+
// Length validation
|
|
251
|
+
if (trimmedDescription.length < VALIDATION_CONFIG.DESCRIPTION_MIN_LENGTH) {
|
|
252
|
+
throw new Error(`Tool '${name}' description too short: ${trimmedDescription.length} characters. ` +
|
|
253
|
+
`Minimum length: ${VALIDATION_CONFIG.DESCRIPTION_MIN_LENGTH} characters. ` +
|
|
254
|
+
`The description should clearly explain what the tool does and when to use it. ` +
|
|
255
|
+
`Example: "Fetches current weather data for a specified location using coordinates or city name"`);
|
|
256
|
+
}
|
|
257
|
+
if (trimmedDescription.length > VALIDATION_CONFIG.DESCRIPTION_MAX_LENGTH) {
|
|
258
|
+
throw new Error(`Tool '${name}' description too long: ${trimmedDescription.length} characters. ` +
|
|
259
|
+
`Maximum length: ${VALIDATION_CONFIG.DESCRIPTION_MAX_LENGTH} characters. ` +
|
|
260
|
+
`Current description: "${trimmedDescription.substring(0, 50)}..." ` +
|
|
261
|
+
`Try to be more concise while keeping the essential information.`);
|
|
262
|
+
}
|
|
263
|
+
// Quality suggestions
|
|
264
|
+
const hasActionWord = /^(get|fetch|calculate|send|create|update|delete|validate|process|generate|parse|convert)/i.test(trimmedDescription);
|
|
265
|
+
if (!hasActionWord) {
|
|
266
|
+
logger.debug(`Tool '${name}' description could start with an action word (get, fetch, calculate, etc.) for better clarity: "${trimmedDescription.substring(0, 30)}..."`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Validate tool configuration with detailed error messages
|
|
271
|
+
*/
|
|
272
|
+
export function validateTool(name, tool) {
|
|
273
|
+
// Enhanced tool name validation
|
|
274
|
+
validateToolName(name);
|
|
275
|
+
// Validate tool object
|
|
276
|
+
if (!tool || typeof tool !== "object") {
|
|
277
|
+
throw new Error(`Tool '${name}' must be an object with description and execute properties. Received: ${typeof tool}. ` +
|
|
278
|
+
`Expected format: { description: "Tool description", execute: async (params) => { ... } }`);
|
|
279
|
+
}
|
|
280
|
+
// Enhanced description validation
|
|
281
|
+
validateToolDescription(name, tool.description);
|
|
135
282
|
// Validate execute function with signature guidance
|
|
136
283
|
if (typeof tool.execute !== "function") {
|
|
137
284
|
throw new Error(`Tool '${name}' must have an execute function. ` +
|
|
@@ -180,6 +327,101 @@ export function validateTool(name, tool) {
|
|
|
180
327
|
throw new Error(errorMessage);
|
|
181
328
|
}
|
|
182
329
|
}
|
|
183
|
-
// Validate
|
|
184
|
-
|
|
330
|
+
// Validate metadata if provided
|
|
331
|
+
if (tool.metadata) {
|
|
332
|
+
if (typeof tool.metadata !== "object" || Array.isArray(tool.metadata)) {
|
|
333
|
+
throw new Error(`Tool '${name}' metadata must be an object. Received: ${typeof tool.metadata}. ` +
|
|
334
|
+
`Example: { category: "data", version: "1.0.0", author: "team@company.com" }`);
|
|
335
|
+
}
|
|
336
|
+
// Validate metadata fields
|
|
337
|
+
if (tool.metadata.version && typeof tool.metadata.version !== "string") {
|
|
338
|
+
throw new Error(`Tool '${name}' metadata.version must be a string. Received: ${typeof tool.metadata.version}. ` +
|
|
339
|
+
`Example: "1.0.0", "2.1.3-beta"`);
|
|
340
|
+
}
|
|
341
|
+
if (tool.metadata.category && typeof tool.metadata.category !== "string") {
|
|
342
|
+
throw new Error(`Tool '${name}' metadata.category must be a string. Received: ${typeof tool.metadata.category}. ` +
|
|
343
|
+
`Example: "data", "communication", "utility"`);
|
|
344
|
+
}
|
|
345
|
+
if (tool.metadata.tags && !Array.isArray(tool.metadata.tags)) {
|
|
346
|
+
throw new Error(`Tool '${name}' metadata.tags must be an array of strings. Received: ${typeof tool.metadata.tags}. ` +
|
|
347
|
+
`Example: ["api", "external", "web"]`);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// Success feedback for debugging
|
|
351
|
+
logger.debug(`Tool '${name}' validation passed`, {
|
|
352
|
+
nameLength: name.length,
|
|
353
|
+
descriptionLength: tool.description.length,
|
|
354
|
+
hasParameters: !!tool.parameters,
|
|
355
|
+
hasMetadata: !!tool.metadata,
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Utility to validate multiple tools at once
|
|
360
|
+
*/
|
|
361
|
+
export function validateTools(tools) {
|
|
362
|
+
const valid = [];
|
|
363
|
+
const invalid = [];
|
|
364
|
+
for (const [name, tool] of Object.entries(tools)) {
|
|
365
|
+
try {
|
|
366
|
+
validateTool(name, tool);
|
|
367
|
+
valid.push(name);
|
|
368
|
+
}
|
|
369
|
+
catch (error) {
|
|
370
|
+
invalid.push({
|
|
371
|
+
name,
|
|
372
|
+
error: error instanceof Error ? error.message : String(error),
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
logger.debug(`Bulk validation completed`, {
|
|
377
|
+
validCount: valid.length,
|
|
378
|
+
invalidCount: invalid.length,
|
|
379
|
+
totalTools: Object.keys(tools).length,
|
|
380
|
+
});
|
|
381
|
+
return { valid, invalid };
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Get validation configuration for external inspection
|
|
385
|
+
*/
|
|
386
|
+
export function getValidationConfig() {
|
|
387
|
+
return { ...VALIDATION_CONFIG };
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Check if a tool name is available (not reserved)
|
|
391
|
+
*/
|
|
392
|
+
export function isToolNameAvailable(name) {
|
|
393
|
+
if (!name || typeof name !== "string") {
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
const trimmedName = name.trim().toLowerCase();
|
|
397
|
+
return (trimmedName.length >= VALIDATION_CONFIG.NAME_MIN_LENGTH &&
|
|
398
|
+
trimmedName.length <= VALIDATION_CONFIG.NAME_MAX_LENGTH &&
|
|
399
|
+
!VALIDATION_CONFIG.RESERVED_NAMES.has(trimmedName) &&
|
|
400
|
+
/^[a-zA-Z0-9_-]+$/.test(trimmedName));
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Suggest alternative tool names if the provided name is invalid
|
|
404
|
+
*/
|
|
405
|
+
export function suggestToolNames(baseName) {
|
|
406
|
+
if (!baseName || typeof baseName !== "string") {
|
|
407
|
+
return VALIDATION_CONFIG.RECOMMENDED_PATTERNS.slice(0, 3);
|
|
408
|
+
}
|
|
409
|
+
const cleanBase = baseName.toLowerCase().replace(/[^a-z0-9]/g, "_");
|
|
410
|
+
const suggestions = [];
|
|
411
|
+
// Add suffixes if the name is reserved
|
|
412
|
+
if (VALIDATION_CONFIG.RESERVED_NAMES.has(cleanBase)) {
|
|
413
|
+
suggestions.push(`${cleanBase}_tool`, `custom_${cleanBase}`, `${cleanBase}_helper`);
|
|
414
|
+
}
|
|
415
|
+
// Add pattern-based suggestions
|
|
416
|
+
const patterns = ["get_", "fetch_", "create_", "update_"];
|
|
417
|
+
patterns.forEach((pattern) => {
|
|
418
|
+
if (!cleanBase.startsWith(pattern.slice(0, -1))) {
|
|
419
|
+
suggestions.push(`${pattern}${cleanBase}`);
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
// Add recommended patterns if no good suggestions
|
|
423
|
+
if (suggestions.length === 0) {
|
|
424
|
+
suggestions.push(...VALIDATION_CONFIG.RECOMMENDED_PATTERNS.slice(0, 3));
|
|
425
|
+
}
|
|
426
|
+
return suggestions.slice(0, 5); // Limit to 5 suggestions
|
|
185
427
|
}
|
|
@@ -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;
|
|
@@ -19,6 +19,12 @@ export class TelemetryService {
|
|
|
19
19
|
mcpToolCalls;
|
|
20
20
|
connectionCounter;
|
|
21
21
|
responseTimeHistogram;
|
|
22
|
+
// Runtime metrics tracking
|
|
23
|
+
activeConnectionCount = 0;
|
|
24
|
+
errorCount = 0;
|
|
25
|
+
requestCount = 0;
|
|
26
|
+
totalResponseTime = 0;
|
|
27
|
+
responseTimeCount = 0;
|
|
22
28
|
constructor() {
|
|
23
29
|
// Check if telemetry is enabled
|
|
24
30
|
this.enabled = this.isTelemetryEnabled();
|
|
@@ -133,6 +139,10 @@ export class TelemetryService {
|
|
|
133
139
|
}
|
|
134
140
|
// Metrics Recording (NO-OP when disabled)
|
|
135
141
|
recordAIRequest(provider, model, tokens, duration) {
|
|
142
|
+
// Track runtime metrics
|
|
143
|
+
this.requestCount++;
|
|
144
|
+
this.totalResponseTime += duration;
|
|
145
|
+
this.responseTimeCount++;
|
|
136
146
|
if (!this.enabled || !this.aiRequestCounter) {
|
|
137
147
|
return;
|
|
138
148
|
}
|
|
@@ -142,6 +152,8 @@ export class TelemetryService {
|
|
|
142
152
|
this.aiTokensUsed?.add(tokens, labels);
|
|
143
153
|
}
|
|
144
154
|
recordAIError(provider, error) {
|
|
155
|
+
// Track runtime metrics
|
|
156
|
+
this.errorCount++;
|
|
145
157
|
if (!this.enabled || !this.aiProviderErrors) {
|
|
146
158
|
return;
|
|
147
159
|
}
|
|
@@ -162,12 +174,29 @@ export class TelemetryService {
|
|
|
162
174
|
});
|
|
163
175
|
}
|
|
164
176
|
recordConnection(type) {
|
|
177
|
+
// Track runtime metrics
|
|
178
|
+
this.activeConnectionCount++;
|
|
165
179
|
if (!this.enabled || !this.connectionCounter) {
|
|
166
180
|
return;
|
|
167
181
|
}
|
|
168
182
|
this.connectionCounter.add(1, { connection_type: type });
|
|
169
183
|
}
|
|
184
|
+
recordConnectionClosed(type) {
|
|
185
|
+
// Track runtime metrics
|
|
186
|
+
this.activeConnectionCount = Math.max(0, this.activeConnectionCount - 1);
|
|
187
|
+
if (!this.enabled || !this.connectionCounter) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
// Optionally record disconnection metrics if needed
|
|
191
|
+
this.connectionCounter.add(-1, {
|
|
192
|
+
connection_type: type,
|
|
193
|
+
event: "disconnect",
|
|
194
|
+
});
|
|
195
|
+
}
|
|
170
196
|
recordResponseTime(endpoint, method, duration) {
|
|
197
|
+
// Track runtime metrics
|
|
198
|
+
this.totalResponseTime += duration;
|
|
199
|
+
this.responseTimeCount++;
|
|
171
200
|
if (!this.enabled || !this.responseTimeHistogram) {
|
|
172
201
|
return;
|
|
173
202
|
}
|
|
@@ -199,13 +228,19 @@ export class TelemetryService {
|
|
|
199
228
|
// Health Checks
|
|
200
229
|
async getHealthMetrics() {
|
|
201
230
|
const memoryUsage = process.memoryUsage();
|
|
231
|
+
// Calculate error rate as percentage of errors vs total requests
|
|
232
|
+
const errorRate = this.requestCount > 0 ? (this.errorCount / this.requestCount) * 100 : 0;
|
|
233
|
+
// Calculate average response time
|
|
234
|
+
const averageResponseTime = this.responseTimeCount > 0
|
|
235
|
+
? this.totalResponseTime / this.responseTimeCount
|
|
236
|
+
: 0;
|
|
202
237
|
return {
|
|
203
238
|
timestamp: Date.now(),
|
|
204
239
|
memoryUsage,
|
|
205
240
|
uptime: process.uptime(),
|
|
206
|
-
activeConnections:
|
|
207
|
-
errorRate:
|
|
208
|
-
averageResponseTime:
|
|
241
|
+
activeConnections: this.activeConnectionCount,
|
|
242
|
+
errorRate: Math.round(errorRate * 100) / 100, // Round to 2 decimal places
|
|
243
|
+
averageResponseTime: Math.round(averageResponseTime * 100) / 100, // Round to 2 decimal places
|
|
209
244
|
};
|
|
210
245
|
}
|
|
211
246
|
// 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 {};
|