@juspay/neurolink 7.36.0 → 7.37.1
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 +18 -18
- package/dist/cli/factories/commandFactory.d.ts +24 -0
- package/dist/cli/factories/commandFactory.js +297 -245
- package/dist/config/taskClassificationConfig.d.ts +51 -0
- package/dist/config/taskClassificationConfig.js +148 -0
- package/dist/core/baseProvider.d.ts +40 -3
- package/dist/core/baseProvider.js +689 -352
- package/dist/core/constants.d.ts +2 -30
- package/dist/core/constants.js +15 -43
- package/dist/factories/providerFactory.js +23 -6
- package/dist/index.d.ts +3 -2
- package/dist/index.js +4 -3
- package/dist/lib/config/taskClassificationConfig.d.ts +51 -0
- package/dist/lib/config/taskClassificationConfig.js +148 -0
- package/dist/lib/core/baseProvider.d.ts +40 -3
- package/dist/lib/core/baseProvider.js +689 -352
- package/dist/lib/core/constants.d.ts +2 -30
- package/dist/lib/core/constants.js +15 -43
- package/dist/lib/factories/providerFactory.js +23 -6
- package/dist/lib/index.d.ts +3 -2
- package/dist/lib/index.js +4 -3
- package/dist/lib/mcp/externalServerManager.js +2 -2
- package/dist/lib/mcp/registry.js +2 -2
- package/dist/lib/mcp/servers/agent/directToolsServer.js +19 -10
- package/dist/lib/mcp/toolRegistry.js +4 -8
- package/dist/lib/neurolink.d.ts +82 -27
- package/dist/lib/neurolink.js +672 -713
- package/dist/lib/providers/amazonBedrock.js +2 -2
- package/dist/lib/providers/googleVertex.d.ts +3 -23
- package/dist/lib/providers/googleVertex.js +14 -342
- package/dist/lib/providers/openAI.d.ts +23 -0
- package/dist/lib/providers/openAI.js +313 -6
- package/dist/lib/providers/sagemaker/language-model.d.ts +2 -2
- package/dist/lib/sdk/toolRegistration.js +18 -1
- package/dist/lib/types/common.d.ts +98 -0
- package/dist/lib/types/index.d.ts +2 -0
- package/dist/lib/types/index.js +2 -0
- package/dist/lib/types/streamTypes.d.ts +13 -6
- package/dist/lib/types/taskClassificationTypes.d.ts +52 -0
- package/dist/lib/types/taskClassificationTypes.js +5 -0
- package/dist/lib/types/typeAliases.d.ts +3 -2
- package/dist/lib/utils/modelRouter.d.ts +107 -0
- package/dist/lib/utils/modelRouter.js +292 -0
- package/dist/lib/utils/parameterValidation.js +6 -25
- package/dist/lib/utils/promptRedaction.d.ts +29 -0
- package/dist/lib/utils/promptRedaction.js +62 -0
- package/dist/lib/utils/schemaConversion.d.ts +14 -0
- package/dist/lib/utils/schemaConversion.js +140 -0
- package/dist/lib/utils/taskClassificationUtils.d.ts +55 -0
- package/dist/lib/utils/taskClassificationUtils.js +149 -0
- package/dist/lib/utils/taskClassifier.d.ts +23 -0
- package/dist/lib/utils/taskClassifier.js +94 -0
- package/dist/lib/utils/transformationUtils.js +143 -5
- package/dist/mcp/externalServerManager.js +2 -2
- package/dist/mcp/registry.js +2 -2
- package/dist/mcp/servers/agent/directToolsServer.js +19 -10
- package/dist/mcp/toolRegistry.js +4 -8
- package/dist/neurolink.d.ts +82 -27
- package/dist/neurolink.js +672 -713
- package/dist/providers/amazonBedrock.js +2 -2
- package/dist/providers/googleVertex.d.ts +3 -23
- package/dist/providers/googleVertex.js +14 -342
- package/dist/providers/openAI.d.ts +23 -0
- package/dist/providers/openAI.js +313 -6
- package/dist/providers/sagemaker/language-model.d.ts +2 -2
- package/dist/sdk/toolRegistration.js +18 -1
- package/dist/types/common.d.ts +98 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +2 -0
- package/dist/types/streamTypes.d.ts +13 -6
- package/dist/types/taskClassificationTypes.d.ts +52 -0
- package/dist/types/taskClassificationTypes.js +5 -0
- package/dist/types/typeAliases.d.ts +3 -2
- package/dist/utils/modelRouter.d.ts +107 -0
- package/dist/utils/modelRouter.js +292 -0
- package/dist/utils/parameterValidation.js +6 -25
- package/dist/utils/promptRedaction.d.ts +29 -0
- package/dist/utils/promptRedaction.js +62 -0
- package/dist/utils/schemaConversion.d.ts +14 -0
- package/dist/utils/schemaConversion.js +140 -0
- package/dist/utils/taskClassificationUtils.d.ts +55 -0
- package/dist/utils/taskClassificationUtils.js +149 -0
- package/dist/utils/taskClassifier.d.ts +23 -0
- package/dist/utils/taskClassifier.js +94 -0
- package/dist/utils/transformationUtils.js +143 -5
- package/package.json +3 -2
@@ -0,0 +1,107 @@
|
|
1
|
+
/**
|
2
|
+
* Model Router for NeuroLink Orchestration
|
3
|
+
* Routes tasks to optimal models based on classification and requirements
|
4
|
+
*/
|
5
|
+
import type { TaskType } from "../types/taskClassificationTypes.js";
|
6
|
+
export interface ModelRoute {
|
7
|
+
provider: string;
|
8
|
+
model: string;
|
9
|
+
reasoning: string;
|
10
|
+
confidence: number;
|
11
|
+
}
|
12
|
+
export interface ModelRoutingOptions {
|
13
|
+
/** Override the task classification */
|
14
|
+
forceTaskType?: TaskType;
|
15
|
+
/** Require specific performance characteristics */
|
16
|
+
requireFast?: boolean;
|
17
|
+
/** Require specific capability (reasoning, creativity, etc.) */
|
18
|
+
requireCapability?: string;
|
19
|
+
/** Fallback strategy if primary choice fails */
|
20
|
+
fallbackStrategy?: "fast" | "reasoning" | "auto";
|
21
|
+
}
|
22
|
+
/**
|
23
|
+
* Model configurations for different task types and providers
|
24
|
+
*/
|
25
|
+
declare const MODEL_CONFIGS: {
|
26
|
+
readonly fast: {
|
27
|
+
readonly primary: {
|
28
|
+
readonly provider: "vertex";
|
29
|
+
readonly model: "gemini-2.5-flash";
|
30
|
+
readonly capabilities: readonly ["speed", "general", "code", "basic-reasoning"];
|
31
|
+
readonly avgResponseTime: 800;
|
32
|
+
readonly costPerToken: 0.0001;
|
33
|
+
readonly reasoning: "Optimized for speed and efficiency via Vertex AI";
|
34
|
+
};
|
35
|
+
readonly fallback: {
|
36
|
+
readonly provider: "vertex";
|
37
|
+
readonly model: "gemini-2.5-pro";
|
38
|
+
readonly capabilities: readonly ["speed", "general", "basic-reasoning"];
|
39
|
+
readonly avgResponseTime: 1200;
|
40
|
+
readonly costPerToken: 0.0002;
|
41
|
+
readonly reasoning: "Vertex AI Gemini Pro fallback";
|
42
|
+
};
|
43
|
+
};
|
44
|
+
readonly reasoning: {
|
45
|
+
readonly primary: {
|
46
|
+
readonly provider: "vertex";
|
47
|
+
readonly model: "claude-sonnet-4@20250514";
|
48
|
+
readonly capabilities: readonly ["reasoning", "analysis", "complex-logic", "code", "creativity"];
|
49
|
+
readonly avgResponseTime: 3000;
|
50
|
+
readonly costPerToken: 0.003;
|
51
|
+
readonly reasoning: "Advanced reasoning and analysis via Claude Sonnet 4 on Vertex AI";
|
52
|
+
};
|
53
|
+
readonly fallback: {
|
54
|
+
readonly provider: "vertex";
|
55
|
+
readonly model: "claude-opus-4@20250514";
|
56
|
+
readonly capabilities: readonly ["reasoning", "analysis", "complex-logic", "code", "creativity", "agentic"];
|
57
|
+
readonly avgResponseTime: 4000;
|
58
|
+
readonly costPerToken: 0.005;
|
59
|
+
readonly reasoning: "Claude Opus 4 fallback on Vertex AI for most complex tasks";
|
60
|
+
};
|
61
|
+
};
|
62
|
+
};
|
63
|
+
/**
|
64
|
+
* Model Router
|
65
|
+
* Intelligently routes tasks to optimal models based on classification
|
66
|
+
*/
|
67
|
+
export declare class ModelRouter {
|
68
|
+
/**
|
69
|
+
* Route a prompt to the optimal model configuration
|
70
|
+
*/
|
71
|
+
static route(prompt: string, options?: ModelRoutingOptions): ModelRoute;
|
72
|
+
/**
|
73
|
+
* Get fallback route if primary route fails
|
74
|
+
*/
|
75
|
+
static getFallbackRoute(prompt: string, primaryRoute: ModelRoute, options?: ModelRoutingOptions): ModelRoute;
|
76
|
+
/**
|
77
|
+
* Determine task type from a model route
|
78
|
+
*/
|
79
|
+
private static getTaskTypeFromRoute;
|
80
|
+
/**
|
81
|
+
* Get all available model configurations
|
82
|
+
*/
|
83
|
+
static getAvailableModels(): typeof MODEL_CONFIGS;
|
84
|
+
/**
|
85
|
+
* Validate model availability for a given route
|
86
|
+
*/
|
87
|
+
static validateRoute(route: ModelRoute): Promise<boolean>;
|
88
|
+
/**
|
89
|
+
* Get routing statistics for multiple prompts
|
90
|
+
*/
|
91
|
+
static getRoutingStats(prompts: string[]): {
|
92
|
+
total: number;
|
93
|
+
fastRoutes: number;
|
94
|
+
reasoningRoutes: number;
|
95
|
+
averageConfidence: number;
|
96
|
+
providerDistribution: Record<string, number>;
|
97
|
+
};
|
98
|
+
/**
|
99
|
+
* Estimate cost and performance for a route
|
100
|
+
*/
|
101
|
+
static getRouteEstimates(route: ModelRoute, estimatedTokens?: number): {
|
102
|
+
estimatedCost: number;
|
103
|
+
estimatedResponseTime: number;
|
104
|
+
capabilities: string[];
|
105
|
+
};
|
106
|
+
}
|
107
|
+
export {};
|
@@ -0,0 +1,292 @@
|
|
1
|
+
/**
|
2
|
+
* Model Router for NeuroLink Orchestration
|
3
|
+
* Routes tasks to optimal models based on classification and requirements
|
4
|
+
*/
|
5
|
+
import { logger } from "./logger.js";
|
6
|
+
import { BinaryTaskClassifier } from "./taskClassifier.js";
|
7
|
+
import { redactForRouting } from "./promptRedaction.js";
|
8
|
+
/**
|
9
|
+
* Routing configuration constants
|
10
|
+
*/
|
11
|
+
const ROUTING_CONFIG = {
|
12
|
+
minRouteConfidence: 0.3,
|
13
|
+
maxRouteConfidence: 0.95,
|
14
|
+
confidenceBoost: 0.1,
|
15
|
+
};
|
16
|
+
/**
|
17
|
+
* Model configurations for different task types and providers
|
18
|
+
*/
|
19
|
+
const MODEL_CONFIGS = {
|
20
|
+
fast: {
|
21
|
+
primary: {
|
22
|
+
provider: "vertex",
|
23
|
+
model: "gemini-2.5-flash",
|
24
|
+
capabilities: ["speed", "general", "code", "basic-reasoning"],
|
25
|
+
avgResponseTime: 800, // ms
|
26
|
+
costPerToken: 0.0001,
|
27
|
+
reasoning: "Optimized for speed and efficiency via Vertex AI",
|
28
|
+
},
|
29
|
+
fallback: {
|
30
|
+
provider: "vertex",
|
31
|
+
model: "gemini-2.5-pro",
|
32
|
+
capabilities: ["speed", "general", "basic-reasoning"],
|
33
|
+
avgResponseTime: 1200,
|
34
|
+
costPerToken: 0.0002,
|
35
|
+
reasoning: "Vertex AI Gemini Pro fallback",
|
36
|
+
},
|
37
|
+
},
|
38
|
+
reasoning: {
|
39
|
+
primary: {
|
40
|
+
provider: "vertex",
|
41
|
+
model: "claude-sonnet-4@20250514",
|
42
|
+
capabilities: [
|
43
|
+
"reasoning",
|
44
|
+
"analysis",
|
45
|
+
"complex-logic",
|
46
|
+
"code",
|
47
|
+
"creativity",
|
48
|
+
],
|
49
|
+
avgResponseTime: 3000, // ms
|
50
|
+
costPerToken: 0.003,
|
51
|
+
reasoning: "Advanced reasoning and analysis via Claude Sonnet 4 on Vertex AI",
|
52
|
+
},
|
53
|
+
fallback: {
|
54
|
+
provider: "vertex",
|
55
|
+
model: "claude-opus-4@20250514",
|
56
|
+
capabilities: [
|
57
|
+
"reasoning",
|
58
|
+
"analysis",
|
59
|
+
"complex-logic",
|
60
|
+
"code",
|
61
|
+
"creativity",
|
62
|
+
"agentic",
|
63
|
+
],
|
64
|
+
avgResponseTime: 4000,
|
65
|
+
costPerToken: 0.005,
|
66
|
+
reasoning: "Claude Opus 4 fallback on Vertex AI for most complex tasks",
|
67
|
+
},
|
68
|
+
},
|
69
|
+
};
|
70
|
+
/**
|
71
|
+
* Model Router
|
72
|
+
* Intelligently routes tasks to optimal models based on classification
|
73
|
+
*/
|
74
|
+
export class ModelRouter {
|
75
|
+
/**
|
76
|
+
* Route a prompt to the optimal model configuration
|
77
|
+
*/
|
78
|
+
static route(prompt, options = {}) {
|
79
|
+
const startTime = Date.now();
|
80
|
+
// 1. Classify the task if not overridden
|
81
|
+
let classification;
|
82
|
+
if (options.forceTaskType) {
|
83
|
+
classification = {
|
84
|
+
type: options.forceTaskType,
|
85
|
+
confidence: ROUTING_CONFIG.maxRouteConfidence, // Use maxRouteConfidence instead of 1.0
|
86
|
+
reasoning: "forced task type",
|
87
|
+
};
|
88
|
+
}
|
89
|
+
else {
|
90
|
+
classification = BinaryTaskClassifier.classify(prompt);
|
91
|
+
}
|
92
|
+
// 2. Apply special requirements
|
93
|
+
let taskType = classification.type;
|
94
|
+
const reasons = [classification.reasoning];
|
95
|
+
if (options.requireFast) {
|
96
|
+
taskType = "fast";
|
97
|
+
reasons.push("speed required");
|
98
|
+
}
|
99
|
+
if (options.requireCapability) {
|
100
|
+
// Check if the capability suggests a specific task type
|
101
|
+
const capability = options.requireCapability.toLowerCase();
|
102
|
+
if (["analysis", "reasoning", "complex", "research"].some((c) => capability.includes(c))) {
|
103
|
+
taskType = "reasoning";
|
104
|
+
reasons.push(`capability: ${capability}`);
|
105
|
+
}
|
106
|
+
else if (["speed", "quick", "fast", "simple"].some((c) => capability.includes(c))) {
|
107
|
+
taskType = "fast";
|
108
|
+
reasons.push(`capability: ${capability}`);
|
109
|
+
}
|
110
|
+
}
|
111
|
+
// 3. Select model configuration
|
112
|
+
const config = MODEL_CONFIGS[taskType];
|
113
|
+
const selectedConfig = config.primary;
|
114
|
+
// 4. Calculate confidence based on multiple factors
|
115
|
+
let confidence = classification.confidence;
|
116
|
+
// Adjust confidence based on prompt characteristics
|
117
|
+
if (taskType === "fast" && prompt.length < 30) {
|
118
|
+
confidence = Math.min(ROUTING_CONFIG.maxRouteConfidence, confidence + ROUTING_CONFIG.confidenceBoost);
|
119
|
+
reasons.push("very short prompt");
|
120
|
+
}
|
121
|
+
if (taskType === "reasoning" && prompt.length > 150) {
|
122
|
+
confidence = Math.min(ROUTING_CONFIG.maxRouteConfidence, confidence + ROUTING_CONFIG.confidenceBoost);
|
123
|
+
reasons.push("detailed prompt");
|
124
|
+
}
|
125
|
+
// Ensure final confidence is within configured bounds
|
126
|
+
confidence = Math.max(ROUTING_CONFIG.minRouteConfidence, Math.min(ROUTING_CONFIG.maxRouteConfidence, confidence));
|
127
|
+
// 5. Create route result
|
128
|
+
const route = {
|
129
|
+
provider: selectedConfig.provider,
|
130
|
+
model: selectedConfig.model,
|
131
|
+
reasoning: reasons.join(", "),
|
132
|
+
confidence,
|
133
|
+
};
|
134
|
+
const routingTime = Date.now() - startTime;
|
135
|
+
logger.debug("Model routing decision", {
|
136
|
+
prompt: redactForRouting(prompt),
|
137
|
+
taskType,
|
138
|
+
route: {
|
139
|
+
provider: route.provider,
|
140
|
+
model: route.model,
|
141
|
+
confidence: route.confidence.toFixed(2),
|
142
|
+
},
|
143
|
+
reasoning: route.reasoning,
|
144
|
+
routingTime: `${routingTime}ms`,
|
145
|
+
options: Object.keys(options).length > 0 ? options : undefined,
|
146
|
+
});
|
147
|
+
return route;
|
148
|
+
}
|
149
|
+
/**
|
150
|
+
* Get fallback route if primary route fails
|
151
|
+
*/
|
152
|
+
static getFallbackRoute(prompt, primaryRoute, options = {}) {
|
153
|
+
// Determine fallback strategy
|
154
|
+
let fallbackType;
|
155
|
+
if (options.fallbackStrategy) {
|
156
|
+
if (options.fallbackStrategy === "auto") {
|
157
|
+
// Use opposite of primary for fallback
|
158
|
+
const primaryType = this.getTaskTypeFromRoute(primaryRoute);
|
159
|
+
fallbackType = primaryType === "fast" ? "reasoning" : "fast";
|
160
|
+
}
|
161
|
+
else {
|
162
|
+
fallbackType = options.fallbackStrategy;
|
163
|
+
}
|
164
|
+
}
|
165
|
+
else {
|
166
|
+
// Default: use fallback model of same type
|
167
|
+
fallbackType = this.getTaskTypeFromRoute(primaryRoute);
|
168
|
+
}
|
169
|
+
const config = MODEL_CONFIGS[fallbackType];
|
170
|
+
const fallbackConfig = config.fallback;
|
171
|
+
const route = {
|
172
|
+
provider: fallbackConfig.provider,
|
173
|
+
model: fallbackConfig.model,
|
174
|
+
reasoning: `fallback from ${primaryRoute.provider}/${primaryRoute.model}`,
|
175
|
+
confidence: Math.max(ROUTING_CONFIG.minRouteConfidence, Math.min(ROUTING_CONFIG.maxRouteConfidence, primaryRoute.confidence - 0.2)),
|
176
|
+
};
|
177
|
+
logger.debug("Fallback route selected", {
|
178
|
+
originalRoute: `${primaryRoute.provider}/${primaryRoute.model}`,
|
179
|
+
fallbackRoute: `${route.provider}/${route.model}`,
|
180
|
+
fallbackType,
|
181
|
+
strategy: options.fallbackStrategy || "default",
|
182
|
+
});
|
183
|
+
return route;
|
184
|
+
}
|
185
|
+
/**
|
186
|
+
* Determine task type from a model route
|
187
|
+
*/
|
188
|
+
static getTaskTypeFromRoute(route) {
|
189
|
+
// Check which config matches this route
|
190
|
+
for (const [taskType, config] of Object.entries(MODEL_CONFIGS)) {
|
191
|
+
if (config.primary.provider === route.provider &&
|
192
|
+
config.primary.model === route.model) {
|
193
|
+
return taskType;
|
194
|
+
}
|
195
|
+
if (config.fallback.provider === route.provider &&
|
196
|
+
config.fallback.model === route.model) {
|
197
|
+
return taskType;
|
198
|
+
}
|
199
|
+
}
|
200
|
+
// Default fallback based on model name patterns
|
201
|
+
if (route.model.includes("flash") || route.model.includes("mini")) {
|
202
|
+
return "fast";
|
203
|
+
}
|
204
|
+
return "reasoning";
|
205
|
+
}
|
206
|
+
/**
|
207
|
+
* Get all available model configurations
|
208
|
+
*/
|
209
|
+
static getAvailableModels() {
|
210
|
+
return MODEL_CONFIGS;
|
211
|
+
}
|
212
|
+
/**
|
213
|
+
* Validate model availability for a given route
|
214
|
+
*/
|
215
|
+
static async validateRoute(route) {
|
216
|
+
try {
|
217
|
+
// This would typically check provider availability
|
218
|
+
// For now, just validate the configuration exists
|
219
|
+
const configs = Object.values(MODEL_CONFIGS).flatMap((config) => [
|
220
|
+
config.primary,
|
221
|
+
config.fallback,
|
222
|
+
]);
|
223
|
+
return configs.some((config) => config.provider === route.provider && config.model === route.model);
|
224
|
+
}
|
225
|
+
catch (error) {
|
226
|
+
logger.error("Route validation failed", {
|
227
|
+
route,
|
228
|
+
error: error instanceof Error ? error.message : String(error),
|
229
|
+
});
|
230
|
+
return false;
|
231
|
+
}
|
232
|
+
}
|
233
|
+
/**
|
234
|
+
* Get routing statistics for multiple prompts
|
235
|
+
*/
|
236
|
+
static getRoutingStats(prompts) {
|
237
|
+
const routes = prompts.map((prompt) => this.route(prompt));
|
238
|
+
// Handle empty prompts array to avoid divide-by-zero
|
239
|
+
if (routes.length === 0) {
|
240
|
+
const stats = {
|
241
|
+
total: 0,
|
242
|
+
fastRoutes: 0,
|
243
|
+
reasoningRoutes: 0,
|
244
|
+
averageConfidence: 0,
|
245
|
+
providerDistribution: {},
|
246
|
+
};
|
247
|
+
logger.debug("Routing statistics", stats);
|
248
|
+
return stats;
|
249
|
+
}
|
250
|
+
const stats = {
|
251
|
+
total: routes.length,
|
252
|
+
fastRoutes: routes.filter((r) => {
|
253
|
+
const taskType = this.getTaskTypeFromRoute(r);
|
254
|
+
return taskType === "fast";
|
255
|
+
}).length,
|
256
|
+
reasoningRoutes: routes.filter((r) => {
|
257
|
+
const taskType = this.getTaskTypeFromRoute(r);
|
258
|
+
return taskType === "reasoning";
|
259
|
+
}).length,
|
260
|
+
averageConfidence: routes.reduce((sum, r) => sum + r.confidence, 0) / routes.length,
|
261
|
+
providerDistribution: routes.reduce((dist, r) => {
|
262
|
+
dist[r.provider] = (dist[r.provider] || 0) + 1;
|
263
|
+
return dist;
|
264
|
+
}, {}),
|
265
|
+
};
|
266
|
+
logger.debug("Routing statistics", stats);
|
267
|
+
return stats;
|
268
|
+
}
|
269
|
+
/**
|
270
|
+
* Estimate cost and performance for a route
|
271
|
+
*/
|
272
|
+
static getRouteEstimates(route, estimatedTokens = 500) {
|
273
|
+
// Find the config for this route
|
274
|
+
const allConfigs = Object.values(MODEL_CONFIGS).flatMap((config) => [
|
275
|
+
config.primary,
|
276
|
+
config.fallback,
|
277
|
+
]);
|
278
|
+
const config = allConfigs.find((c) => c.provider === route.provider && c.model === route.model);
|
279
|
+
if (!config) {
|
280
|
+
return {
|
281
|
+
estimatedCost: 0,
|
282
|
+
estimatedResponseTime: 2000,
|
283
|
+
capabilities: [],
|
284
|
+
};
|
285
|
+
}
|
286
|
+
return {
|
287
|
+
estimatedCost: config.costPerToken * estimatedTokens,
|
288
|
+
estimatedResponseTime: config.avgResponseTime,
|
289
|
+
capabilities: [...config.capabilities],
|
290
|
+
};
|
291
|
+
}
|
292
|
+
}
|
@@ -192,28 +192,9 @@ export function validateMCPTool(tool) {
|
|
192
192
|
if (execError) {
|
193
193
|
errors.push(execError);
|
194
194
|
}
|
195
|
-
//
|
196
|
-
if (mcpTool.execute) {
|
197
|
-
|
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
|
-
}
|
195
|
+
// Simplified validation - just check if execute is a function
|
196
|
+
if (mcpTool.execute && typeof mcpTool.execute !== "function") {
|
197
|
+
errors.push(new ValidationError("Execute must be a function", "execute", "INVALID_TYPE", ["Provide a function for the execute property"]));
|
217
198
|
}
|
218
199
|
// Check optional properties
|
219
200
|
if (mcpTool.inputSchema && !isNonNullObject(mcpTool.inputSchema)) {
|
@@ -264,7 +245,7 @@ export function validateTextGenerationOptions(options) {
|
|
264
245
|
errors.push(tempError);
|
265
246
|
}
|
266
247
|
// Validate maxTokens
|
267
|
-
const tokensError = validateNumberRange(opts.maxTokens, "maxTokens", 1,
|
248
|
+
const tokensError = validateNumberRange(opts.maxTokens, "maxTokens", 1, 128000);
|
268
249
|
if (tokensError) {
|
269
250
|
errors.push(tokensError);
|
270
251
|
}
|
@@ -316,7 +297,7 @@ export function validateStreamOptions(options) {
|
|
316
297
|
errors.push(tempError);
|
317
298
|
}
|
318
299
|
// Validate maxTokens
|
319
|
-
const tokensError = validateNumberRange(opts.maxTokens, "maxTokens", 1,
|
300
|
+
const tokensError = validateNumberRange(opts.maxTokens, "maxTokens", 1, 128000);
|
320
301
|
if (tokensError) {
|
321
302
|
errors.push(tokensError);
|
322
303
|
}
|
@@ -349,7 +330,7 @@ export function validateGenerateOptions(options) {
|
|
349
330
|
if (tempError) {
|
350
331
|
errors.push(tempError);
|
351
332
|
}
|
352
|
-
const tokensError = validateNumberRange(opts.maxTokens, "maxTokens", 1,
|
333
|
+
const tokensError = validateNumberRange(opts.maxTokens, "maxTokens", 1, 128000);
|
353
334
|
if (tokensError) {
|
354
335
|
errors.push(tokensError);
|
355
336
|
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
/**
|
2
|
+
* Prompt redaction utilities for safe logging
|
3
|
+
* Provides consistent prompt masking across NeuroLink components
|
4
|
+
*/
|
5
|
+
export interface PromptRedactionOptions {
|
6
|
+
/** Maximum length of redacted prompt */
|
7
|
+
maxLength?: number;
|
8
|
+
/** Whether to show word count */
|
9
|
+
showWordCount?: boolean;
|
10
|
+
/** Mask character to use for redaction */
|
11
|
+
maskChar?: string;
|
12
|
+
}
|
13
|
+
/**
|
14
|
+
* Redact a prompt for safe logging
|
15
|
+
* Truncates to maxLength and optionally shows word count
|
16
|
+
*/
|
17
|
+
export declare function redactPrompt(prompt: string, options?: PromptRedactionOptions): string;
|
18
|
+
/**
|
19
|
+
* Create a short safe mask for highly sensitive contexts
|
20
|
+
*/
|
21
|
+
export declare function createSafeMask(prompt: string, _maskLength?: number): string;
|
22
|
+
/**
|
23
|
+
* Redact for classification context (matches classifier behavior)
|
24
|
+
*/
|
25
|
+
export declare function redactForClassification(prompt: string): string;
|
26
|
+
/**
|
27
|
+
* Redact for routing context (matches router behavior)
|
28
|
+
*/
|
29
|
+
export declare function redactForRouting(prompt: string): string;
|
@@ -0,0 +1,62 @@
|
|
1
|
+
/**
|
2
|
+
* Prompt redaction utilities for safe logging
|
3
|
+
* Provides consistent prompt masking across NeuroLink components
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* Default redaction options
|
7
|
+
*/
|
8
|
+
const DEFAULT_REDACTION_OPTIONS = {
|
9
|
+
maxLength: 100,
|
10
|
+
showWordCount: true,
|
11
|
+
maskChar: "*",
|
12
|
+
};
|
13
|
+
/**
|
14
|
+
* Redact a prompt for safe logging
|
15
|
+
* Truncates to maxLength and optionally shows word count
|
16
|
+
*/
|
17
|
+
export function redactPrompt(prompt, options = {}) {
|
18
|
+
const opts = { ...DEFAULT_REDACTION_OPTIONS, ...options };
|
19
|
+
if (!prompt || typeof prompt !== "string") {
|
20
|
+
return "[INVALID_PROMPT]";
|
21
|
+
}
|
22
|
+
const wordCount = prompt.trim().split(/\s+/).length;
|
23
|
+
let redacted = prompt.substring(0, opts.maxLength);
|
24
|
+
// Add ellipsis if truncated
|
25
|
+
if (prompt.length > opts.maxLength) {
|
26
|
+
redacted = redacted.substring(0, opts.maxLength - 3) + "...";
|
27
|
+
}
|
28
|
+
// Optionally append word count
|
29
|
+
if (opts.showWordCount) {
|
30
|
+
redacted += ` [${wordCount} words]`;
|
31
|
+
}
|
32
|
+
return redacted;
|
33
|
+
}
|
34
|
+
/**
|
35
|
+
* Create a short safe mask for highly sensitive contexts
|
36
|
+
*/
|
37
|
+
export function createSafeMask(prompt, _maskLength = 20) {
|
38
|
+
if (!prompt || typeof prompt !== "string") {
|
39
|
+
return "[INVALID_PROMPT]";
|
40
|
+
}
|
41
|
+
const wordCount = prompt.trim().split(/\s+/).length;
|
42
|
+
const charCount = prompt.length;
|
43
|
+
return `[REDACTED: ${charCount} chars, ${wordCount} words]`;
|
44
|
+
}
|
45
|
+
/**
|
46
|
+
* Redact for classification context (matches classifier behavior)
|
47
|
+
*/
|
48
|
+
export function redactForClassification(prompt) {
|
49
|
+
return redactPrompt(prompt, {
|
50
|
+
maxLength: 100,
|
51
|
+
showWordCount: false,
|
52
|
+
});
|
53
|
+
}
|
54
|
+
/**
|
55
|
+
* Redact for routing context (matches router behavior)
|
56
|
+
*/
|
57
|
+
export function redactForRouting(prompt) {
|
58
|
+
return redactPrompt(prompt, {
|
59
|
+
maxLength: 100,
|
60
|
+
showWordCount: true,
|
61
|
+
});
|
62
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import type { ZodUnknownSchema } from "../types/tools.js";
|
2
|
+
/**
|
3
|
+
* Convert Zod schema to JSON Schema format for Claude AI
|
4
|
+
*/
|
5
|
+
export declare function convertZodToJsonSchema(zodSchema: ZodUnknownSchema): object;
|
6
|
+
/**
|
7
|
+
* Check if a value is a Zod schema
|
8
|
+
*/
|
9
|
+
export declare function isZodSchema(value: unknown): boolean;
|
10
|
+
/**
|
11
|
+
* Convert JSON Schema to Zod schema format using official json-schema-to-zod library
|
12
|
+
* This ensures complete preservation of all schema structure and validation rules
|
13
|
+
*/
|
14
|
+
export declare function convertJsonSchemaToZod(jsonSchema: Record<string, unknown>): ZodUnknownSchema;
|