@juspay/neurolink 5.0.0 → 5.2.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 +20 -7
- package/README.md +160 -172
- package/dist/agent/direct-tools.d.ts +6 -6
- package/dist/chat/sse-handler.js +5 -4
- package/dist/chat/websocket-chat-handler.js +9 -9
- package/dist/cli/commands/config.d.ts +3 -3
- package/dist/cli/commands/mcp.js +9 -8
- package/dist/cli/commands/ollama.js +3 -3
- package/dist/cli/factories/command-factory.d.ts +18 -0
- package/dist/cli/factories/command-factory.js +183 -0
- package/dist/cli/index.js +105 -157
- package/dist/cli/utils/interactive-setup.js +2 -2
- package/dist/core/base-provider.d.ts +423 -0
- package/dist/core/base-provider.js +365 -0
- package/dist/core/constants.d.ts +1 -1
- package/dist/core/constants.js +1 -1
- package/dist/core/dynamic-models.d.ts +6 -6
- package/dist/core/evaluation.d.ts +19 -80
- package/dist/core/evaluation.js +185 -484
- package/dist/core/factory.d.ts +3 -3
- package/dist/core/factory.js +31 -91
- package/dist/core/service-registry.d.ts +47 -0
- package/dist/core/service-registry.js +112 -0
- package/dist/core/types.d.ts +49 -49
- package/dist/core/types.js +1 -0
- package/dist/factories/compatibility-factory.d.ts +20 -0
- package/dist/factories/compatibility-factory.js +69 -0
- package/dist/factories/provider-factory.d.ts +72 -0
- package/dist/factories/provider-factory.js +144 -0
- package/dist/factories/provider-generate-factory.d.ts +20 -0
- package/dist/factories/provider-generate-factory.js +87 -0
- package/dist/factories/provider-registry.d.ts +38 -0
- package/dist/factories/provider-registry.js +107 -0
- package/dist/index.d.ts +8 -5
- package/dist/index.js +5 -5
- package/dist/lib/agent/direct-tools.d.ts +6 -6
- package/dist/lib/chat/sse-handler.js +5 -4
- package/dist/lib/chat/websocket-chat-handler.js +9 -9
- package/dist/lib/core/base-provider.d.ts +423 -0
- package/dist/lib/core/base-provider.js +365 -0
- package/dist/lib/core/constants.d.ts +1 -1
- package/dist/lib/core/constants.js +1 -1
- package/dist/lib/core/dynamic-models.d.ts +6 -6
- package/dist/lib/core/evaluation.d.ts +19 -80
- package/dist/lib/core/evaluation.js +185 -484
- package/dist/lib/core/factory.d.ts +3 -3
- package/dist/lib/core/factory.js +30 -91
- package/dist/lib/core/service-registry.d.ts +47 -0
- package/dist/lib/core/service-registry.js +112 -0
- package/dist/lib/core/types.d.ts +49 -49
- package/dist/lib/core/types.js +1 -0
- package/dist/lib/factories/compatibility-factory.d.ts +20 -0
- package/dist/lib/factories/compatibility-factory.js +69 -0
- package/dist/lib/factories/provider-factory.d.ts +72 -0
- package/dist/lib/factories/provider-factory.js +144 -0
- package/dist/lib/factories/provider-generate-factory.d.ts +20 -0
- package/dist/lib/factories/provider-generate-factory.js +87 -0
- package/dist/lib/factories/provider-registry.d.ts +38 -0
- package/dist/lib/factories/provider-registry.js +107 -0
- package/dist/lib/index.d.ts +8 -5
- package/dist/lib/index.js +5 -5
- package/dist/lib/mcp/client.js +5 -5
- package/dist/lib/mcp/config.js +28 -3
- package/dist/lib/mcp/dynamic-orchestrator.js +8 -8
- package/dist/lib/mcp/external-client.js +2 -2
- package/dist/lib/mcp/factory.d.ts +1 -1
- package/dist/lib/mcp/factory.js +1 -1
- package/dist/lib/mcp/function-calling.js +1 -1
- package/dist/lib/mcp/initialize-tools.d.ts +1 -1
- package/dist/lib/mcp/initialize-tools.js +45 -1
- package/dist/lib/mcp/initialize.js +16 -6
- package/dist/lib/mcp/neurolink-mcp-client.js +10 -10
- package/dist/lib/mcp/orchestrator.js +4 -4
- package/dist/lib/mcp/servers/agent/direct-tools-server.d.ts +8 -0
- package/dist/lib/mcp/servers/agent/direct-tools-server.js +109 -0
- package/dist/lib/mcp/servers/ai-providers/ai-analysis-tools.js +10 -10
- package/dist/lib/mcp/servers/ai-providers/ai-core-server.js +8 -6
- package/dist/lib/mcp/servers/ai-providers/ai-workflow-tools.d.ts +2 -2
- package/dist/lib/mcp/servers/ai-providers/ai-workflow-tools.js +16 -16
- package/dist/lib/mcp/unified-registry.d.ts +4 -0
- package/dist/lib/mcp/unified-registry.js +42 -9
- package/dist/lib/neurolink.d.ts +161 -174
- package/dist/lib/neurolink.js +723 -397
- package/dist/lib/providers/amazon-bedrock.d.ts +32 -0
- package/dist/lib/providers/amazon-bedrock.js +143 -0
- package/dist/lib/providers/analytics-helper.js +7 -4
- package/dist/lib/providers/anthropic-baseprovider.d.ts +23 -0
- package/dist/lib/providers/anthropic-baseprovider.js +114 -0
- package/dist/lib/providers/anthropic.d.ts +19 -39
- package/dist/lib/providers/anthropic.js +84 -378
- package/dist/lib/providers/azure-openai.d.ts +20 -0
- package/dist/lib/providers/azure-openai.js +89 -0
- package/dist/lib/providers/function-calling-provider.d.ts +14 -12
- package/dist/lib/providers/function-calling-provider.js +114 -64
- package/dist/lib/providers/google-ai-studio.d.ts +23 -0
- package/dist/lib/providers/google-ai-studio.js +107 -0
- package/dist/lib/providers/google-vertex.d.ts +47 -0
- package/dist/lib/providers/google-vertex.js +205 -0
- package/dist/lib/providers/huggingFace.d.ts +33 -27
- package/dist/lib/providers/huggingFace.js +103 -400
- package/dist/lib/providers/index.d.ts +9 -9
- package/dist/lib/providers/index.js +9 -9
- package/dist/lib/providers/mcp-provider.d.ts +13 -8
- package/dist/lib/providers/mcp-provider.js +63 -18
- package/dist/lib/providers/mistral.d.ts +42 -0
- package/dist/lib/providers/mistral.js +160 -0
- package/dist/lib/providers/ollama.d.ts +52 -35
- package/dist/lib/providers/ollama.js +297 -477
- package/dist/lib/providers/openAI.d.ts +21 -21
- package/dist/lib/providers/openAI.js +81 -245
- package/dist/lib/sdk/tool-extension.d.ts +181 -0
- package/dist/lib/sdk/tool-extension.js +283 -0
- package/dist/lib/sdk/tool-registration.d.ts +95 -0
- package/dist/lib/sdk/tool-registration.js +167 -0
- package/dist/lib/types/generate-types.d.ts +80 -0
- package/dist/lib/types/generate-types.js +1 -0
- package/dist/lib/types/mcp-types.d.ts +116 -0
- package/dist/lib/types/mcp-types.js +5 -0
- package/dist/lib/types/stream-types.d.ts +95 -0
- package/dist/lib/types/stream-types.js +1 -0
- package/dist/lib/types/universal-provider-options.d.ts +87 -0
- package/dist/lib/types/universal-provider-options.js +53 -0
- package/dist/lib/utils/providerUtils-fixed.js +1 -1
- package/dist/lib/utils/streaming-utils.d.ts +14 -2
- package/dist/lib/utils/streaming-utils.js +0 -3
- package/dist/mcp/client.js +5 -5
- package/dist/mcp/config.js +28 -3
- package/dist/mcp/dynamic-orchestrator.js +8 -8
- package/dist/mcp/external-client.js +2 -2
- package/dist/mcp/factory.d.ts +1 -1
- package/dist/mcp/factory.js +1 -1
- package/dist/mcp/function-calling.js +1 -1
- package/dist/mcp/initialize-tools.d.ts +1 -1
- package/dist/mcp/initialize-tools.js +45 -1
- package/dist/mcp/initialize.js +16 -6
- package/dist/mcp/neurolink-mcp-client.js +10 -10
- package/dist/mcp/orchestrator.js +4 -4
- package/dist/mcp/servers/agent/direct-tools-server.d.ts +8 -0
- package/dist/mcp/servers/agent/direct-tools-server.js +109 -0
- package/dist/mcp/servers/ai-providers/ai-analysis-tools.js +10 -10
- package/dist/mcp/servers/ai-providers/ai-core-server.js +8 -6
- package/dist/mcp/servers/ai-providers/ai-workflow-tools.d.ts +2 -2
- package/dist/mcp/servers/ai-providers/ai-workflow-tools.js +16 -16
- package/dist/mcp/unified-registry.d.ts +4 -0
- package/dist/mcp/unified-registry.js +42 -9
- package/dist/neurolink.d.ts +161 -174
- package/dist/neurolink.js +723 -397
- package/dist/providers/amazon-bedrock.d.ts +32 -0
- package/dist/providers/amazon-bedrock.js +143 -0
- package/dist/providers/analytics-helper.js +7 -4
- package/dist/providers/anthropic-baseprovider.d.ts +23 -0
- package/dist/providers/anthropic-baseprovider.js +114 -0
- package/dist/providers/anthropic.d.ts +19 -39
- package/dist/providers/anthropic.js +83 -377
- package/dist/providers/azure-openai.d.ts +20 -0
- package/dist/providers/azure-openai.js +89 -0
- package/dist/providers/function-calling-provider.d.ts +14 -12
- package/dist/providers/function-calling-provider.js +114 -64
- package/dist/providers/google-ai-studio.d.ts +23 -0
- package/dist/providers/google-ai-studio.js +108 -0
- package/dist/providers/google-vertex.d.ts +47 -0
- package/dist/providers/google-vertex.js +205 -0
- package/dist/providers/huggingFace.d.ts +33 -27
- package/dist/providers/huggingFace.js +102 -399
- package/dist/providers/index.d.ts +9 -9
- package/dist/providers/index.js +9 -9
- package/dist/providers/mcp-provider.d.ts +13 -8
- package/dist/providers/mcp-provider.js +63 -18
- package/dist/providers/mistral.d.ts +42 -0
- package/dist/providers/mistral.js +160 -0
- package/dist/providers/ollama.d.ts +52 -35
- package/dist/providers/ollama.js +297 -476
- package/dist/providers/openAI.d.ts +21 -21
- package/dist/providers/openAI.js +81 -246
- package/dist/sdk/tool-extension.d.ts +181 -0
- package/dist/sdk/tool-extension.js +283 -0
- package/dist/sdk/tool-registration.d.ts +95 -0
- package/dist/sdk/tool-registration.js +168 -0
- package/dist/types/generate-types.d.ts +80 -0
- package/dist/types/generate-types.js +1 -0
- package/dist/types/mcp-types.d.ts +116 -0
- package/dist/types/mcp-types.js +5 -0
- package/dist/types/stream-types.d.ts +95 -0
- package/dist/types/stream-types.js +1 -0
- package/dist/types/universal-provider-options.d.ts +87 -0
- package/dist/types/universal-provider-options.js +53 -0
- package/dist/utils/providerUtils-fixed.js +1 -1
- package/dist/utils/streaming-utils.d.ts +14 -2
- package/dist/utils/streaming-utils.js +0 -3
- package/package.json +15 -10
- package/dist/lib/providers/agent-enhanced-provider.d.ts +0 -89
- package/dist/lib/providers/agent-enhanced-provider.js +0 -614
- package/dist/lib/providers/amazonBedrock.d.ts +0 -19
- package/dist/lib/providers/amazonBedrock.js +0 -334
- package/dist/lib/providers/azureOpenAI.d.ts +0 -39
- package/dist/lib/providers/azureOpenAI.js +0 -436
- package/dist/lib/providers/googleAIStudio.d.ts +0 -49
- package/dist/lib/providers/googleAIStudio.js +0 -333
- package/dist/lib/providers/googleVertexAI.d.ts +0 -38
- package/dist/lib/providers/googleVertexAI.js +0 -519
- package/dist/lib/providers/mistralAI.d.ts +0 -34
- package/dist/lib/providers/mistralAI.js +0 -294
- package/dist/providers/agent-enhanced-provider.d.ts +0 -89
- package/dist/providers/agent-enhanced-provider.js +0 -614
- package/dist/providers/amazonBedrock.d.ts +0 -19
- package/dist/providers/amazonBedrock.js +0 -334
- package/dist/providers/azureOpenAI.d.ts +0 -39
- package/dist/providers/azureOpenAI.js +0 -437
- package/dist/providers/googleAIStudio.d.ts +0 -49
- package/dist/providers/googleAIStudio.js +0 -333
- package/dist/providers/googleVertexAI.d.ts +0 -38
- package/dist/providers/googleVertexAI.js +0 -519
- package/dist/providers/mistralAI.d.ts +0 -34
- package/dist/providers/mistralAI.js +0 -294
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NeuroLink SDK Tool Extension System
|
|
3
|
+
* Allows developers to register custom tools that integrate with AI providers
|
|
4
|
+
*/
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { tool as createAISDKTool } from "ai";
|
|
7
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
8
|
+
import { logger } from "../utils/logger.js";
|
|
9
|
+
/**
|
|
10
|
+
* Converts a custom tool to Vercel AI SDK format
|
|
11
|
+
*/
|
|
12
|
+
export function convertToAISDKTool(name, customTool) {
|
|
13
|
+
// Convert parameters to JSON schema if needed
|
|
14
|
+
let parametersSchema = {};
|
|
15
|
+
let zodSchema;
|
|
16
|
+
if (customTool.parameters) {
|
|
17
|
+
if ("parse" in customTool.parameters && "_def" in customTool.parameters) {
|
|
18
|
+
// It's a Zod schema
|
|
19
|
+
zodSchema = customTool.parameters;
|
|
20
|
+
parametersSchema = zodToJsonSchema(zodSchema);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
// It's already a JSON schema - convert to Zod
|
|
24
|
+
parametersSchema = customTool.parameters;
|
|
25
|
+
zodSchema = z.object({}).passthrough(); // Allow any properties
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
zodSchema = z.object({});
|
|
30
|
+
}
|
|
31
|
+
return createAISDKTool({
|
|
32
|
+
description: customTool.description,
|
|
33
|
+
parameters: zodSchema,
|
|
34
|
+
execute: async (args) => {
|
|
35
|
+
try {
|
|
36
|
+
// Apply timeout if configured
|
|
37
|
+
if (customTool.config?.timeout) {
|
|
38
|
+
return await Promise.race([
|
|
39
|
+
customTool.execute(args),
|
|
40
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`Tool ${name} timed out`)), customTool.config.timeout)),
|
|
41
|
+
]);
|
|
42
|
+
}
|
|
43
|
+
return await customTool.execute(args);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
logger.error(`Tool ${name} execution failed:`, error);
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Tool registry for managing custom tools
|
|
54
|
+
*/
|
|
55
|
+
export class ToolRegistry {
|
|
56
|
+
tools = new Map();
|
|
57
|
+
middleware = [];
|
|
58
|
+
permissions = {};
|
|
59
|
+
rateLimits = new Map();
|
|
60
|
+
/**
|
|
61
|
+
* Simple rate limiting check with automatic cleanup
|
|
62
|
+
*/
|
|
63
|
+
checkRateLimit(name, rateLimit) {
|
|
64
|
+
const now = Date.now();
|
|
65
|
+
// Clean up expired entries to prevent memory leaks
|
|
66
|
+
for (const [key, limit] of this.rateLimits.entries()) {
|
|
67
|
+
if (limit.resetTime <= now) {
|
|
68
|
+
this.rateLimits.delete(key);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const limit = this.rateLimits.get(name);
|
|
72
|
+
if (limit && limit.resetTime > now) {
|
|
73
|
+
if (limit.count >= rateLimit.requests) {
|
|
74
|
+
throw new Error(`Tool ${name} rate limit exceeded`);
|
|
75
|
+
}
|
|
76
|
+
limit.count++;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
this.rateLimits.set(name, {
|
|
80
|
+
count: 1,
|
|
81
|
+
resetTime: now + rateLimit.window,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Register a custom tool
|
|
87
|
+
*/
|
|
88
|
+
register(name, tool) {
|
|
89
|
+
if (this.tools.has(name)) {
|
|
90
|
+
logger.warn(`Tool ${name} already registered, overwriting`);
|
|
91
|
+
}
|
|
92
|
+
this.tools.set(name, tool);
|
|
93
|
+
logger.info(`Registered custom tool: ${name}`);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Register multiple tools at once
|
|
97
|
+
*/
|
|
98
|
+
registerMany(tools) {
|
|
99
|
+
Object.entries(tools).forEach(([name, tool]) => {
|
|
100
|
+
this.register(name, tool);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Unregister a tool
|
|
105
|
+
*/
|
|
106
|
+
unregister(name) {
|
|
107
|
+
const result = this.tools.delete(name);
|
|
108
|
+
if (result) {
|
|
109
|
+
logger.info(`Unregistered tool: ${name}`);
|
|
110
|
+
}
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Get a tool by name
|
|
115
|
+
*/
|
|
116
|
+
get(name) {
|
|
117
|
+
return this.tools.get(name);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Get all registered tools
|
|
121
|
+
*/
|
|
122
|
+
getAll() {
|
|
123
|
+
return new Map(this.tools);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Convert all tools to AI SDK format
|
|
127
|
+
*/
|
|
128
|
+
toAISDKTools() {
|
|
129
|
+
const aiTools = {};
|
|
130
|
+
for (const [name, tool] of this.tools) {
|
|
131
|
+
if (this.isToolAllowed(name)) {
|
|
132
|
+
aiTools[name] = convertToAISDKTool(name, tool);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return aiTools;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Add middleware
|
|
139
|
+
*/
|
|
140
|
+
use(middleware) {
|
|
141
|
+
this.middleware.push(middleware);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Set permissions
|
|
145
|
+
*/
|
|
146
|
+
setPermissions(permissions) {
|
|
147
|
+
this.permissions = permissions;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Check if a tool is allowed
|
|
151
|
+
*/
|
|
152
|
+
isToolAllowed(name) {
|
|
153
|
+
// Check denylist first
|
|
154
|
+
if (this.permissions.denylist?.includes(name)) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
// Check allowlist if specified
|
|
158
|
+
if (this.permissions.allowlist &&
|
|
159
|
+
!this.permissions.allowlist.includes(name)) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Execute a tool with middleware
|
|
166
|
+
*/
|
|
167
|
+
async execute(name, args, context) {
|
|
168
|
+
const tool = this.tools.get(name);
|
|
169
|
+
if (!tool) {
|
|
170
|
+
throw new Error(`Tool ${name} not found`);
|
|
171
|
+
}
|
|
172
|
+
// Check permissions
|
|
173
|
+
if (!this.isToolAllowed(name)) {
|
|
174
|
+
throw new Error(`Tool ${name} is not allowed`);
|
|
175
|
+
}
|
|
176
|
+
// Check custom validator
|
|
177
|
+
if (this.permissions.customValidator) {
|
|
178
|
+
const allowed = await this.permissions.customValidator(name, args);
|
|
179
|
+
if (!allowed) {
|
|
180
|
+
throw new Error(`Tool ${name} execution denied by custom validator`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Check rate limit
|
|
184
|
+
if (tool.config?.rateLimit) {
|
|
185
|
+
this.checkRateLimit(name, tool.config.rateLimit);
|
|
186
|
+
}
|
|
187
|
+
// Build middleware chain
|
|
188
|
+
let index = 0;
|
|
189
|
+
const next = async () => {
|
|
190
|
+
if (index < this.middleware.length) {
|
|
191
|
+
const middleware = this.middleware[index++];
|
|
192
|
+
return middleware(name, args, next, context);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
// Execute the actual tool
|
|
196
|
+
return tool.execute(args, context);
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
return next();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Create a simple tool helper
|
|
204
|
+
*/
|
|
205
|
+
export function createTool(config) {
|
|
206
|
+
return config;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Create an async tool helper
|
|
210
|
+
*/
|
|
211
|
+
export function createAsyncTool(config) {
|
|
212
|
+
return config;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Create a batch tool that processes multiple items
|
|
216
|
+
*/
|
|
217
|
+
export function createBatchTool(config) {
|
|
218
|
+
return {
|
|
219
|
+
...config,
|
|
220
|
+
execute: async ({ items }, context) => {
|
|
221
|
+
const batchSize = config.batchSize || 10;
|
|
222
|
+
const results = [];
|
|
223
|
+
for (let i = 0; i < items.length; i += batchSize) {
|
|
224
|
+
const batch = items.slice(i, i + batchSize);
|
|
225
|
+
const batchResults = await Promise.all(batch.map((item) => config.processItem(item, context)));
|
|
226
|
+
results.push(...batchResults);
|
|
227
|
+
}
|
|
228
|
+
return results;
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Tool testing utilities
|
|
234
|
+
*/
|
|
235
|
+
export const TestUtils = {
|
|
236
|
+
/**
|
|
237
|
+
* Create a mock tool context
|
|
238
|
+
*/
|
|
239
|
+
mockContext(overrides) {
|
|
240
|
+
return {
|
|
241
|
+
callTool: async (name, args) => {
|
|
242
|
+
logger.debug(`Mock tool call: ${name}`, args);
|
|
243
|
+
return {};
|
|
244
|
+
},
|
|
245
|
+
session: {
|
|
246
|
+
id: "test-session",
|
|
247
|
+
userId: "test-user",
|
|
248
|
+
provider: "test-provider",
|
|
249
|
+
model: "test-model",
|
|
250
|
+
},
|
|
251
|
+
logger,
|
|
252
|
+
...overrides,
|
|
253
|
+
};
|
|
254
|
+
},
|
|
255
|
+
/**
|
|
256
|
+
* Test a tool with mock data
|
|
257
|
+
*/
|
|
258
|
+
async testTool(tool, testCases) {
|
|
259
|
+
const context = TestUtils.mockContext();
|
|
260
|
+
const results = [];
|
|
261
|
+
for (const testCase of testCases) {
|
|
262
|
+
try {
|
|
263
|
+
const result = await tool.execute(testCase.input, context);
|
|
264
|
+
results.push({
|
|
265
|
+
input: testCase.input,
|
|
266
|
+
output: result,
|
|
267
|
+
success: true,
|
|
268
|
+
matches: testCase.expected
|
|
269
|
+
? JSON.stringify(result) === JSON.stringify(testCase.expected)
|
|
270
|
+
: undefined,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
results.push({
|
|
275
|
+
input: testCase.input,
|
|
276
|
+
error: error instanceof Error ? error.message : String(error),
|
|
277
|
+
success: false,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return results;
|
|
282
|
+
},
|
|
283
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NeuroLink SDK Tool Registration API
|
|
3
|
+
* Simple interface for developers to register custom tools
|
|
4
|
+
*/
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import type { Tool } from "ai";
|
|
7
|
+
import { logger } from "../utils/logger.js";
|
|
8
|
+
import type { InMemoryMCPServerConfig, InMemoryToolInfo } from "../types/mcp-types.js";
|
|
9
|
+
/**
|
|
10
|
+
* Context provided to tools during execution
|
|
11
|
+
*/
|
|
12
|
+
export interface ToolContext {
|
|
13
|
+
/**
|
|
14
|
+
* Current session ID
|
|
15
|
+
*/
|
|
16
|
+
sessionId: string;
|
|
17
|
+
/**
|
|
18
|
+
* User ID if available
|
|
19
|
+
*/
|
|
20
|
+
userId?: string;
|
|
21
|
+
/**
|
|
22
|
+
* AI provider being used
|
|
23
|
+
*/
|
|
24
|
+
provider?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Model being used
|
|
27
|
+
*/
|
|
28
|
+
model?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Call another tool
|
|
31
|
+
*/
|
|
32
|
+
callTool?: (name: string, args: any) => Promise<any>;
|
|
33
|
+
/**
|
|
34
|
+
* Logger instance
|
|
35
|
+
*/
|
|
36
|
+
logger: typeof logger;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Simple tool interface for SDK users
|
|
40
|
+
*/
|
|
41
|
+
export interface SimpleTool {
|
|
42
|
+
/**
|
|
43
|
+
* Tool description that helps AI understand when to use it
|
|
44
|
+
*/
|
|
45
|
+
description: string;
|
|
46
|
+
/**
|
|
47
|
+
* Parameters schema using Zod (optional)
|
|
48
|
+
*/
|
|
49
|
+
parameters?: z.ZodSchema;
|
|
50
|
+
/**
|
|
51
|
+
* Tool execution function
|
|
52
|
+
*/
|
|
53
|
+
execute: (args: any, context?: ToolContext) => Promise<any> | any;
|
|
54
|
+
/**
|
|
55
|
+
* Optional metadata
|
|
56
|
+
*/
|
|
57
|
+
metadata?: {
|
|
58
|
+
category?: string;
|
|
59
|
+
version?: string;
|
|
60
|
+
author?: string;
|
|
61
|
+
[key: string]: any;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Converts a SimpleTool to Vercel AI SDK format
|
|
66
|
+
*/
|
|
67
|
+
export declare function convertToAISDKTool(name: string, simpleTool: SimpleTool): Tool;
|
|
68
|
+
/**
|
|
69
|
+
* Converts a SimpleTool to MCP tool format
|
|
70
|
+
*/
|
|
71
|
+
export declare function convertToMCPTool(simpleTool: SimpleTool): InMemoryToolInfo;
|
|
72
|
+
/**
|
|
73
|
+
* Creates an in-memory MCP server configuration from a set of tools
|
|
74
|
+
*/
|
|
75
|
+
export declare function createMCPServerFromTools(serverId: string, tools: Record<string, SimpleTool>, metadata?: {
|
|
76
|
+
title?: string;
|
|
77
|
+
description?: string;
|
|
78
|
+
category?: string;
|
|
79
|
+
[key: string]: any;
|
|
80
|
+
}): InMemoryMCPServerConfig;
|
|
81
|
+
/**
|
|
82
|
+
* Helper to create a tool with type safety
|
|
83
|
+
*/
|
|
84
|
+
export declare function createTool<TParams = any>(config: SimpleTool): SimpleTool;
|
|
85
|
+
/**
|
|
86
|
+
* Helper to create a tool with typed parameters
|
|
87
|
+
*/
|
|
88
|
+
export declare function createTypedTool<TParams extends z.ZodSchema>(config: Omit<SimpleTool, "execute"> & {
|
|
89
|
+
parameters: TParams;
|
|
90
|
+
execute: (args: z.infer<TParams>, context?: ToolContext) => Promise<any> | any;
|
|
91
|
+
}): SimpleTool;
|
|
92
|
+
/**
|
|
93
|
+
* Validate tool configuration with detailed error messages
|
|
94
|
+
*/
|
|
95
|
+
export declare function validateTool(name: string, tool: SimpleTool): void;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NeuroLink SDK Tool Registration API
|
|
3
|
+
* Simple interface for developers to register custom tools
|
|
4
|
+
*/
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { tool as createAISDKTool } from "ai";
|
|
7
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
8
|
+
import { logger } from "../utils/logger.js";
|
|
9
|
+
/**
|
|
10
|
+
* Configuration constants for tool validation
|
|
11
|
+
*/
|
|
12
|
+
const envValue = parseInt(process.env.NEUROLINK_TOOL_DESCRIPTION_MAX_LENGTH || "200", 10);
|
|
13
|
+
const DEFAULT_DESCRIPTION_MAX_LENGTH = Number.isInteger(envValue) && envValue > 0 ? envValue : 200;
|
|
14
|
+
/**
|
|
15
|
+
* Converts a SimpleTool to Vercel AI SDK format
|
|
16
|
+
*/
|
|
17
|
+
export function convertToAISDKTool(name, simpleTool) {
|
|
18
|
+
return createAISDKTool({
|
|
19
|
+
description: simpleTool.description,
|
|
20
|
+
parameters: simpleTool.parameters || z.object({}),
|
|
21
|
+
execute: async (args) => {
|
|
22
|
+
try {
|
|
23
|
+
// Create a minimal context for standalone execution
|
|
24
|
+
const context = {
|
|
25
|
+
sessionId: `tool-${name}-${Date.now()}`,
|
|
26
|
+
logger,
|
|
27
|
+
};
|
|
28
|
+
const result = await simpleTool.execute(args, context);
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
logger.error(`Tool ${name} execution failed:`, error);
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Converts a SimpleTool to MCP tool format
|
|
40
|
+
*/
|
|
41
|
+
export function convertToMCPTool(simpleTool) {
|
|
42
|
+
return {
|
|
43
|
+
description: simpleTool.description,
|
|
44
|
+
execute: async (params) => {
|
|
45
|
+
try {
|
|
46
|
+
const result = await simpleTool.execute(params);
|
|
47
|
+
return {
|
|
48
|
+
success: true,
|
|
49
|
+
data: result,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
54
|
+
logger.error("MCP tool execution failed:", error);
|
|
55
|
+
return {
|
|
56
|
+
success: false,
|
|
57
|
+
error: errorMessage,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
inputSchema: simpleTool.parameters,
|
|
62
|
+
isImplemented: true,
|
|
63
|
+
metadata: simpleTool.metadata,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Creates an in-memory MCP server configuration from a set of tools
|
|
68
|
+
*/
|
|
69
|
+
export function createMCPServerFromTools(serverId, tools, metadata) {
|
|
70
|
+
const mcpTools = {};
|
|
71
|
+
for (const [name, tool] of Object.entries(tools)) {
|
|
72
|
+
mcpTools[name] = convertToMCPTool(tool);
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
server: {
|
|
76
|
+
title: metadata?.title || serverId,
|
|
77
|
+
description: metadata?.description,
|
|
78
|
+
tools: mcpTools,
|
|
79
|
+
},
|
|
80
|
+
category: metadata?.category,
|
|
81
|
+
metadata: metadata || {},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Helper to create a tool with type safety
|
|
86
|
+
*/
|
|
87
|
+
export function createTool(config) {
|
|
88
|
+
return config;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Helper to create a tool with typed parameters
|
|
92
|
+
*/
|
|
93
|
+
export function createTypedTool(config) {
|
|
94
|
+
return config;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Validate tool description length
|
|
98
|
+
*/
|
|
99
|
+
function validateDescriptionLength(name, description) {
|
|
100
|
+
const maxDescriptionLength = Number.isInteger(DEFAULT_DESCRIPTION_MAX_LENGTH) &&
|
|
101
|
+
DEFAULT_DESCRIPTION_MAX_LENGTH > 0
|
|
102
|
+
? DEFAULT_DESCRIPTION_MAX_LENGTH
|
|
103
|
+
: 200;
|
|
104
|
+
if (description.length > maxDescriptionLength) {
|
|
105
|
+
throw new Error(`Tool '${name}' description should be concise (max ${maxDescriptionLength} characters). ` +
|
|
106
|
+
`Current length: ${description.length}. ` +
|
|
107
|
+
`Consider shortening: "${description.substring(0, 50)}..."`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Validate tool configuration with detailed error messages
|
|
112
|
+
*/
|
|
113
|
+
export function validateTool(name, tool) {
|
|
114
|
+
// Validate tool name
|
|
115
|
+
if (!name || typeof name !== "string" || name.trim() === "") {
|
|
116
|
+
throw new Error(`Invalid tool name: must be a non-empty string. Received: ${name}`);
|
|
117
|
+
}
|
|
118
|
+
// Validate tool name format (alphanumeric, hyphens, underscores only)
|
|
119
|
+
const validNamePattern = /^[a-zA-Z0-9_-]+$/;
|
|
120
|
+
if (!validNamePattern.test(name)) {
|
|
121
|
+
throw new Error(`Invalid tool name format: '${name}'. Tool names must contain only alphanumeric characters, hyphens, and underscores. ` +
|
|
122
|
+
`Examples: 'calculate-tax', 'get_weather', 'sendEmail123'`);
|
|
123
|
+
}
|
|
124
|
+
// Validate tool object
|
|
125
|
+
if (!tool || typeof tool !== "object") {
|
|
126
|
+
throw new Error(`Tool '${name}' must be an object with description and execute properties. Received: ${typeof tool}`);
|
|
127
|
+
}
|
|
128
|
+
// Validate description
|
|
129
|
+
if (!tool.description ||
|
|
130
|
+
typeof tool.description !== "string" ||
|
|
131
|
+
tool.description.trim() === "") {
|
|
132
|
+
throw new Error(`Tool '${name}' must have a non-empty description string. ` +
|
|
133
|
+
`Example: { description: "Calculates mathematical expressions", execute: async (params) => {...} }`);
|
|
134
|
+
}
|
|
135
|
+
// Validate execute function with signature guidance
|
|
136
|
+
if (typeof tool.execute !== "function") {
|
|
137
|
+
throw new Error(`Tool '${name}' must have an execute function. ` +
|
|
138
|
+
`Expected signature: async (params?: any) => Promise<any>. ` +
|
|
139
|
+
`Received: ${typeof tool.execute}. ` +
|
|
140
|
+
`Example: { execute: async (params) => { return { success: true, data: result }; } }`);
|
|
141
|
+
}
|
|
142
|
+
// Validate parameters schema if provided - support both Zod and custom schemas
|
|
143
|
+
if (tool.parameters) {
|
|
144
|
+
if (typeof tool.parameters !== "object") {
|
|
145
|
+
throw new Error(`Tool '${name}' parameters must be an object. ` +
|
|
146
|
+
`Received: ${typeof tool.parameters}`);
|
|
147
|
+
}
|
|
148
|
+
// Check for common schema validation methods (Zod uses 'parse', others might use 'validate')
|
|
149
|
+
const params = tool.parameters;
|
|
150
|
+
const hasValidationMethod = typeof params.parse === "function" ||
|
|
151
|
+
typeof params.validate === "function" ||
|
|
152
|
+
"_def" in params; // Zod schemas have _def property
|
|
153
|
+
if (!hasValidationMethod) {
|
|
154
|
+
const errorMessage = typeof params.parse === "function" || "_def" in params
|
|
155
|
+
? `Tool '${name}' has a Zod-like schema but validation failed. Ensure it's a valid Zod schema: z.object({ ... })`
|
|
156
|
+
: typeof params.validate === "function"
|
|
157
|
+
? `Tool '${name}' has a validate method but it may not be callable. Ensure: { parameters: { validate: (data) => { ... } } }`
|
|
158
|
+
: `Tool '${name}' parameters must be a schema object with validation. ` +
|
|
159
|
+
`Supported formats:\n` +
|
|
160
|
+
`• Zod schema: { parameters: z.object({ value: z.string() }) }\n` +
|
|
161
|
+
`• Custom schema: { parameters: { validate: (data) => { ... } } }\n` +
|
|
162
|
+
`• Custom schema: { parameters: { parse: (data) => { ... } } }`;
|
|
163
|
+
throw new Error(errorMessage);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// Validate description length for better UX
|
|
167
|
+
validateDescriptionLength(name, tool.description);
|
|
168
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { ZodType, ZodTypeDef } from "zod";
|
|
2
|
+
import type { Tool, Schema } from "ai";
|
|
3
|
+
import type { AIProviderName, AnalyticsData, EvaluationData } from "../core/types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Generate function options interface - Primary method for content generation
|
|
6
|
+
* Future-ready for multi-modal capabilities while maintaining text focus
|
|
7
|
+
*/
|
|
8
|
+
export interface GenerateOptions {
|
|
9
|
+
input: {
|
|
10
|
+
text: string;
|
|
11
|
+
};
|
|
12
|
+
output?: {
|
|
13
|
+
format?: "text" | "structured" | "json";
|
|
14
|
+
};
|
|
15
|
+
provider?: AIProviderName | string;
|
|
16
|
+
model?: string;
|
|
17
|
+
temperature?: number;
|
|
18
|
+
maxTokens?: number;
|
|
19
|
+
systemPrompt?: string;
|
|
20
|
+
schema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>;
|
|
21
|
+
tools?: Record<string, Tool>;
|
|
22
|
+
timeout?: number | string;
|
|
23
|
+
disableTools?: boolean;
|
|
24
|
+
enableEvaluation?: boolean;
|
|
25
|
+
enableAnalytics?: boolean;
|
|
26
|
+
context?: Record<string, any>;
|
|
27
|
+
evaluationDomain?: string;
|
|
28
|
+
toolUsageContext?: string;
|
|
29
|
+
conversationHistory?: Array<{
|
|
30
|
+
role: string;
|
|
31
|
+
content: string;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Generate function result interface - Primary output format
|
|
36
|
+
* Future-ready for multi-modal outputs while maintaining text focus
|
|
37
|
+
*/
|
|
38
|
+
export interface GenerateResult {
|
|
39
|
+
content: string;
|
|
40
|
+
outputs?: {
|
|
41
|
+
text: string;
|
|
42
|
+
};
|
|
43
|
+
provider?: string;
|
|
44
|
+
model?: string;
|
|
45
|
+
usage?: {
|
|
46
|
+
inputTokens: number;
|
|
47
|
+
outputTokens: number;
|
|
48
|
+
totalTokens: number;
|
|
49
|
+
};
|
|
50
|
+
responseTime?: number;
|
|
51
|
+
toolCalls?: Array<{
|
|
52
|
+
toolCallId: string;
|
|
53
|
+
toolName: string;
|
|
54
|
+
args: Record<string, any>;
|
|
55
|
+
}>;
|
|
56
|
+
toolResults?: any[];
|
|
57
|
+
toolsUsed?: string[];
|
|
58
|
+
toolExecutions?: Array<{
|
|
59
|
+
name: string;
|
|
60
|
+
input: Record<string, any>;
|
|
61
|
+
output: any;
|
|
62
|
+
duration: number;
|
|
63
|
+
}>;
|
|
64
|
+
enhancedWithTools?: boolean;
|
|
65
|
+
availableTools?: Array<{
|
|
66
|
+
name: string;
|
|
67
|
+
description: string;
|
|
68
|
+
parameters: Record<string, any>;
|
|
69
|
+
}>;
|
|
70
|
+
analytics?: AnalyticsData;
|
|
71
|
+
evaluation?: EvaluationData;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Enhanced provider interface with generate method
|
|
75
|
+
*/
|
|
76
|
+
export interface EnhancedProvider {
|
|
77
|
+
generate(options: GenerateOptions): Promise<GenerateResult>;
|
|
78
|
+
getName(): string;
|
|
79
|
+
isAvailable(): Promise<boolean>;
|
|
80
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|