@juspay/neurolink 2.1.0 → 3.0.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 +29 -9
- package/README.md +17 -39
- package/dist/cli/index.js +28 -16
- package/dist/lib/mcp/plugins/filesystem-mcp.d.ts +1 -1
- package/dist/lib/providers/agent-enhanced-provider.js +61 -53
- package/dist/lib/providers/amazonBedrock.js +11 -7
- package/dist/lib/providers/anthropic.js +13 -11
- package/dist/lib/providers/azureOpenAI.js +10 -10
- package/dist/lib/providers/googleAIStudio.js +14 -7
- package/dist/lib/providers/googleVertexAI.js +14 -7
- package/dist/lib/providers/huggingFace.js +11 -7
- package/dist/lib/providers/mistralAI.js +11 -7
- package/dist/lib/providers/ollama.js +12 -4
- package/dist/lib/providers/openAI.js +11 -7
- package/dist/lib/providers/timeout-wrapper.d.ts +2 -2
- package/dist/lib/providers/timeout-wrapper.js +3 -3
- package/dist/lib/proxy/proxy-fetch.d.ts +18 -0
- package/dist/lib/proxy/proxy-fetch.js +64 -0
- package/dist/lib/utils/timeout.d.ts +4 -4
- package/dist/lib/utils/timeout.js +42 -34
- package/dist/mcp/plugins/filesystem-mcp.d.ts +1 -1
- package/dist/mcp/plugins/filesystem-mcp.js +1 -1
- package/dist/providers/agent-enhanced-provider.js +61 -53
- package/dist/providers/amazonBedrock.js +11 -7
- package/dist/providers/anthropic.js +13 -11
- package/dist/providers/azureOpenAI.js +10 -10
- package/dist/providers/googleAIStudio.js +14 -7
- package/dist/providers/googleVertexAI.js +14 -7
- package/dist/providers/huggingFace.js +11 -7
- package/dist/providers/mistralAI.js +11 -7
- package/dist/providers/ollama.js +12 -4
- package/dist/providers/openAI.js +11 -7
- package/dist/providers/timeout-wrapper.d.ts +2 -2
- package/dist/providers/timeout-wrapper.js +3 -3
- package/dist/proxy/proxy-fetch.d.ts +18 -0
- package/dist/proxy/proxy-fetch.js +64 -0
- package/dist/utils/timeout.d.ts +4 -4
- package/dist/utils/timeout.js +42 -34
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,35 +1,55 @@
|
|
|
1
|
-
# [
|
|
1
|
+
# [3.0.0](https://github.com/juspay/neurolink/compare/v2.1.0...v3.0.0) (2025-07-01)
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
### Features
|
|
5
5
|
|
|
6
|
-
* **
|
|
6
|
+
* **proxy:** add comprehensive enterprise proxy support across all providers ([9668e67](https://github.com/juspay/neurolink/commit/9668e67dfaa27831ba85d45fdf5b7739de902b28))
|
|
7
7
|
|
|
8
|
-
# [2.0.0](https://github.com/juspay/neurolink/compare/v1.11.3...v2.0.0) (2025-06-28)
|
|
9
8
|
|
|
9
|
+
### BREAKING CHANGES
|
|
10
|
+
|
|
11
|
+
* **proxy:** None - fully backward compatible
|
|
12
|
+
|
|
13
|
+
Files modified:
|
|
14
|
+
- docs/ENTERPRISE-PROXY-SETUP.md (NEW) - Comprehensive enterprise proxy guide
|
|
15
|
+
- docs/PROVIDER-CONFIGURATION.md - Added proxy configuration section
|
|
16
|
+
- docs/CLI-GUIDE.md - Added proxy environment variables documentation
|
|
17
|
+
- docs/ENVIRONMENT-VARIABLES.md - Added proxy configuration examples
|
|
18
|
+
- docs/TROUBLESHOOTING.md - Added proxy troubleshooting procedures
|
|
19
|
+
- .env.example - Added proxy environment variables
|
|
20
|
+
- memory-bank/ - Updated with proxy implementation milestone
|
|
21
|
+
- .clinerules - Added proxy success patterns
|
|
22
|
+
- CHANGELOG.md - Added v2.2.0 proxy support entry
|
|
23
|
+
- package.json - Updated description with enterprise features
|
|
24
|
+
- README.md - Removed outdated content
|
|
25
|
+
|
|
26
|
+
# [2.1.0](https://github.com/juspay/neurolink/compare/v2.0.0...v2.1.0) (2025-06-29)
|
|
10
27
|
|
|
11
28
|
### Features
|
|
12
29
|
|
|
13
|
-
|
|
30
|
+
- **timeout:** add comprehensive timeout support for all AI providers ([8610f4a](https://github.com/juspay/neurolink/commit/8610f4ade418345b0395ab72af6e675f6eec6f93))
|
|
14
31
|
|
|
32
|
+
# [2.0.0](https://github.com/juspay/neurolink/compare/v1.11.3...v2.0.0) (2025-06-28)
|
|
33
|
+
|
|
34
|
+
### Features
|
|
35
|
+
|
|
36
|
+
- **cli:** add command variations and stream agent support ([5fc4c26](https://github.com/juspay/neurolink/commit/5fc4c26b23bd189be52272521bdd2ca40dd55837))
|
|
15
37
|
|
|
16
38
|
### BREAKING CHANGES
|
|
17
39
|
|
|
18
|
-
|
|
40
|
+
- **cli:** 'generate-text' command is deprecated and will be removed in v2.0
|
|
19
41
|
|
|
20
42
|
## [1.11.3](https://github.com/juspay/neurolink/compare/v1.11.2...v1.11.3) (2025-06-22)
|
|
21
43
|
|
|
22
|
-
|
|
23
44
|
### Bug Fixes
|
|
24
45
|
|
|
25
|
-
|
|
46
|
+
- resolve MCP external tools returning raw JSON instead of human-readable responses ([921a12b](https://github.com/juspay/neurolink/commit/921a12b5b31ca96bbfe3f1db05001ddb84470e14))
|
|
26
47
|
|
|
27
48
|
## [1.11.2](https://github.com/juspay/neurolink/compare/v1.11.1...v1.11.2) (2025-06-22)
|
|
28
49
|
|
|
29
|
-
|
|
30
50
|
### Bug Fixes
|
|
31
51
|
|
|
32
|
-
|
|
52
|
+
- **ci:** refactor auto-converted Node.js scripts ([4088888](https://github.com/juspay/neurolink/commit/408888863f8223e64269423412f5c79a35ddfe36))
|
|
33
53
|
|
|
34
54
|
## [1.11.1](https://github.com/juspay/neurolink/compare/v1.11.0...v1.11.1) (2025-06-21)
|
|
35
55
|
|
package/README.md
CHANGED
|
@@ -11,28 +11,6 @@
|
|
|
11
11
|
|
|
12
12
|
**NeuroLink** unifies OpenAI, Bedrock, Vertex AI, Google AI Studio, Anthropic, Azure OpenAI, Hugging Face, Ollama, and Mistral AI with intelligent fallback and streaming support. Available as both a **programmatic SDK** and **professional CLI tool**. Extracted from production use at Juspay.
|
|
13
13
|
|
|
14
|
-
## 🔥 **Latest Breakthrough: Full MCP Tool Integration Operational** (June 21, 2025)
|
|
15
|
-
|
|
16
|
-
**MAJOR SUCCESS**: All blocking TypeScript compilation errors resolved + Complete CLI MCP integration achieved!
|
|
17
|
-
|
|
18
|
-
✅ **Function Calling Ready**: AI can now execute real filesystem operations, data analysis, and system commands
|
|
19
|
-
✅ **Production Validated**: 23,230+ token MCP context loading confirmed via comprehensive CLI testing
|
|
20
|
-
✅ **Zero Build Errors**: Clean TypeScript compilation after resolving all 13 blocking errors
|
|
21
|
-
✅ **CLI Tool Integration**: Both `generate`/`gen` and `agent-generate` commands use full MCP capabilities
|
|
22
|
-
✅ **Backward Compatible**: Tools enabled by default with opt-out flag for traditional usage
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
# NEW: AI can now access your filesystem and execute tools (use preferred commands)
|
|
26
|
-
npx @juspay/neurolink generate "List files in this directory" --provider google-ai
|
|
27
|
-
|
|
28
|
-
# Alternative shorter command
|
|
29
|
-
npx @juspay/neurolink gen "List files in this directory" --provider google-ai
|
|
30
|
-
|
|
31
|
-
# ⚠️ DEPRECATED: generate-text will be removed in v2.0 (use 'generate' or 'gen' instead)
|
|
32
|
-
# This command shows a deprecation warning and is kept for backward compatibility only
|
|
33
|
-
npx @juspay/neurolink generate-text "List files in this directory" --provider google-ai
|
|
34
|
-
```
|
|
35
|
-
|
|
36
14
|
## 🚀 Quick Start
|
|
37
15
|
|
|
38
16
|
### Install & Run (2 minutes)
|
|
@@ -61,7 +39,7 @@ import { createBestAIProvider } from "@juspay/neurolink";
|
|
|
61
39
|
const provider = createBestAIProvider();
|
|
62
40
|
const result = await provider.generateText({
|
|
63
41
|
prompt: "Write a haiku about programming",
|
|
64
|
-
timeout:
|
|
42
|
+
timeout: "30s", // Optional: Set custom timeout (default: 30s)
|
|
65
43
|
});
|
|
66
44
|
|
|
67
45
|
console.log(result.text);
|
|
@@ -101,14 +79,14 @@ npx @juspay/neurolink status
|
|
|
101
79
|
|
|
102
80
|
## 🛠️ MCP Integration Status (v1.11.1) ✅ **PRODUCTION READY**
|
|
103
81
|
|
|
104
|
-
| Component | Status | Description
|
|
105
|
-
| ------------------- | ------------------ |
|
|
106
|
-
| Built-in Tools | ✅ **Working** | Time tool, utilities - fully functional
|
|
107
|
-
| External Discovery | ✅ **Working** | 58+ MCP servers auto-discovered from all AI tools
|
|
108
|
-
| Tool Execution | ✅ **Working** | Real-time AI tool calling with built-in tools
|
|
82
|
+
| Component | Status | Description |
|
|
83
|
+
| ------------------- | ------------------ | ---------------------------------------------------------- |
|
|
84
|
+
| Built-in Tools | ✅ **Working** | Time tool, utilities - fully functional |
|
|
85
|
+
| External Discovery | ✅ **Working** | 58+ MCP servers auto-discovered from all AI tools |
|
|
86
|
+
| Tool Execution | ✅ **Working** | Real-time AI tool calling with built-in tools |
|
|
109
87
|
| **External Tools** | ✅ **SOLVED** | **Two-step tool calling fixed - human-readable responses** |
|
|
110
|
-
| **CLI Integration** | ✅ **READY** | **Production-ready AI assistant with external tools**
|
|
111
|
-
| External Activation | 🔧 **Development** | Discovery complete, activation protocol in progress
|
|
88
|
+
| **CLI Integration** | ✅ **READY** | **Production-ready AI assistant with external tools** |
|
|
89
|
+
| External Activation | 🔧 **Development** | Discovery complete, activation protocol in progress |
|
|
112
90
|
|
|
113
91
|
### ✅ Quick MCP Test (v1.7.1)
|
|
114
92
|
|
|
@@ -213,16 +191,16 @@ npx @juspay/neurolink batch prompts.txt --timeout 45s --output results.json
|
|
|
213
191
|
export const POST: RequestHandler = async ({ request }) => {
|
|
214
192
|
const { message } = await request.json();
|
|
215
193
|
const provider = createBestAIProvider();
|
|
216
|
-
|
|
194
|
+
|
|
217
195
|
try {
|
|
218
|
-
const result = await provider.streamText({
|
|
196
|
+
const result = await provider.streamText({
|
|
219
197
|
prompt: message,
|
|
220
|
-
timeout:
|
|
198
|
+
timeout: "2m", // 2 minutes for streaming
|
|
221
199
|
});
|
|
222
200
|
return new Response(result.toReadableStream());
|
|
223
201
|
} catch (error) {
|
|
224
|
-
if (error.name ===
|
|
225
|
-
return new Response(
|
|
202
|
+
if (error.name === "TimeoutError") {
|
|
203
|
+
return new Response("Request timed out", { status: 408 });
|
|
226
204
|
}
|
|
227
205
|
throw error;
|
|
228
206
|
}
|
|
@@ -232,12 +210,12 @@ export const POST: RequestHandler = async ({ request }) => {
|
|
|
232
210
|
export async function POST(request: NextRequest) {
|
|
233
211
|
const { prompt } = await request.json();
|
|
234
212
|
const provider = createBestAIProvider();
|
|
235
|
-
|
|
236
|
-
const result = await provider.generateText({
|
|
213
|
+
|
|
214
|
+
const result = await provider.generateText({
|
|
237
215
|
prompt,
|
|
238
|
-
timeout: process.env.AI_TIMEOUT ||
|
|
216
|
+
timeout: process.env.AI_TIMEOUT || "30s", // Configurable timeout
|
|
239
217
|
});
|
|
240
|
-
|
|
218
|
+
|
|
241
219
|
return NextResponse.json({ text: result.text });
|
|
242
220
|
}
|
|
243
221
|
```
|
package/dist/cli/index.js
CHANGED
|
@@ -268,7 +268,7 @@ const cli = yargs(args)
|
|
|
268
268
|
.example('$0 generate-text "Hello world" --disable-tools', "Use without tool integration"), async (argv) => {
|
|
269
269
|
// Check if generate-text was used specifically (for deprecation warning)
|
|
270
270
|
const usedCommand = argv._[0];
|
|
271
|
-
if (usedCommand ===
|
|
271
|
+
if (usedCommand === "generate-text" && !argv.quiet) {
|
|
272
272
|
console.warn(chalk.yellow('⚠️ Warning: "generate-text" is deprecated. Use "generate" or "gen" instead for multimodal support.'));
|
|
273
273
|
}
|
|
274
274
|
let originalConsole = {};
|
|
@@ -331,20 +331,26 @@ const cli = yargs(args)
|
|
|
331
331
|
spinner.succeed(chalk.green("✅ Text generated successfully!"));
|
|
332
332
|
}
|
|
333
333
|
// Handle both AgentEnhancedProvider (AI SDK) and standard NeuroLink SDK responses
|
|
334
|
-
const responseText = result
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
334
|
+
const responseText = result
|
|
335
|
+
? result.text || result.content || ""
|
|
336
|
+
: "";
|
|
337
|
+
const responseUsage = result
|
|
338
|
+
? result.usage || {
|
|
339
|
+
promptTokens: 0,
|
|
340
|
+
completionTokens: 0,
|
|
341
|
+
totalTokens: 0,
|
|
342
|
+
}
|
|
343
|
+
: { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
|
|
340
344
|
if (argv.format === "json") {
|
|
341
345
|
const jsonOutput = {
|
|
342
346
|
content: responseText,
|
|
343
|
-
provider: result
|
|
347
|
+
provider: result
|
|
348
|
+
? result.provider || argv.provider
|
|
349
|
+
: argv.provider,
|
|
344
350
|
usage: responseUsage,
|
|
345
|
-
responseTime: result ?
|
|
346
|
-
toolCalls: result ?
|
|
347
|
-
toolResults: result ?
|
|
351
|
+
responseTime: result ? result.responseTime || 0 : 0,
|
|
352
|
+
toolCalls: result ? result.toolCalls || [] : [],
|
|
353
|
+
toolResults: result ? result.toolResults || [] : [],
|
|
348
354
|
};
|
|
349
355
|
process.stdout.write(JSON.stringify(jsonOutput, null, 2) + "\n");
|
|
350
356
|
}
|
|
@@ -354,7 +360,9 @@ const cli = yargs(args)
|
|
|
354
360
|
console.log("\n" + responseText + "\n");
|
|
355
361
|
}
|
|
356
362
|
// Show tool calls if any
|
|
357
|
-
if (result &&
|
|
363
|
+
if (result &&
|
|
364
|
+
result.toolCalls &&
|
|
365
|
+
result.toolCalls.length > 0) {
|
|
358
366
|
console.log(chalk.blue("🔧 Tools Called:"));
|
|
359
367
|
for (const toolCall of result.toolCalls) {
|
|
360
368
|
console.log(`- ${toolCall.toolName}`);
|
|
@@ -363,7 +371,9 @@ const cli = yargs(args)
|
|
|
363
371
|
console.log();
|
|
364
372
|
}
|
|
365
373
|
// Show tool results if any
|
|
366
|
-
if (result &&
|
|
374
|
+
if (result &&
|
|
375
|
+
result.toolResults &&
|
|
376
|
+
result.toolResults.length > 0) {
|
|
367
377
|
console.log(chalk.blue("📋 Tool Results:"));
|
|
368
378
|
for (const toolResult of result.toolResults) {
|
|
369
379
|
console.log(`- ${toolResult.toolCallId}`);
|
|
@@ -372,9 +382,11 @@ const cli = yargs(args)
|
|
|
372
382
|
console.log();
|
|
373
383
|
}
|
|
374
384
|
console.log(JSON.stringify({
|
|
375
|
-
provider: result
|
|
385
|
+
provider: result
|
|
386
|
+
? result.provider || argv.provider
|
|
387
|
+
: argv.provider,
|
|
376
388
|
usage: responseUsage,
|
|
377
|
-
responseTime: result ?
|
|
389
|
+
responseTime: result ? result.responseTime || 0 : 0,
|
|
378
390
|
}, null, 2));
|
|
379
391
|
if (responseUsage.totalTokens) {
|
|
380
392
|
console.log(chalk.blue(`ℹ️ ${responseUsage.totalTokens} tokens used`));
|
|
@@ -501,7 +513,7 @@ const cli = yargs(args)
|
|
|
501
513
|
const DELAY_MS = 50;
|
|
502
514
|
for (let i = 0; i < text.length; i += CHUNK_SIZE) {
|
|
503
515
|
process.stdout.write(text.slice(i, i + CHUNK_SIZE));
|
|
504
|
-
await new Promise(resolve => setTimeout(resolve, DELAY_MS)); // Small delay
|
|
516
|
+
await new Promise((resolve) => setTimeout(resolve, DELAY_MS)); // Small delay
|
|
505
517
|
}
|
|
506
518
|
if (!argv.quiet) {
|
|
507
519
|
process.stdout.write("\n");
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Implements the new MCP contract with security sandbox
|
|
4
4
|
* Based on research document recommendations
|
|
5
5
|
*/
|
|
6
|
-
import { MCP, MCPMetadata, ExecutionContext } from "../contracts/mcp-contract.js";
|
|
6
|
+
import { MCP, type MCPMetadata, type ExecutionContext } from "../contracts/mcp-contract.js";
|
|
7
7
|
/**
|
|
8
8
|
* FileSystem MCP Configuration
|
|
9
9
|
*/
|
|
@@ -66,14 +66,15 @@ export class AgentEnhancedProvider {
|
|
|
66
66
|
try {
|
|
67
67
|
mcpLogger.info("[AgentEnhancedProvider] Initializing MCP integration...");
|
|
68
68
|
this.mcpSystem = new UnifiedMCPSystem({
|
|
69
|
-
configPath: this.config.mcpDiscoveryOptions?.configFiles?.[0] ||
|
|
69
|
+
configPath: this.config.mcpDiscoveryOptions?.configFiles?.[0] ||
|
|
70
|
+
".mcp-config.json",
|
|
70
71
|
enableExternalServers: true,
|
|
71
72
|
enableInternalServers: true,
|
|
72
|
-
autoInitialize: false
|
|
73
|
+
autoInitialize: false,
|
|
73
74
|
});
|
|
74
75
|
// ADD TIMEOUT to prevent hanging forever
|
|
75
76
|
const initPromise = this.mcpSystem.initialize();
|
|
76
|
-
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error(
|
|
77
|
+
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("MCP initialization timeout after 15 seconds")), this.config.mcpInitTimeoutMs || 15000));
|
|
77
78
|
await Promise.race([initPromise, timeoutPromise]);
|
|
78
79
|
this.mcpInitialized = true;
|
|
79
80
|
mcpLogger.info("[AgentEnhancedProvider] MCP integration initialized successfully");
|
|
@@ -101,10 +102,13 @@ export class AgentEnhancedProvider {
|
|
|
101
102
|
return directTools;
|
|
102
103
|
}
|
|
103
104
|
// Get MCP tools if available
|
|
104
|
-
|
|
105
|
+
const mcpTools = {};
|
|
105
106
|
try {
|
|
106
107
|
// Skip if MCP failed to initialize or is still initializing
|
|
107
|
-
if (this.mcpInitFailed ||
|
|
108
|
+
if (this.mcpInitFailed ||
|
|
109
|
+
this.mcpInitializing ||
|
|
110
|
+
!this.mcpInitialized ||
|
|
111
|
+
!this.mcpSystem) {
|
|
108
112
|
return directTools;
|
|
109
113
|
}
|
|
110
114
|
const mcpToolInfos = await this.mcpSystem.listTools();
|
|
@@ -123,7 +127,7 @@ export class AgentEnhancedProvider {
|
|
|
123
127
|
? new AbortController()
|
|
124
128
|
: undefined;
|
|
125
129
|
if (toolAbortController && toolTimeout) {
|
|
126
|
-
const timeoutMs = typeof toolTimeout ===
|
|
130
|
+
const timeoutMs = typeof toolTimeout === "string"
|
|
127
131
|
? parseTimeout(toolTimeout)
|
|
128
132
|
: toolTimeout;
|
|
129
133
|
timeoutId = setTimeout(() => {
|
|
@@ -131,31 +135,35 @@ export class AgentEnhancedProvider {
|
|
|
131
135
|
}, timeoutMs);
|
|
132
136
|
}
|
|
133
137
|
const context = {
|
|
134
|
-
sessionId:
|
|
135
|
-
userId:
|
|
138
|
+
sessionId: "cli-session",
|
|
139
|
+
userId: "cli-user",
|
|
136
140
|
secureFS: {
|
|
137
141
|
readFile: async (path, encoding) => {
|
|
138
|
-
const fs = await import(
|
|
139
|
-
return encoding
|
|
142
|
+
const fs = await import("fs/promises");
|
|
143
|
+
return encoding
|
|
144
|
+
? fs.readFile(path, {
|
|
145
|
+
encoding: encoding,
|
|
146
|
+
})
|
|
147
|
+
: fs.readFile(path);
|
|
140
148
|
},
|
|
141
149
|
writeFile: async (path, content) => {
|
|
142
|
-
const fs = await import(
|
|
150
|
+
const fs = await import("fs/promises");
|
|
143
151
|
await fs.writeFile(path, content);
|
|
144
152
|
},
|
|
145
153
|
readdir: async (path) => {
|
|
146
|
-
const fs = await import(
|
|
154
|
+
const fs = await import("fs/promises");
|
|
147
155
|
return fs.readdir(path);
|
|
148
156
|
},
|
|
149
157
|
stat: async (path) => {
|
|
150
|
-
const fs = await import(
|
|
158
|
+
const fs = await import("fs/promises");
|
|
151
159
|
return fs.stat(path);
|
|
152
160
|
},
|
|
153
161
|
mkdir: async (path, options) => {
|
|
154
|
-
const fs = await import(
|
|
162
|
+
const fs = await import("fs/promises");
|
|
155
163
|
await fs.mkdir(path, options);
|
|
156
164
|
},
|
|
157
165
|
exists: async (path) => {
|
|
158
|
-
const fs = await import(
|
|
166
|
+
const fs = await import("fs/promises");
|
|
159
167
|
try {
|
|
160
168
|
await fs.access(path);
|
|
161
169
|
return true;
|
|
@@ -163,34 +171,34 @@ export class AgentEnhancedProvider {
|
|
|
163
171
|
catch {
|
|
164
172
|
return false;
|
|
165
173
|
}
|
|
166
|
-
}
|
|
174
|
+
},
|
|
167
175
|
},
|
|
168
176
|
path: {
|
|
169
177
|
join: (...paths) => {
|
|
170
|
-
const path = require(
|
|
178
|
+
const path = require("path");
|
|
171
179
|
return path.join(...paths);
|
|
172
180
|
},
|
|
173
181
|
resolve: (...paths) => {
|
|
174
|
-
const path = require(
|
|
182
|
+
const path = require("path");
|
|
175
183
|
return path.resolve(...paths);
|
|
176
184
|
},
|
|
177
185
|
relative: (from, to) => {
|
|
178
|
-
const path = require(
|
|
186
|
+
const path = require("path");
|
|
179
187
|
return path.relative(from, to);
|
|
180
188
|
},
|
|
181
189
|
dirname: (path) => {
|
|
182
|
-
const pathLib = require(
|
|
190
|
+
const pathLib = require("path");
|
|
183
191
|
return pathLib.dirname(path);
|
|
184
192
|
},
|
|
185
193
|
basename: (path, ext) => {
|
|
186
|
-
const pathLib = require(
|
|
194
|
+
const pathLib = require("path");
|
|
187
195
|
return pathLib.basename(path, ext);
|
|
188
|
-
}
|
|
196
|
+
},
|
|
189
197
|
},
|
|
190
|
-
grantedPermissions: [
|
|
198
|
+
grantedPermissions: ["read", "write", "execute"],
|
|
191
199
|
log: (level, message, data) => {
|
|
192
200
|
const logFn = mcpLogger[level];
|
|
193
|
-
if (typeof logFn ===
|
|
201
|
+
if (typeof logFn === "function") {
|
|
194
202
|
if (data) {
|
|
195
203
|
logFn(`${message} ${JSON.stringify(data)}`);
|
|
196
204
|
}
|
|
@@ -198,7 +206,7 @@ export class AgentEnhancedProvider {
|
|
|
198
206
|
logFn(message);
|
|
199
207
|
}
|
|
200
208
|
}
|
|
201
|
-
}
|
|
209
|
+
},
|
|
202
210
|
};
|
|
203
211
|
const toolPromise = this.mcpSystem.executeTool(toolInfo.name, args, context);
|
|
204
212
|
let result;
|
|
@@ -207,10 +215,10 @@ export class AgentEnhancedProvider {
|
|
|
207
215
|
result = await Promise.race([
|
|
208
216
|
toolPromise,
|
|
209
217
|
new Promise((_, reject) => {
|
|
210
|
-
toolAbortController.signal.addEventListener(
|
|
218
|
+
toolAbortController.signal.addEventListener("abort", () => {
|
|
211
219
|
reject(new Error(`Tool ${toolInfo.name} timed out after ${this.config.toolExecutionTimeout}`));
|
|
212
220
|
});
|
|
213
|
-
})
|
|
221
|
+
}),
|
|
214
222
|
]);
|
|
215
223
|
}
|
|
216
224
|
else {
|
|
@@ -230,7 +238,7 @@ export class AgentEnhancedProvider {
|
|
|
230
238
|
mcpLogger.error(`MCP tool ${toolInfo.name} execution failed:`, error);
|
|
231
239
|
throw error;
|
|
232
240
|
}
|
|
233
|
-
}
|
|
241
|
+
},
|
|
234
242
|
};
|
|
235
243
|
}
|
|
236
244
|
mcpLogger.info(`[AgentEnhancedProvider] Loaded ${Object.keys(mcpTools).length} MCP tools`);
|
|
@@ -246,22 +254,20 @@ export class AgentEnhancedProvider {
|
|
|
246
254
|
: optionsOrPrompt;
|
|
247
255
|
const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt, schema, timeout, } = options;
|
|
248
256
|
// Get combined tools (direct + MCP) if enabled
|
|
249
|
-
const tools = this.config.enableTools
|
|
250
|
-
? await this.getCombinedTools()
|
|
251
|
-
: {};
|
|
257
|
+
const tools = this.config.enableTools ? await this.getCombinedTools() : {};
|
|
252
258
|
const log = (msg, data) => {
|
|
253
|
-
mcpLogger.info(`[AgentEnhancedProvider] ${msg}`, data ? JSON.stringify(data, null, 2) :
|
|
259
|
+
mcpLogger.info(`[AgentEnhancedProvider] ${msg}`, data ? JSON.stringify(data, null, 2) : "");
|
|
254
260
|
};
|
|
255
|
-
log(
|
|
261
|
+
log("Starting text generation", {
|
|
256
262
|
prompt: prompt.substring(0, 100),
|
|
257
263
|
toolsCount: Object.keys(tools).length,
|
|
258
|
-
maxSteps: this.config.maxSteps
|
|
264
|
+
maxSteps: this.config.maxSteps,
|
|
259
265
|
});
|
|
260
266
|
try {
|
|
261
267
|
// Parse timeout if provided
|
|
262
268
|
let abortSignal;
|
|
263
269
|
if (timeout) {
|
|
264
|
-
const timeoutMs = typeof timeout ===
|
|
270
|
+
const timeoutMs = typeof timeout === "string" ? parseTimeout(timeout) : timeout;
|
|
265
271
|
if (timeoutMs !== undefined) {
|
|
266
272
|
abortSignal = AbortSignal.timeout(timeoutMs);
|
|
267
273
|
}
|
|
@@ -279,24 +285,26 @@ export class AgentEnhancedProvider {
|
|
|
279
285
|
toolChoice: this.shouldForceToolUsage(prompt) ? "required" : "auto",
|
|
280
286
|
abortSignal, // Pass abort signal for timeout support
|
|
281
287
|
});
|
|
282
|
-
log(
|
|
288
|
+
log("Generation completed", {
|
|
283
289
|
text: result.text?.substring(0, 200),
|
|
284
290
|
finishReason: result.finishReason,
|
|
285
291
|
toolCallsCount: result.toolCalls?.length || 0,
|
|
286
292
|
toolResultsCount: result.toolResults?.length || 0,
|
|
287
|
-
stepsCount: result.steps?.length || 0
|
|
293
|
+
stepsCount: result.steps?.length || 0,
|
|
288
294
|
});
|
|
289
295
|
// Check if tools were called but no final text was generated
|
|
290
|
-
if (result.finishReason ===
|
|
291
|
-
|
|
296
|
+
if (result.finishReason === "tool-calls" &&
|
|
297
|
+
!result.text &&
|
|
298
|
+
result.toolResults?.length > 0) {
|
|
299
|
+
log("Tools called but no final text generated, creating summary response");
|
|
292
300
|
try {
|
|
293
301
|
// Extract tool results and create a summary prompt
|
|
294
|
-
let toolResultsSummary =
|
|
302
|
+
let toolResultsSummary = "";
|
|
295
303
|
if (result.toolResults) {
|
|
296
304
|
for (const toolResult of result.toolResults) {
|
|
297
305
|
const resultData = toolResult.result || toolResult;
|
|
298
306
|
// Try to extract meaningful data from the result
|
|
299
|
-
if (typeof resultData ===
|
|
307
|
+
if (typeof resultData === "object" && resultData !== null) {
|
|
300
308
|
if (resultData.success && resultData.items) {
|
|
301
309
|
// This looks like a filesystem listing
|
|
302
310
|
toolResultsSummary += `Directory listing for ${resultData.path}:\n`;
|
|
@@ -311,34 +319,36 @@ export class AgentEnhancedProvider {
|
|
|
311
319
|
else {
|
|
312
320
|
toolResultsSummary += String(resultData);
|
|
313
321
|
}
|
|
314
|
-
toolResultsSummary +=
|
|
322
|
+
toolResultsSummary += "\n\n";
|
|
315
323
|
}
|
|
316
324
|
}
|
|
317
|
-
log(
|
|
325
|
+
log("Tool results extracted", {
|
|
318
326
|
summaryLength: toolResultsSummary.length,
|
|
319
|
-
preview: toolResultsSummary.substring(0, 200)
|
|
327
|
+
preview: toolResultsSummary.substring(0, 200),
|
|
320
328
|
});
|
|
321
329
|
// Create a simple, direct summary
|
|
322
330
|
const finalText = `Based on the user request "${prompt}", here's what I found:\n\n${toolResultsSummary}`;
|
|
323
|
-
log(
|
|
331
|
+
log("Final text created", {
|
|
324
332
|
textLength: finalText.length,
|
|
325
|
-
preview: finalText.substring(0, 200)
|
|
333
|
+
preview: finalText.substring(0, 200),
|
|
326
334
|
});
|
|
327
335
|
// Return result with the formatted text
|
|
328
336
|
return {
|
|
329
337
|
...result,
|
|
330
338
|
text: finalText,
|
|
331
|
-
finishReason:
|
|
339
|
+
finishReason: "stop",
|
|
332
340
|
};
|
|
333
341
|
}
|
|
334
342
|
catch (error) {
|
|
335
|
-
log(
|
|
343
|
+
log("Error in summary generation", {
|
|
344
|
+
error: error instanceof Error ? error.message : String(error),
|
|
345
|
+
});
|
|
336
346
|
// Fallback: return raw tool results
|
|
337
347
|
const fallbackText = `Tool execution completed. Raw results: ${JSON.stringify(result.toolResults, null, 2)}`;
|
|
338
348
|
return {
|
|
339
349
|
...result,
|
|
340
350
|
text: fallbackText,
|
|
341
|
-
finishReason:
|
|
351
|
+
finishReason: "stop",
|
|
342
352
|
};
|
|
343
353
|
}
|
|
344
354
|
}
|
|
@@ -356,14 +366,12 @@ export class AgentEnhancedProvider {
|
|
|
356
366
|
: optionsOrPrompt;
|
|
357
367
|
const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt, timeout, } = options;
|
|
358
368
|
// Get combined tools (direct + MCP) if enabled
|
|
359
|
-
const tools = this.config.enableTools
|
|
360
|
-
? await this.getCombinedTools()
|
|
361
|
-
: {};
|
|
369
|
+
const tools = this.config.enableTools ? await this.getCombinedTools() : {};
|
|
362
370
|
try {
|
|
363
371
|
// Parse timeout if provided
|
|
364
372
|
let abortSignal;
|
|
365
373
|
if (timeout) {
|
|
366
|
-
const timeoutMs = typeof timeout ===
|
|
374
|
+
const timeoutMs = typeof timeout === "string" ? parseTimeout(timeout) : timeout;
|
|
367
375
|
if (timeoutMs !== undefined) {
|
|
368
376
|
abortSignal = AbortSignal.timeout(timeoutMs);
|
|
369
377
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createAmazonBedrock } from "@ai-sdk/amazon-bedrock";
|
|
2
2
|
import { streamText, generateText, Output, } from "ai";
|
|
3
3
|
import { logger } from "../utils/logger.js";
|
|
4
|
-
import { createTimeoutController, TimeoutError, getDefaultTimeout } from "../utils/timeout.js";
|
|
4
|
+
import { createTimeoutController, TimeoutError, getDefaultTimeout, } from "../utils/timeout.js";
|
|
5
5
|
// Default system context
|
|
6
6
|
const DEFAULT_SYSTEM_CONTEXT = {
|
|
7
7
|
systemPrompt: "You are a helpful AI assistant.",
|
|
@@ -129,7 +129,7 @@ export class AmazonBedrock {
|
|
|
129
129
|
const options = typeof optionsOrPrompt === "string"
|
|
130
130
|
? { prompt: optionsOrPrompt }
|
|
131
131
|
: optionsOrPrompt;
|
|
132
|
-
const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema, timeout = getDefaultTimeout(provider,
|
|
132
|
+
const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema, timeout = getDefaultTimeout(provider, "stream"), } = options;
|
|
133
133
|
// Use schema from options or fallback parameter
|
|
134
134
|
const finalSchema = schema || analysisSchema;
|
|
135
135
|
logger.debug(`[${functionTag}] Stream request started`, {
|
|
@@ -141,7 +141,7 @@ export class AmazonBedrock {
|
|
|
141
141
|
timeout,
|
|
142
142
|
});
|
|
143
143
|
// Create timeout controller if timeout is specified
|
|
144
|
-
const timeoutController = createTimeoutController(timeout, provider,
|
|
144
|
+
const timeoutController = createTimeoutController(timeout, provider, "stream");
|
|
145
145
|
const streamOptions = {
|
|
146
146
|
model: this.model,
|
|
147
147
|
prompt: prompt,
|
|
@@ -149,7 +149,9 @@ export class AmazonBedrock {
|
|
|
149
149
|
temperature,
|
|
150
150
|
maxTokens,
|
|
151
151
|
// Add abort signal if available
|
|
152
|
-
...(timeoutController && {
|
|
152
|
+
...(timeoutController && {
|
|
153
|
+
abortSignal: timeoutController.controller.signal,
|
|
154
|
+
}),
|
|
153
155
|
onError: (event) => {
|
|
154
156
|
const error = event.error;
|
|
155
157
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -234,7 +236,7 @@ export class AmazonBedrock {
|
|
|
234
236
|
const options = typeof optionsOrPrompt === "string"
|
|
235
237
|
? { prompt: optionsOrPrompt }
|
|
236
238
|
: optionsOrPrompt;
|
|
237
|
-
const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema, timeout = getDefaultTimeout(provider,
|
|
239
|
+
const { prompt, temperature = 0.7, maxTokens = 1000, systemPrompt = DEFAULT_SYSTEM_CONTEXT.systemPrompt, schema, timeout = getDefaultTimeout(provider, "generate"), } = options;
|
|
238
240
|
// Use schema from options or fallback parameter
|
|
239
241
|
const finalSchema = schema || analysisSchema;
|
|
240
242
|
logger.debug(`[${functionTag}] Generate text started`, {
|
|
@@ -247,7 +249,7 @@ export class AmazonBedrock {
|
|
|
247
249
|
timeout,
|
|
248
250
|
});
|
|
249
251
|
// Create timeout controller if timeout is specified
|
|
250
|
-
const timeoutController = createTimeoutController(timeout, provider,
|
|
252
|
+
const timeoutController = createTimeoutController(timeout, provider, "generate");
|
|
251
253
|
const generateOptions = {
|
|
252
254
|
model: this.model,
|
|
253
255
|
prompt: prompt,
|
|
@@ -255,7 +257,9 @@ export class AmazonBedrock {
|
|
|
255
257
|
temperature,
|
|
256
258
|
maxTokens,
|
|
257
259
|
// Add abort signal if available
|
|
258
|
-
...(timeoutController && {
|
|
260
|
+
...(timeoutController && {
|
|
261
|
+
abortSignal: timeoutController.controller.signal,
|
|
262
|
+
}),
|
|
259
263
|
};
|
|
260
264
|
if (finalSchema) {
|
|
261
265
|
generateOptions.experimental_output = Output.object({
|