@juspay/neurolink 9.25.2 → 9.26.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 +6 -0
- package/dist/adapters/providerImageAdapter.d.ts +3 -27
- package/dist/adapters/providerImageAdapter.js +9 -199
- package/dist/agent/directTools.d.ts +35 -3
- package/dist/agent/directTools.js +122 -0
- package/dist/cli/commands/config.d.ts +6 -6
- package/dist/context/contextCompactor.d.ts +1 -2
- package/dist/context/contextCompactor.js +7 -1
- package/dist/context/prompts/summarizationPrompt.d.ts +3 -3
- package/dist/context/prompts/summarizationPrompt.js +16 -9
- package/dist/context/stages/structuredSummarizer.d.ts +2 -2
- package/dist/context/stages/structuredSummarizer.js +80 -30
- package/dist/lib/adapters/providerImageAdapter.d.ts +3 -27
- package/dist/lib/adapters/providerImageAdapter.js +9 -199
- package/dist/lib/agent/directTools.d.ts +33 -1
- package/dist/lib/agent/directTools.js +122 -0
- package/dist/lib/context/contextCompactor.d.ts +1 -2
- package/dist/lib/context/contextCompactor.js +7 -1
- package/dist/lib/context/prompts/summarizationPrompt.d.ts +3 -3
- package/dist/lib/context/prompts/summarizationPrompt.js +16 -9
- package/dist/lib/context/stages/structuredSummarizer.d.ts +2 -2
- package/dist/lib/context/stages/structuredSummarizer.js +80 -30
- package/dist/lib/mcp/servers/agent/directToolsServer.js +2 -0
- package/dist/lib/mcp/toolRegistry.d.ts +8 -0
- package/dist/lib/mcp/toolRegistry.js +20 -0
- package/dist/lib/neurolink.d.ts +10 -0
- package/dist/lib/neurolink.js +281 -17
- package/dist/lib/providers/googleAiStudio.js +13 -7
- package/dist/lib/types/configTypes.d.ts +3 -0
- package/dist/lib/types/contextTypes.d.ts +5 -2
- package/dist/lib/types/contextTypes.js +8 -8
- package/dist/lib/types/generateTypes.d.ts +25 -0
- package/dist/lib/types/modelTypes.d.ts +2 -2
- package/dist/lib/utils/messageBuilder.js +2 -0
- package/dist/lib/utils/modelAliasResolver.d.ts +17 -0
- package/dist/lib/utils/modelAliasResolver.js +55 -0
- package/dist/lib/utils/pdfProcessor.d.ts +1 -1
- package/dist/lib/utils/pdfProcessor.js +7 -7
- package/dist/lib/utils/toolUtils.d.ts +8 -0
- package/dist/lib/utils/toolUtils.js +15 -0
- package/dist/lib/workflow/config.d.ts +24 -24
- package/dist/mcp/servers/agent/directToolsServer.js +2 -0
- package/dist/mcp/toolRegistry.d.ts +8 -0
- package/dist/mcp/toolRegistry.js +20 -0
- package/dist/neurolink.d.ts +10 -0
- package/dist/neurolink.js +281 -17
- package/dist/providers/googleAiStudio.js +13 -7
- package/dist/server/utils/validation.d.ts +2 -2
- package/dist/types/configTypes.d.ts +3 -0
- package/dist/types/contextTypes.d.ts +5 -2
- package/dist/types/contextTypes.js +8 -8
- package/dist/types/generateTypes.d.ts +25 -0
- package/dist/utils/messageBuilder.js +2 -0
- package/dist/utils/modelAliasResolver.d.ts +17 -0
- package/dist/utils/modelAliasResolver.js +54 -0
- package/dist/utils/pdfProcessor.d.ts +1 -1
- package/dist/utils/pdfProcessor.js +7 -7
- package/dist/utils/toolUtils.d.ts +8 -0
- package/dist/utils/toolUtils.js +15 -0
- package/dist/workflow/config.d.ts +82 -82
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [9.26.0](https://github.com/juspay/neurolink/compare/v9.25.2...v9.26.0) (2026-03-16)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
- **(core):** production reliability fixes, bash tool, and LiteLLM vision tests (NL-001–NL-007) ([9a915e6](https://github.com/juspay/neurolink/commit/9a915e6f00e1e54e31967e47893f3b24e40eaad9))
|
|
6
|
+
|
|
1
7
|
## [9.25.2](https://github.com/juspay/neurolink/compare/v9.25.1...v9.25.2) (2026-03-15)
|
|
2
8
|
|
|
3
9
|
### Bug Fixes
|
|
@@ -14,34 +14,10 @@ export declare class MultimodalLogger {
|
|
|
14
14
|
*/
|
|
15
15
|
export declare class ProviderImageAdapter {
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Validate image count against provider limits.
|
|
18
|
+
* Warns at 80% threshold, throws error if limit exceeded.
|
|
18
19
|
*/
|
|
19
|
-
static
|
|
20
|
-
/**
|
|
21
|
-
* Format content for OpenAI (GPT-4o format)
|
|
22
|
-
*/
|
|
23
|
-
private static formatForOpenAI;
|
|
24
|
-
/**
|
|
25
|
-
* Format content for Google AI (Gemini format)
|
|
26
|
-
*/
|
|
27
|
-
private static formatForGoogleAI;
|
|
28
|
-
/**
|
|
29
|
-
* Format content for Anthropic (Claude format)
|
|
30
|
-
*/
|
|
31
|
-
private static formatForAnthropic;
|
|
32
|
-
/**
|
|
33
|
-
* Format content for Vertex AI (model-specific routing)
|
|
34
|
-
*/
|
|
35
|
-
private static formatForVertex;
|
|
36
|
-
/**
|
|
37
|
-
* Validate image count against provider limits
|
|
38
|
-
* Warns at 80% threshold, throws error if limit exceeded
|
|
39
|
-
*/
|
|
40
|
-
private static validateImageCount;
|
|
41
|
-
/**
|
|
42
|
-
* Validate that provider and model support vision
|
|
43
|
-
*/
|
|
44
|
-
private static validateVisionSupport;
|
|
20
|
+
static validateImageCount(imageCount: number, provider: string, model?: string): void;
|
|
45
21
|
/**
|
|
46
22
|
* Convert simple images array to advanced content format
|
|
47
23
|
* @param text - Text content to include
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Provider Image Adapter - Smart routing for multimodal content
|
|
3
3
|
* Handles provider-specific image formatting and vision capability validation
|
|
4
4
|
*/
|
|
5
|
-
import { logger } from "../utils/logger.js";
|
|
6
5
|
import { ImageProcessor } from "../utils/imageProcessor.js";
|
|
6
|
+
import { logger } from "../utils/logger.js";
|
|
7
7
|
/**
|
|
8
8
|
* Simplified logger for essential error reporting only
|
|
9
9
|
*/
|
|
@@ -436,184 +436,15 @@ const VISION_CAPABILITIES = {
|
|
|
436
436
|
* Provider Image Adapter - Smart routing and formatting
|
|
437
437
|
*/
|
|
438
438
|
export class ProviderImageAdapter {
|
|
439
|
+
// NOTE: The legacy `adaptForProvider` method and its private helpers
|
|
440
|
+
// (formatForOpenAI, formatForGoogleAI, formatForAnthropic, formatForVertex,
|
|
441
|
+
// validateVisionSupport) were removed as dead code. The production image
|
|
442
|
+
// pipeline uses `convertSimpleImagesToProviderFormat` in messageBuilder.ts
|
|
443
|
+
// with Vercel AI SDK's native ImagePart format. Image count limits are
|
|
444
|
+
// enforced via the public `validateImageCount` method below.
|
|
439
445
|
/**
|
|
440
|
-
*
|
|
441
|
-
|
|
442
|
-
static async adaptForProvider(text, images, provider, model) {
|
|
443
|
-
try {
|
|
444
|
-
// Validate provider supports vision
|
|
445
|
-
this.validateVisionSupport(provider, model);
|
|
446
|
-
let adaptedPayload;
|
|
447
|
-
// Process images based on provider requirements
|
|
448
|
-
switch (provider.toLowerCase()) {
|
|
449
|
-
case "openai":
|
|
450
|
-
adaptedPayload = this.formatForOpenAI(text, images);
|
|
451
|
-
break;
|
|
452
|
-
case "azure":
|
|
453
|
-
case "azure-openai":
|
|
454
|
-
// Azure uses same format as OpenAI but validate with azure provider name
|
|
455
|
-
this.validateImageCount(images.length, "azure");
|
|
456
|
-
adaptedPayload = this.formatForOpenAI(text, images, true);
|
|
457
|
-
break;
|
|
458
|
-
case "google-ai":
|
|
459
|
-
case "google":
|
|
460
|
-
adaptedPayload = this.formatForGoogleAI(text, images);
|
|
461
|
-
break;
|
|
462
|
-
case "anthropic":
|
|
463
|
-
adaptedPayload = this.formatForAnthropic(text, images);
|
|
464
|
-
break;
|
|
465
|
-
case "vertex":
|
|
466
|
-
adaptedPayload = this.formatForVertex(text, images, model);
|
|
467
|
-
break;
|
|
468
|
-
case "ollama":
|
|
469
|
-
// Ollama uses same format as OpenAI but validate with ollama provider name
|
|
470
|
-
this.validateImageCount(images.length, "ollama");
|
|
471
|
-
adaptedPayload = this.formatForOpenAI(text, images, true);
|
|
472
|
-
break;
|
|
473
|
-
case "huggingface":
|
|
474
|
-
adaptedPayload = this.formatForOpenAI(text, images);
|
|
475
|
-
break;
|
|
476
|
-
case "sagemaker":
|
|
477
|
-
adaptedPayload = this.formatForOpenAI(text, images);
|
|
478
|
-
break;
|
|
479
|
-
case "litellm":
|
|
480
|
-
// LiteLLM uses same format as OpenAI but validate with litellm provider name
|
|
481
|
-
this.validateImageCount(images.length, "litellm");
|
|
482
|
-
adaptedPayload = this.formatForOpenAI(text, images, true);
|
|
483
|
-
break;
|
|
484
|
-
case "mistral":
|
|
485
|
-
// Mistral uses same format as OpenAI but validate with mistral provider name
|
|
486
|
-
this.validateImageCount(images.length, "mistral");
|
|
487
|
-
adaptedPayload = this.formatForOpenAI(text, images, true);
|
|
488
|
-
break;
|
|
489
|
-
case "bedrock":
|
|
490
|
-
// Bedrock uses same format as Anthropic but validate with bedrock provider name
|
|
491
|
-
this.validateImageCount(images.length, "bedrock");
|
|
492
|
-
adaptedPayload = this.formatForAnthropic(text, images, true);
|
|
493
|
-
break;
|
|
494
|
-
case "openrouter":
|
|
495
|
-
// OpenRouter routes to underlying providers, use OpenAI format
|
|
496
|
-
this.validateImageCount(images.length, "openrouter");
|
|
497
|
-
adaptedPayload = this.formatForOpenAI(text, images);
|
|
498
|
-
break;
|
|
499
|
-
default:
|
|
500
|
-
throw new Error(`Vision not supported for provider: ${provider}`);
|
|
501
|
-
}
|
|
502
|
-
return adaptedPayload;
|
|
503
|
-
}
|
|
504
|
-
catch (error) {
|
|
505
|
-
MultimodalLogger.logError("ADAPTATION", error, {
|
|
506
|
-
provider,
|
|
507
|
-
model,
|
|
508
|
-
imageCount: images.length,
|
|
509
|
-
});
|
|
510
|
-
throw error;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
/**
|
|
514
|
-
* Format content for OpenAI (GPT-4o format)
|
|
515
|
-
*/
|
|
516
|
-
static formatForOpenAI(text, images, skipValidation = false) {
|
|
517
|
-
// Validate image count before processing (unless called from another formatter)
|
|
518
|
-
if (!skipValidation) {
|
|
519
|
-
this.validateImageCount(images.length, "openai");
|
|
520
|
-
}
|
|
521
|
-
const content = [{ type: "text", text }];
|
|
522
|
-
images.forEach((image, index) => {
|
|
523
|
-
try {
|
|
524
|
-
const imageUrl = ImageProcessor.processImageForOpenAI(image);
|
|
525
|
-
content.push({
|
|
526
|
-
type: "image_url",
|
|
527
|
-
image_url: { url: imageUrl },
|
|
528
|
-
});
|
|
529
|
-
}
|
|
530
|
-
catch (error) {
|
|
531
|
-
MultimodalLogger.logError("PROCESS_IMAGE", error, {
|
|
532
|
-
index,
|
|
533
|
-
provider: "openai",
|
|
534
|
-
});
|
|
535
|
-
throw error;
|
|
536
|
-
}
|
|
537
|
-
});
|
|
538
|
-
return { messages: [{ role: "user", content }] };
|
|
539
|
-
}
|
|
540
|
-
/**
|
|
541
|
-
* Format content for Google AI (Gemini format)
|
|
542
|
-
*/
|
|
543
|
-
static formatForGoogleAI(text, images, skipValidation = false) {
|
|
544
|
-
// Validate image count before processing (unless called from another formatter)
|
|
545
|
-
if (!skipValidation) {
|
|
546
|
-
this.validateImageCount(images.length, "google-ai");
|
|
547
|
-
}
|
|
548
|
-
const parts = [{ text }];
|
|
549
|
-
images.forEach((image, index) => {
|
|
550
|
-
try {
|
|
551
|
-
const { mimeType, data } = ImageProcessor.processImageForGoogle(image);
|
|
552
|
-
parts.push({
|
|
553
|
-
inlineData: { mimeType, data },
|
|
554
|
-
});
|
|
555
|
-
}
|
|
556
|
-
catch (error) {
|
|
557
|
-
MultimodalLogger.logError("PROCESS_IMAGE", error, {
|
|
558
|
-
index,
|
|
559
|
-
provider: "google-ai",
|
|
560
|
-
});
|
|
561
|
-
throw error;
|
|
562
|
-
}
|
|
563
|
-
});
|
|
564
|
-
return { contents: [{ parts }] };
|
|
565
|
-
}
|
|
566
|
-
/**
|
|
567
|
-
* Format content for Anthropic (Claude format)
|
|
568
|
-
*/
|
|
569
|
-
static formatForAnthropic(text, images, skipValidation = false) {
|
|
570
|
-
// Validate image count before processing (unless called from another formatter)
|
|
571
|
-
if (!skipValidation) {
|
|
572
|
-
this.validateImageCount(images.length, "anthropic");
|
|
573
|
-
}
|
|
574
|
-
const content = [{ type: "text", text }];
|
|
575
|
-
images.forEach((image, index) => {
|
|
576
|
-
try {
|
|
577
|
-
const { mediaType, data } = ImageProcessor.processImageForAnthropic(image);
|
|
578
|
-
content.push({
|
|
579
|
-
type: "image",
|
|
580
|
-
source: {
|
|
581
|
-
type: "base64",
|
|
582
|
-
media_type: mediaType,
|
|
583
|
-
data,
|
|
584
|
-
},
|
|
585
|
-
});
|
|
586
|
-
}
|
|
587
|
-
catch (error) {
|
|
588
|
-
MultimodalLogger.logError("PROCESS_IMAGE", error, {
|
|
589
|
-
index,
|
|
590
|
-
provider: "anthropic",
|
|
591
|
-
});
|
|
592
|
-
throw error;
|
|
593
|
-
}
|
|
594
|
-
});
|
|
595
|
-
return { messages: [{ role: "user", content }] };
|
|
596
|
-
}
|
|
597
|
-
/**
|
|
598
|
-
* Format content for Vertex AI (model-specific routing)
|
|
599
|
-
*/
|
|
600
|
-
static formatForVertex(text, images, model) {
|
|
601
|
-
// Validate image count with model-specific limits before processing
|
|
602
|
-
this.validateImageCount(images.length, "vertex", model);
|
|
603
|
-
// Route based on model type, skip validation in delegated methods
|
|
604
|
-
if (model.includes("gemini")) {
|
|
605
|
-
return this.formatForGoogleAI(text, images, true);
|
|
606
|
-
}
|
|
607
|
-
else if (model.includes("claude")) {
|
|
608
|
-
return this.formatForAnthropic(text, images, true);
|
|
609
|
-
}
|
|
610
|
-
else {
|
|
611
|
-
return this.formatForGoogleAI(text, images, true);
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
/**
|
|
615
|
-
* Validate image count against provider limits
|
|
616
|
-
* Warns at 80% threshold, throws error if limit exceeded
|
|
446
|
+
* Validate image count against provider limits.
|
|
447
|
+
* Warns at 80% threshold, throws error if limit exceeded.
|
|
617
448
|
*/
|
|
618
449
|
static validateImageCount(imageCount, provider, model) {
|
|
619
450
|
const normalizedProvider = provider.toLowerCase();
|
|
@@ -659,27 +490,6 @@ export class ProviderImageAdapter {
|
|
|
659
490
|
`Maximum allowed: ${limit}. Please reduce the number of images.`);
|
|
660
491
|
}
|
|
661
492
|
}
|
|
662
|
-
/**
|
|
663
|
-
* Validate that provider and model support vision
|
|
664
|
-
*/
|
|
665
|
-
static validateVisionSupport(provider, model) {
|
|
666
|
-
const normalizedProvider = normalizeVisionProvider(provider);
|
|
667
|
-
const supportedModels = VISION_CAPABILITIES[normalizedProvider];
|
|
668
|
-
if (!supportedModels) {
|
|
669
|
-
throw new Error(`Provider ${provider} does not support vision processing. ` +
|
|
670
|
-
`Supported providers: ${Object.keys(VISION_CAPABILITIES).join(", ")}`);
|
|
671
|
-
}
|
|
672
|
-
const isSupported = supportedModels.some((supportedModel) => model.toLowerCase().includes(supportedModel.toLowerCase()));
|
|
673
|
-
// Proxy providers route to arbitrary underlying models — skip the allowlist
|
|
674
|
-
// check for unknown models and let the underlying provider error if needed.
|
|
675
|
-
if (!isSupported && PROXY_PROVIDERS.has(normalizedProvider)) {
|
|
676
|
-
return;
|
|
677
|
-
}
|
|
678
|
-
if (!isSupported) {
|
|
679
|
-
throw new Error(`Provider ${provider} with model ${model} does not support vision processing. ` +
|
|
680
|
-
`Supported models for ${provider}: ${supportedModels.join(", ")}`);
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
493
|
/**
|
|
684
494
|
* Convert simple images array to advanced content format
|
|
685
495
|
* @param text - Text content to include
|
|
@@ -220,8 +220,8 @@ export declare const directAgentTools: {
|
|
|
220
220
|
mode: z.ZodDefault<z.ZodEnum<["create", "overwrite", "append"]>>;
|
|
221
221
|
}, "strip", z.ZodTypeAny, {
|
|
222
222
|
path: string;
|
|
223
|
-
content: string;
|
|
224
223
|
mode: "append" | "create" | "overwrite";
|
|
224
|
+
content: string;
|
|
225
225
|
}, {
|
|
226
226
|
path: string;
|
|
227
227
|
content: string;
|
|
@@ -250,8 +250,8 @@ export declare const directAgentTools: {
|
|
|
250
250
|
}> & {
|
|
251
251
|
execute: (args: {
|
|
252
252
|
path: string;
|
|
253
|
-
content: string;
|
|
254
253
|
mode: "append" | "create" | "overwrite";
|
|
254
|
+
content: string;
|
|
255
255
|
}, options: import("ai").ToolExecutionOptions) => PromiseLike<{
|
|
256
256
|
success: boolean;
|
|
257
257
|
error: string;
|
|
@@ -464,6 +464,36 @@ export declare const directAgentTools: {
|
|
|
464
464
|
}>;
|
|
465
465
|
};
|
|
466
466
|
};
|
|
467
|
+
/**
|
|
468
|
+
* Bash command execution tool - exported separately for opt-in use.
|
|
469
|
+
*
|
|
470
|
+
* SECURITY: This tool is NOT included in directAgentTools by default.
|
|
471
|
+
* It must be explicitly enabled via:
|
|
472
|
+
* - Environment variable: NEUROLINK_ENABLE_BASH_TOOL=true
|
|
473
|
+
* - Config: toolConfig.enableBashTool = true
|
|
474
|
+
*
|
|
475
|
+
* Import this directly when you need bash execution capabilities:
|
|
476
|
+
* import { bashTool } from '../agent/directTools.js';
|
|
477
|
+
*/
|
|
478
|
+
export declare const bashTool: import("ai").Tool<z.ZodObject<{
|
|
479
|
+
command: z.ZodString;
|
|
480
|
+
timeout: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
481
|
+
cwd: z.ZodOptional<z.ZodString>;
|
|
482
|
+
}, "strip", z.ZodTypeAny, {
|
|
483
|
+
timeout: number;
|
|
484
|
+
command: string;
|
|
485
|
+
cwd?: string | undefined;
|
|
486
|
+
}, {
|
|
487
|
+
command: string;
|
|
488
|
+
timeout?: number | undefined;
|
|
489
|
+
cwd?: string | undefined;
|
|
490
|
+
}>, unknown> & {
|
|
491
|
+
execute: (args: {
|
|
492
|
+
timeout: number;
|
|
493
|
+
command: string;
|
|
494
|
+
cwd?: string | undefined;
|
|
495
|
+
}, options: import("ai").ToolExecutionOptions) => PromiseLike<unknown>;
|
|
496
|
+
};
|
|
467
497
|
/**
|
|
468
498
|
* Type aliases for specific tool categories
|
|
469
499
|
*/
|
|
@@ -481,7 +511,9 @@ export type UtilityToolsMap = {
|
|
|
481
511
|
calculateMath: typeof directAgentTools.calculateMath;
|
|
482
512
|
listDirectory: typeof directAgentTools.listDirectory;
|
|
483
513
|
};
|
|
484
|
-
export type AllToolsMap = typeof directAgentTools
|
|
514
|
+
export type AllToolsMap = typeof directAgentTools & {
|
|
515
|
+
executeBashCommand?: typeof bashTool;
|
|
516
|
+
};
|
|
485
517
|
/**
|
|
486
518
|
* Get a subset of tools for specific use cases with improved type safety
|
|
487
519
|
*/
|
|
@@ -6,9 +6,18 @@ import { tool } from "ai";
|
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import * as fs from "fs";
|
|
8
8
|
import * as path from "path";
|
|
9
|
+
import { execFile } from "child_process";
|
|
9
10
|
import { logger } from "../utils/logger.js";
|
|
10
11
|
import { VertexAI } from "@google-cloud/vertexai";
|
|
11
12
|
import { CSVProcessor } from "../utils/csvProcessor.js";
|
|
13
|
+
import { shouldEnableBashTool } from "../utils/toolUtils.js";
|
|
14
|
+
const MAX_OUTPUT_BYTES = 102400; // 100KB
|
|
15
|
+
function truncateOutput(output) {
|
|
16
|
+
if (output.length > MAX_OUTPUT_BYTES) {
|
|
17
|
+
return (output.slice(0, MAX_OUTPUT_BYTES) + "\n... [output truncated at 100KB]");
|
|
18
|
+
}
|
|
19
|
+
return output;
|
|
20
|
+
}
|
|
12
21
|
// Runtime Google Search tool creation - bypasses TypeScript strict typing
|
|
13
22
|
function createGoogleSearchTools() {
|
|
14
23
|
const searchTool = {};
|
|
@@ -534,6 +543,9 @@ export const directAgentTools = {
|
|
|
534
543
|
}
|
|
535
544
|
},
|
|
536
545
|
}),
|
|
546
|
+
// NOTE: executeBashCommand was moved to a separate opt-in export (bashTool) for security.
|
|
547
|
+
// It is only included in directAgentTools when NEUROLINK_ENABLE_BASH_TOOL=true or
|
|
548
|
+
// toolConfig.enableBashTool is explicitly set to true. See shouldEnableBashTool() in toolUtils.ts.
|
|
537
549
|
websearchGrounding: tool({
|
|
538
550
|
description: "Search the web for current information using Google Search grounding. Returns raw search data for AI processing.",
|
|
539
551
|
parameters: z.object({
|
|
@@ -657,6 +669,116 @@ export const directAgentTools = {
|
|
|
657
669
|
},
|
|
658
670
|
}),
|
|
659
671
|
};
|
|
672
|
+
/**
|
|
673
|
+
* Bash command execution tool - exported separately for opt-in use.
|
|
674
|
+
*
|
|
675
|
+
* SECURITY: This tool is NOT included in directAgentTools by default.
|
|
676
|
+
* It must be explicitly enabled via:
|
|
677
|
+
* - Environment variable: NEUROLINK_ENABLE_BASH_TOOL=true
|
|
678
|
+
* - Config: toolConfig.enableBashTool = true
|
|
679
|
+
*
|
|
680
|
+
* Import this directly when you need bash execution capabilities:
|
|
681
|
+
* import { bashTool } from '../agent/directTools.js';
|
|
682
|
+
*/
|
|
683
|
+
export const bashTool = tool({
|
|
684
|
+
description: "Execute a bash/shell command and return stdout, stderr, and exit code. Supports full shell syntax including pipes, redirects, and variable expansion. Requires HITL confirmation when enabled.",
|
|
685
|
+
parameters: z.object({
|
|
686
|
+
command: z
|
|
687
|
+
.string()
|
|
688
|
+
.describe("The shell command to execute (supports pipes, redirects, etc.)"),
|
|
689
|
+
timeout: z
|
|
690
|
+
.number()
|
|
691
|
+
.optional()
|
|
692
|
+
.default(30000)
|
|
693
|
+
.describe("Timeout in milliseconds (default: 30000, max: 120000)"),
|
|
694
|
+
cwd: z
|
|
695
|
+
.string()
|
|
696
|
+
.optional()
|
|
697
|
+
.describe("Working directory (defaults to process.cwd())"),
|
|
698
|
+
}),
|
|
699
|
+
execute: async ({ command, timeout = 30000, cwd }) => {
|
|
700
|
+
try {
|
|
701
|
+
const effectiveTimeout = Math.min(Math.max(timeout, 100), 120000);
|
|
702
|
+
const resolvedCwd = cwd ? path.resolve(cwd) : process.cwd();
|
|
703
|
+
const currentCwd = process.cwd();
|
|
704
|
+
// Verify cwd exists before resolving symlinks
|
|
705
|
+
if (!fs.existsSync(resolvedCwd) ||
|
|
706
|
+
!fs.statSync(resolvedCwd).isDirectory()) {
|
|
707
|
+
return {
|
|
708
|
+
success: false,
|
|
709
|
+
code: -1,
|
|
710
|
+
stdout: "",
|
|
711
|
+
stderr: "",
|
|
712
|
+
error: `Directory does not exist: ${resolvedCwd}`,
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
// Security: resolve symlinks and prevent execution outside current directory
|
|
716
|
+
try {
|
|
717
|
+
const realCwd = fs.realpathSync(currentCwd);
|
|
718
|
+
const realResolvedCwd = fs.realpathSync(resolvedCwd);
|
|
719
|
+
if (!realResolvedCwd.startsWith(realCwd)) {
|
|
720
|
+
return {
|
|
721
|
+
success: false,
|
|
722
|
+
code: -1,
|
|
723
|
+
stdout: "",
|
|
724
|
+
stderr: "",
|
|
725
|
+
error: "Access denied: Cannot execute commands outside current directory",
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
catch {
|
|
730
|
+
return {
|
|
731
|
+
success: false,
|
|
732
|
+
code: -1,
|
|
733
|
+
stdout: "",
|
|
734
|
+
stderr: "",
|
|
735
|
+
error: "Access denied: Cannot resolve directory path",
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
// Use /bin/bash -c to support full shell syntax (pipes, redirects, etc.)
|
|
739
|
+
return await new Promise((resolve) => {
|
|
740
|
+
execFile("/bin/bash", ["-c", command], {
|
|
741
|
+
timeout: effectiveTimeout,
|
|
742
|
+
cwd: resolvedCwd,
|
|
743
|
+
maxBuffer: MAX_OUTPUT_BYTES,
|
|
744
|
+
}, (error, stdout, stderr) => {
|
|
745
|
+
if (error) {
|
|
746
|
+
const exitCode = typeof error.code === "number" ? error.code : 1;
|
|
747
|
+
resolve({
|
|
748
|
+
success: false,
|
|
749
|
+
code: exitCode,
|
|
750
|
+
stdout: truncateOutput(stdout || ""),
|
|
751
|
+
stderr: truncateOutput(stderr || error.message),
|
|
752
|
+
error: error.killed ? "Command timed out" : error.message,
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
else {
|
|
756
|
+
resolve({
|
|
757
|
+
success: true,
|
|
758
|
+
code: 0,
|
|
759
|
+
stdout: truncateOutput(stdout),
|
|
760
|
+
stderr: truncateOutput(stderr),
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
});
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
catch (error) {
|
|
767
|
+
return {
|
|
768
|
+
success: false,
|
|
769
|
+
code: -1,
|
|
770
|
+
stdout: "",
|
|
771
|
+
stderr: "",
|
|
772
|
+
error: error instanceof Error ? error.message : String(error),
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
},
|
|
776
|
+
});
|
|
777
|
+
// Conditionally inject executeBashCommand into directAgentTools when opted in.
|
|
778
|
+
// This ensures the tool is only available to SDK consumers who explicitly enable it.
|
|
779
|
+
if (shouldEnableBashTool()) {
|
|
780
|
+
directAgentTools.executeBashCommand = bashTool;
|
|
781
|
+
}
|
|
660
782
|
// eslint-disable-next-line no-redeclare
|
|
661
783
|
export function getToolsForCategory(category = "all") {
|
|
662
784
|
switch (category) {
|
|
@@ -83,13 +83,13 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
83
83
|
model: z.ZodDefault<z.ZodString>;
|
|
84
84
|
}, "strip", z.ZodTypeAny, {
|
|
85
85
|
model: string;
|
|
86
|
-
apiKey?: string | undefined;
|
|
87
86
|
endpoint?: string | undefined;
|
|
87
|
+
apiKey?: string | undefined;
|
|
88
88
|
deploymentId?: string | undefined;
|
|
89
89
|
}, {
|
|
90
90
|
model?: string | undefined;
|
|
91
|
-
apiKey?: string | undefined;
|
|
92
91
|
endpoint?: string | undefined;
|
|
92
|
+
apiKey?: string | undefined;
|
|
93
93
|
deploymentId?: string | undefined;
|
|
94
94
|
}>>;
|
|
95
95
|
"google-ai": z.ZodOptional<z.ZodObject<{
|
|
@@ -163,8 +163,8 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
163
163
|
} | undefined;
|
|
164
164
|
azure?: {
|
|
165
165
|
model: string;
|
|
166
|
-
apiKey?: string | undefined;
|
|
167
166
|
endpoint?: string | undefined;
|
|
167
|
+
apiKey?: string | undefined;
|
|
168
168
|
deploymentId?: string | undefined;
|
|
169
169
|
} | undefined;
|
|
170
170
|
"google-ai"?: {
|
|
@@ -212,8 +212,8 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
212
212
|
} | undefined;
|
|
213
213
|
azure?: {
|
|
214
214
|
model?: string | undefined;
|
|
215
|
-
apiKey?: string | undefined;
|
|
216
215
|
endpoint?: string | undefined;
|
|
216
|
+
apiKey?: string | undefined;
|
|
217
217
|
deploymentId?: string | undefined;
|
|
218
218
|
} | undefined;
|
|
219
219
|
"google-ai"?: {
|
|
@@ -483,8 +483,8 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
483
483
|
} | undefined;
|
|
484
484
|
azure?: {
|
|
485
485
|
model: string;
|
|
486
|
-
apiKey?: string | undefined;
|
|
487
486
|
endpoint?: string | undefined;
|
|
487
|
+
apiKey?: string | undefined;
|
|
488
488
|
deploymentId?: string | undefined;
|
|
489
489
|
} | undefined;
|
|
490
490
|
"google-ai"?: {
|
|
@@ -581,8 +581,8 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
581
581
|
} | undefined;
|
|
582
582
|
azure?: {
|
|
583
583
|
model?: string | undefined;
|
|
584
|
-
apiKey?: string | undefined;
|
|
585
584
|
endpoint?: string | undefined;
|
|
585
|
+
apiKey?: string | undefined;
|
|
586
586
|
deploymentId?: string | undefined;
|
|
587
587
|
} | undefined;
|
|
588
588
|
"google-ai"?: {
|
|
@@ -10,8 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { ChatMessage, ConversationMemoryConfig } from "../types/conversation.js";
|
|
12
12
|
import type { CompactionResult, CompactionConfig } from "../types/contextTypes.js";
|
|
13
|
-
export type { CompactionResult,
|
|
14
|
-
export type CompactionStage = "prune" | "deduplicate" | "summarize" | "truncate";
|
|
13
|
+
export type { CompactionConfig, CompactionResult, CompactionStage, } from "../types/contextTypes.js";
|
|
15
14
|
export declare class ContextCompactor {
|
|
16
15
|
private config;
|
|
17
16
|
constructor(config?: CompactionConfig);
|
|
@@ -15,8 +15,8 @@ import { SpanSerializer, SpanType, SpanStatus, } from "../observability/index.js
|
|
|
15
15
|
import { getMetricsAggregator } from "../observability/index.js";
|
|
16
16
|
import { pruneToolOutputs } from "./stages/toolOutputPruner.js";
|
|
17
17
|
import { deduplicateFileReads } from "./stages/fileReadDeduplicator.js";
|
|
18
|
-
import { summarizeMessages } from "./stages/structuredSummarizer.js";
|
|
19
18
|
import { truncateWithSlidingWindow } from "./stages/slidingWindowTruncator.js";
|
|
19
|
+
import { summarizeMessages } from "./stages/structuredSummarizer.js";
|
|
20
20
|
const DEFAULT_CONFIG = {
|
|
21
21
|
enablePrune: true,
|
|
22
22
|
enableDeduplicate: true,
|
|
@@ -106,6 +106,7 @@ export class ContextCompactor {
|
|
|
106
106
|
model: this.config.summarizationModel,
|
|
107
107
|
keepRecentRatio: this.config.keepRecentRatio,
|
|
108
108
|
memoryConfig,
|
|
109
|
+
targetTokens,
|
|
109
110
|
}), 120_000, "LLM summarization timed out after 120s");
|
|
110
111
|
if (summarizeResult.summarized) {
|
|
111
112
|
currentMessages = summarizeResult.messages;
|
|
@@ -146,6 +147,11 @@ export class ContextCompactor {
|
|
|
146
147
|
const stageTokensBefore = estimateMessagesTokens(currentMessages, provider);
|
|
147
148
|
const truncResult = truncateWithSlidingWindow(currentMessages, {
|
|
148
149
|
fraction: this.config.truncationFraction,
|
|
150
|
+
currentTokens: stageTokensBefore,
|
|
151
|
+
targetTokens: targetTokens,
|
|
152
|
+
provider: provider,
|
|
153
|
+
adaptiveBuffer: 0.15,
|
|
154
|
+
maxIterations: 3,
|
|
149
155
|
});
|
|
150
156
|
if (truncResult.truncated) {
|
|
151
157
|
currentMessages = truncResult.messages;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Summarization Prompt Builder
|
|
3
3
|
*
|
|
4
|
-
* Builds prompts for summarizing conversation context into a
|
|
4
|
+
* Builds prompts for summarizing conversation context into a 10-section structure.
|
|
5
5
|
* Supports both initial summarization and incremental merging with existing summaries.
|
|
6
6
|
*/
|
|
7
7
|
import type { SummarizationPromptOptions } from "../../types/contextTypes.js";
|
|
8
8
|
export type { SummarizationPromptOptions } from "../../types/contextTypes.js";
|
|
9
|
-
declare const
|
|
9
|
+
declare const SUMMARY_SECTIONS: string[];
|
|
10
10
|
/**
|
|
11
11
|
* Builds a summarization prompt based on the provided options.
|
|
12
12
|
*
|
|
@@ -14,4 +14,4 @@ declare const NINE_SECTIONS: string[];
|
|
|
14
14
|
* @returns The constructed prompt string
|
|
15
15
|
*/
|
|
16
16
|
export declare function buildSummarizationPrompt(options: SummarizationPromptOptions): string;
|
|
17
|
-
export {
|
|
17
|
+
export { SUMMARY_SECTIONS };
|