@juspay/neurolink 12.27.2 → 12.28.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -2
- package/dist/agent/directTools.d.ts +118 -94
- package/dist/agent/directTools.js +578 -446
- package/dist/agent/index.d.ts +1 -0
- package/dist/agent/index.js +1 -0
- package/dist/agent/prompts/terminalAgentPrompt.d.ts +13 -0
- package/dist/agent/prompts/terminalAgentPrompt.js +59 -0
- package/dist/browser/neurolink.min.js +384 -378
- package/dist/cli/factories/commandFactory.d.ts +25 -0
- package/dist/cli/factories/commandFactory.js +78 -8
- package/dist/cli/loop/optionsSchema.d.ts +1 -1
- package/dist/core/baseProvider.d.ts +17 -1
- package/dist/core/baseProvider.js +48 -1
- package/dist/core/modules/ToolsManager.d.ts +7 -1
- package/dist/core/modules/ToolsManager.js +8 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mcp/toolRegistry.d.ts +12 -1
- package/dist/mcp/toolRegistry.js +26 -2
- package/dist/neurolink.d.ts +13 -0
- package/dist/neurolink.js +97 -10
- package/dist/session/globalSessionState.d.ts +8 -0
- package/dist/session/globalSessionState.js +17 -0
- package/dist/types/agentMode.d.ts +9 -0
- package/dist/types/agentMode.js +1 -0
- package/dist/types/cli.d.ts +6 -0
- package/dist/types/config.d.ts +9 -0
- package/dist/types/fileToolRoots.d.ts +17 -0
- package/dist/types/fileToolRoots.js +7 -0
- package/dist/types/generate.d.ts +17 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +2 -0
- package/dist/types/providers.d.ts +6 -0
- package/dist/types/stream.d.ts +7 -0
- package/dist/types/tools.d.ts +7 -0
- package/dist/utils/fileToolRoots.d.ts +34 -0
- package/dist/utils/fileToolRoots.js +111 -0
- package/dist/utils/messageBuilder.js +32 -1
- package/dist/utils/pathSandbox.d.ts +9 -6
- package/dist/utils/pathSandbox.js +35 -9
- package/docs-site/static/search-index.json +6 -5
- package/package.json +6 -2
|
@@ -145,6 +145,11 @@ export declare class CLICommandFactory {
|
|
|
145
145
|
description: string;
|
|
146
146
|
alias: string;
|
|
147
147
|
};
|
|
148
|
+
toolRoot: {
|
|
149
|
+
type: "string";
|
|
150
|
+
array: boolean;
|
|
151
|
+
description: string;
|
|
152
|
+
};
|
|
148
153
|
format: {
|
|
149
154
|
choices: string[];
|
|
150
155
|
default: string;
|
|
@@ -609,6 +614,17 @@ export declare class CLICommandFactory {
|
|
|
609
614
|
alias: string;
|
|
610
615
|
};
|
|
611
616
|
};
|
|
617
|
+
static readonly agentOptions: {
|
|
618
|
+
agentMode: {
|
|
619
|
+
type: "boolean";
|
|
620
|
+
description: string;
|
|
621
|
+
};
|
|
622
|
+
maxSteps: {
|
|
623
|
+
type: "number";
|
|
624
|
+
description: string;
|
|
625
|
+
coerce: (value: unknown) => number;
|
|
626
|
+
};
|
|
627
|
+
};
|
|
612
628
|
private static buildOptions;
|
|
613
629
|
private static processCliImages;
|
|
614
630
|
private static processCliCSVFiles;
|
|
@@ -920,6 +936,10 @@ export declare class CLICommandFactory {
|
|
|
920
936
|
* Flush Langfuse traces before exit
|
|
921
937
|
*/
|
|
922
938
|
private static flushLangfuseTraces;
|
|
939
|
+
/** process.exit discards piped stdout queued past the 64 KiB buffer; resolves false if the reader stalls past the bound. */
|
|
940
|
+
private static flushStdout;
|
|
941
|
+
/** Forced exit that fails loudly when queued output could not be delivered. */
|
|
942
|
+
private static exitAfterStdoutDrain;
|
|
923
943
|
}
|
|
924
944
|
/** Re-export of CLICommandFactory's static option definitions for direct import by tests/tooling. */
|
|
925
945
|
export declare const commonOptions: {
|
|
@@ -1048,6 +1068,11 @@ export declare const commonOptions: {
|
|
|
1048
1068
|
description: string;
|
|
1049
1069
|
alias: string;
|
|
1050
1070
|
};
|
|
1071
|
+
toolRoot: {
|
|
1072
|
+
type: "string";
|
|
1073
|
+
array: boolean;
|
|
1074
|
+
description: string;
|
|
1075
|
+
};
|
|
1051
1076
|
format: {
|
|
1052
1077
|
choices: string[];
|
|
1053
1078
|
default: string;
|
|
@@ -2,6 +2,7 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import chalk from "chalk";
|
|
4
4
|
import ora from "ora";
|
|
5
|
+
import { STEP_LIMITS } from "../../core/constants.js";
|
|
5
6
|
import { ModelResolver } from "../../models/modelResolver.js";
|
|
6
7
|
import { providerChoicesFor } from "../../factories/mediaHandlerCatalog.js";
|
|
7
8
|
import { globalSession } from "../../session/globalSessionState.js";
|
|
@@ -48,6 +49,21 @@ const DERIVED_PROVIDER_CHOICES = [
|
|
|
48
49
|
];
|
|
49
50
|
/** Space-separated form for the bash-completion script, kept in sync with DERIVED_PROVIDER_CHOICES by construction. */
|
|
50
51
|
export const BASH_COMPLETION_PROVIDERS = DERIVED_PROVIDER_CHOICES.join(" ");
|
|
52
|
+
/** EX_IOERR (sysexits.h): the result could not be fully written to stdout. */
|
|
53
|
+
const STDOUT_DRAIN_FAILED_EXIT_CODE = 74;
|
|
54
|
+
const DEFAULT_STDOUT_DRAIN_TIMEOUT_MS = 30_000;
|
|
55
|
+
const STDOUT_DRAIN_WARNING = "neurolink: stdout drain timed out; output may be incomplete\n";
|
|
56
|
+
let stdoutDrainTimeoutMs;
|
|
57
|
+
const resolveStdoutDrainTimeoutMs = () => {
|
|
58
|
+
if (stdoutDrainTimeoutMs === undefined) {
|
|
59
|
+
const override = Number(process.env.NEUROLINK_STDOUT_DRAIN_TIMEOUT_MS);
|
|
60
|
+
stdoutDrainTimeoutMs =
|
|
61
|
+
Number.isFinite(override) && override > 0
|
|
62
|
+
? override
|
|
63
|
+
: DEFAULT_STDOUT_DRAIN_TIMEOUT_MS;
|
|
64
|
+
}
|
|
65
|
+
return stdoutDrainTimeoutMs;
|
|
66
|
+
};
|
|
51
67
|
/**
|
|
52
68
|
* CLI Command Factory for generate commands
|
|
53
69
|
*/
|
|
@@ -221,6 +237,11 @@ export class CLICommandFactory {
|
|
|
221
237
|
description: "System prompt to guide AI behavior",
|
|
222
238
|
alias: "s",
|
|
223
239
|
},
|
|
240
|
+
toolRoot: {
|
|
241
|
+
type: "string",
|
|
242
|
+
array: true,
|
|
243
|
+
description: "Directory the built-in file tools may read and write (repeatable). Defaults to the working directory. Constrains bash's working directory, not its commands.",
|
|
244
|
+
},
|
|
224
245
|
// Output control options
|
|
225
246
|
format: {
|
|
226
247
|
choices: ["text", "json", "table"],
|
|
@@ -736,6 +757,26 @@ export class CLICommandFactory {
|
|
|
736
757
|
alias: "skills-dir",
|
|
737
758
|
},
|
|
738
759
|
};
|
|
760
|
+
// Registered on generate and stream only; the flags mean nothing elsewhere.
|
|
761
|
+
static agentOptions = {
|
|
762
|
+
agentMode: {
|
|
763
|
+
type: "boolean",
|
|
764
|
+
description: "Run as an autonomous terminal agent: prepend Neurolink's versioned agent instructions to the system prompt",
|
|
765
|
+
},
|
|
766
|
+
maxSteps: {
|
|
767
|
+
type: "number",
|
|
768
|
+
description: `Maximum tool-calling steps before the turn stops (integer ${STEP_LIMITS.min}-${STEP_LIMITS.max}, default ${STEP_LIMITS.default}; some providers cap lower)`,
|
|
769
|
+
coerce: (value) => {
|
|
770
|
+
if (typeof value !== "number" ||
|
|
771
|
+
!Number.isInteger(value) ||
|
|
772
|
+
value < STEP_LIMITS.min ||
|
|
773
|
+
value > STEP_LIMITS.max) {
|
|
774
|
+
throw new Error(`--max-steps must be an integer between ${STEP_LIMITS.min} and ${STEP_LIMITS.max}`);
|
|
775
|
+
}
|
|
776
|
+
return value;
|
|
777
|
+
},
|
|
778
|
+
},
|
|
779
|
+
};
|
|
739
780
|
// Helper method to build options for commands. `excludeOptions` drops
|
|
740
781
|
// common flags from registration entirely (not just from validation) —
|
|
741
782
|
// #1191 round-5: batch uses this to omit `commonOptions.file` so `--file`
|
|
@@ -882,6 +923,8 @@ export class CLICommandFactory {
|
|
|
882
923
|
stopSequences: argv.stopSequences,
|
|
883
924
|
enabledToolNames: argv.enabledToolNames,
|
|
884
925
|
systemPrompt: argv.system,
|
|
926
|
+
agentMode: argv.agentMode,
|
|
927
|
+
maxSteps: argv.maxSteps,
|
|
885
928
|
timeout: argv.timeout,
|
|
886
929
|
disableTools: argv.disableTools,
|
|
887
930
|
enableAnalytics: argv.enableAnalytics,
|
|
@@ -1531,7 +1574,8 @@ export class CLICommandFactory {
|
|
|
1531
1574
|
.example('$0 generate "Summarize this report" --pdf ./report.pdf', "Analyze a PDF document")
|
|
1532
1575
|
.example('$0 generate "Key trends?" --csv large-data.csv --csvMaxRows 100', "Analyze a CSV with a row limit")
|
|
1533
1576
|
.example('$0 generate "Compare the chart and the report" --image ./chart.png --pdf ./report.pdf', "Combine multiple file types in one prompt")
|
|
1534
|
-
.example('$0 generate "What is in this file?" --file ./data.json', "Auto-detect a file type with --file")
|
|
1577
|
+
.example('$0 generate "What is in this file?" --file ./data.json', "Auto-detect a file type with --file")
|
|
1578
|
+
.example('$0 generate "Fix the failing config" --agent-mode --max-steps 60', "Run as an autonomous terminal agent with a step budget"), CLICommandFactory.agentOptions);
|
|
1535
1579
|
},
|
|
1536
1580
|
handler: async (argv) => await CLICommandFactory.executeGenerate(argv),
|
|
1537
1581
|
};
|
|
@@ -1556,7 +1600,7 @@ export class CLICommandFactory {
|
|
|
1556
1600
|
.example('$0 stream "Narrate this video" --video path/to/video.mp4', "Stream video analysis")
|
|
1557
1601
|
.example('$0 stream "Describe this image" --image ./photo.jpg', "Stream image analysis (multimodal input)")
|
|
1558
1602
|
.example('$0 stream "Summarize this document" --pdf ./report.pdf', "Stream PDF analysis")
|
|
1559
|
-
.example('$0 stream "Explain this dataset" --csv ./data.csv --csv-format markdown', "Stream CSV analysis"));
|
|
1603
|
+
.example('$0 stream "Explain this dataset" --csv ./data.csv --csv-format markdown', "Stream CSV analysis"), CLICommandFactory.agentOptions);
|
|
1560
1604
|
},
|
|
1561
1605
|
handler: async (argv) => await CLICommandFactory.executeStream(argv),
|
|
1562
1606
|
};
|
|
@@ -2261,7 +2305,7 @@ export class CLICommandFactory {
|
|
|
2261
2305
|
logger.error("Error during SDK shutdown:", shutdownError);
|
|
2262
2306
|
}
|
|
2263
2307
|
if (!globalSession.getCurrentSessionId()) {
|
|
2264
|
-
|
|
2308
|
+
await CLICommandFactory.exitAfterStdoutDrain();
|
|
2265
2309
|
}
|
|
2266
2310
|
}
|
|
2267
2311
|
}
|
|
@@ -2562,7 +2606,7 @@ export class CLICommandFactory {
|
|
|
2562
2606
|
}
|
|
2563
2607
|
if (!globalSession.getCurrentSessionId()) {
|
|
2564
2608
|
await CLICommandFactory.flushLangfuseTraces();
|
|
2565
|
-
|
|
2609
|
+
await CLICommandFactory.exitAfterStdoutDrain(0);
|
|
2566
2610
|
}
|
|
2567
2611
|
}
|
|
2568
2612
|
/**
|
|
@@ -2627,7 +2671,7 @@ export class CLICommandFactory {
|
|
|
2627
2671
|
}
|
|
2628
2672
|
if (!globalSession.getCurrentSessionId()) {
|
|
2629
2673
|
await CLICommandFactory.flushLangfuseTraces();
|
|
2630
|
-
|
|
2674
|
+
await CLICommandFactory.exitAfterStdoutDrain(0);
|
|
2631
2675
|
}
|
|
2632
2676
|
return;
|
|
2633
2677
|
}
|
|
@@ -2646,6 +2690,7 @@ export class CLICommandFactory {
|
|
|
2646
2690
|
if (skillsConfig) {
|
|
2647
2691
|
globalSession.setSkillsConfig(skillsConfig);
|
|
2648
2692
|
}
|
|
2693
|
+
globalSession.setFileToolRoots(argv.toolRoot);
|
|
2649
2694
|
// Initialize SDK and session
|
|
2650
2695
|
const sdk = globalSession.getOrCreateNeuroLink();
|
|
2651
2696
|
const sessionVariables = CLICommandFactory.normalizeLoopSessionVariables(globalSession.getSessionVariables());
|
|
@@ -2700,6 +2745,8 @@ export class CLICommandFactory {
|
|
|
2700
2745
|
topK: enhancedOptions.topK,
|
|
2701
2746
|
stopSequences: enhancedOptions.stopSequences,
|
|
2702
2747
|
systemPrompt: enhancedOptions.systemPrompt,
|
|
2748
|
+
agentMode: enhancedOptions.agentMode,
|
|
2749
|
+
maxSteps: enhancedOptions.maxSteps,
|
|
2703
2750
|
timeout: enhancedOptions.timeout
|
|
2704
2751
|
? enhancedOptions.timeout * 1000
|
|
2705
2752
|
: undefined,
|
|
@@ -2892,7 +2939,7 @@ export class CLICommandFactory {
|
|
|
2892
2939
|
}
|
|
2893
2940
|
if (!globalSession.getCurrentSessionId()) {
|
|
2894
2941
|
await CLICommandFactory.flushLangfuseTraces();
|
|
2895
|
-
|
|
2942
|
+
await CLICommandFactory.exitAfterStdoutDrain(0);
|
|
2896
2943
|
}
|
|
2897
2944
|
}
|
|
2898
2945
|
/**
|
|
@@ -2914,6 +2961,7 @@ export class CLICommandFactory {
|
|
|
2914
2961
|
if (skillsConfig) {
|
|
2915
2962
|
globalSession.setSkillsConfig(skillsConfig);
|
|
2916
2963
|
}
|
|
2964
|
+
globalSession.setFileToolRoots(argv.toolRoot);
|
|
2917
2965
|
const sdk = globalSession.getOrCreateNeuroLink();
|
|
2918
2966
|
const sessionVariables = CLICommandFactory.normalizeLoopSessionVariables(globalSession.getSessionVariables());
|
|
2919
2967
|
const enhancedOptions = { ...options, ...sessionVariables };
|
|
@@ -2949,6 +2997,8 @@ export class CLICommandFactory {
|
|
|
2949
2997
|
topK: enhancedOptions.topK,
|
|
2950
2998
|
stopSequences: enhancedOptions.stopSequences,
|
|
2951
2999
|
systemPrompt: enhancedOptions.systemPrompt,
|
|
3000
|
+
agentMode: enhancedOptions.agentMode,
|
|
3001
|
+
maxSteps: enhancedOptions.maxSteps,
|
|
2952
3002
|
timeout: enhancedOptions.timeout
|
|
2953
3003
|
? enhancedOptions.timeout * 1000
|
|
2954
3004
|
: undefined,
|
|
@@ -3391,7 +3441,7 @@ export class CLICommandFactory {
|
|
|
3391
3441
|
await CLICommandFactory.handleStreamOutput(options, fullContent);
|
|
3392
3442
|
if (!globalSession.getCurrentSessionId()) {
|
|
3393
3443
|
await CLICommandFactory.flushLangfuseTraces();
|
|
3394
|
-
|
|
3444
|
+
await CLICommandFactory.exitAfterStdoutDrain(0);
|
|
3395
3445
|
}
|
|
3396
3446
|
}
|
|
3397
3447
|
catch (error) {
|
|
@@ -3462,6 +3512,7 @@ export class CLICommandFactory {
|
|
|
3462
3512
|
if (skillsConfig) {
|
|
3463
3513
|
globalSession.setSkillsConfig(skillsConfig);
|
|
3464
3514
|
}
|
|
3515
|
+
globalSession.setFileToolRoots(argv.toolRoot);
|
|
3465
3516
|
const sdk = globalSession.getOrCreateNeuroLink();
|
|
3466
3517
|
const sessionVariables = CLICommandFactory.normalizeLoopSessionVariables(globalSession.getSessionVariables());
|
|
3467
3518
|
const enhancedOptions = { ...options, ...sessionVariables };
|
|
@@ -3595,7 +3646,7 @@ export class CLICommandFactory {
|
|
|
3595
3646
|
CLICommandFactory.handleOutput(results, options);
|
|
3596
3647
|
if (!globalSession.getCurrentSessionId()) {
|
|
3597
3648
|
await CLICommandFactory.flushLangfuseTraces();
|
|
3598
|
-
|
|
3649
|
+
await CLICommandFactory.exitAfterStdoutDrain(0);
|
|
3599
3650
|
}
|
|
3600
3651
|
}
|
|
3601
3652
|
catch (error) {
|
|
@@ -4561,6 +4612,25 @@ export class CLICommandFactory {
|
|
|
4561
4612
|
logger.error("[CLI] Error flushing Langfuse traces", { error });
|
|
4562
4613
|
}
|
|
4563
4614
|
}
|
|
4615
|
+
/** process.exit discards piped stdout queued past the 64 KiB buffer; resolves false if the reader stalls past the bound. */
|
|
4616
|
+
static flushStdout() {
|
|
4617
|
+
return new Promise((resolve) => {
|
|
4618
|
+
const timer = setTimeout(() => resolve(false), resolveStdoutDrainTimeoutMs());
|
|
4619
|
+
timer.unref();
|
|
4620
|
+
process.stdout.write("", () => {
|
|
4621
|
+
clearTimeout(timer);
|
|
4622
|
+
resolve(true);
|
|
4623
|
+
});
|
|
4624
|
+
});
|
|
4625
|
+
}
|
|
4626
|
+
/** Forced exit that fails loudly when queued output could not be delivered. */
|
|
4627
|
+
static async exitAfterStdoutDrain(exitCode) {
|
|
4628
|
+
if (await CLICommandFactory.flushStdout()) {
|
|
4629
|
+
process.exit(exitCode);
|
|
4630
|
+
}
|
|
4631
|
+
process.stderr.write(STDOUT_DRAIN_WARNING);
|
|
4632
|
+
process.exit(STDOUT_DRAIN_FAILED_EXIT_CODE);
|
|
4633
|
+
}
|
|
4564
4634
|
}
|
|
4565
4635
|
/** Re-export of CLICommandFactory's static option definitions for direct import by tests/tooling. */
|
|
4566
4636
|
export const commonOptions = CLICommandFactory.commonOptions;
|
|
@@ -4,4 +4,4 @@ import type { OptionSchema, TextGenerationOptions } from "../../types/index.js";
|
|
|
4
4
|
* This object provides metadata for validation and help text in the CLI loop.
|
|
5
5
|
* It is derived from the main TextGenerationOptions interface to ensure consistency.
|
|
6
6
|
*/
|
|
7
|
-
export declare const textGenerationOptionsSchema: Record<keyof Omit<TextGenerationOptions, "prompt" | "input" | "schema" | "tools" | "context" | "conversationHistory" | "conversationMessages" | "conversationMemoryConfig" | "originalPrompt" | "middleware" | "expectedOutcome" | "evaluationCriteria" | "region" | "csvOptions" | "pdfOptions" | "imageOptions" | "tts" | "stt" | "thinkingConfig" | "requestId" | "fileRegistry" | "abortSignal" | "toolFilter" | "excludeTools" | "toolChoice" | "prepareStep" | "credentials" | "onFinish" | "onError" | "processors" | "piiDetection" | "responseValidation" | "inputValidation" | "toolExecutionCapture" | "toolExecutionRecorder">, OptionSchema>;
|
|
7
|
+
export declare const textGenerationOptionsSchema: Record<keyof Omit<TextGenerationOptions, "prompt" | "input" | "schema" | "tools" | "context" | "conversationHistory" | "conversationMessages" | "conversationMemoryConfig" | "originalPrompt" | "middleware" | "expectedOutcome" | "evaluationCriteria" | "region" | "csvOptions" | "pdfOptions" | "imageOptions" | "tts" | "stt" | "thinkingConfig" | "requestId" | "fileRegistry" | "abortSignal" | "toolFilter" | "excludeTools" | "toolChoice" | "prepareStep" | "credentials" | "onFinish" | "onError" | "processors" | "piiDetection" | "responseValidation" | "inputValidation" | "toolExecutionCapture" | "toolExecutionRecorder" | "toolRoots">, OptionSchema>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AIProviderName } from "../constants/enums.js";
|
|
2
2
|
import type { EvaluationData } from "../index.js";
|
|
3
3
|
import type { NeuroLink } from "../neurolink.js";
|
|
4
|
-
import type { UnknownRecord, MiddlewareFactoryOptions, StreamOptions, StreamResult, AIProvider, AnalyticsData, EnhancedGenerateResult, TextGenerationOptions, TextGenerationResult, ValidationSchema, EmbedInput, DecisionRequest, DecisionResult } from "../types/index.js";
|
|
4
|
+
import type { FileToolRootPolicy, UnknownRecord, MiddlewareFactoryOptions, StreamOptions, StreamResult, AIProvider, AnalyticsData, EnhancedGenerateResult, TextGenerationOptions, TextGenerationResult, ValidationSchema, EmbedInput, DecisionRequest, DecisionResult } from "../types/index.js";
|
|
5
5
|
import { TelemetryHandler } from "./modules/TelemetryHandler.js";
|
|
6
6
|
import type { LanguageModel, ModelMessage, RawUsageObject, Tool, ToolCallRepairFunction, ToolSet } from "../types/index.js";
|
|
7
7
|
export declare abstract class BaseProvider implements AIProvider {
|
|
@@ -11,6 +11,7 @@ export declare abstract class BaseProvider implements AIProvider {
|
|
|
11
11
|
protected middlewareOptions?: MiddlewareFactoryOptions;
|
|
12
12
|
protected readonly directTools: {};
|
|
13
13
|
protected mcpTools?: Record<string, Tool>;
|
|
14
|
+
private fileToolRootsBound;
|
|
14
15
|
protected customTools?: Map<string, unknown>;
|
|
15
16
|
protected toolExecutor?: (toolName: string, params: unknown) => Promise<unknown>;
|
|
16
17
|
protected sessionId?: string;
|
|
@@ -532,6 +533,21 @@ export declare abstract class BaseProvider implements AIProvider {
|
|
|
532
533
|
/**
|
|
533
534
|
* Get all available tools - delegated to ToolsManager
|
|
534
535
|
*/
|
|
536
|
+
/**
|
|
537
|
+
* Bind the built-in file tools to one request's root policy. NeuroLink
|
|
538
|
+
* calls this before every provider call that carries the caller's options,
|
|
539
|
+
* because several providers override generate()/stream() and assemble
|
|
540
|
+
* their tools without passing through BaseProvider's entry points.
|
|
541
|
+
* Providers are created per request, so a bound policy never reaches
|
|
542
|
+
* another request.
|
|
543
|
+
*/
|
|
544
|
+
setFileToolRootPolicy(policy: FileToolRootPolicy | undefined): void;
|
|
545
|
+
/**
|
|
546
|
+
* Resolve roots for a provider called directly, without NeuroLink. A
|
|
547
|
+
* policy NeuroLink already bound is left alone unless these options carry
|
|
548
|
+
* their own. An invalid root throws, before any model request.
|
|
549
|
+
*/
|
|
550
|
+
private applyFileToolRoots;
|
|
535
551
|
protected getAllTools(): Promise<Record<string, Tool>>;
|
|
536
552
|
/**
|
|
537
553
|
* Calculate actual cost - delegated to TelemetryHandler
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { context, SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
|
|
2
|
-
import { directAgentTools } from "../agent/directTools.js";
|
|
2
|
+
import { createDirectAgentTools, directAgentTools, } from "../agent/directTools.js";
|
|
3
|
+
import { boundFileToolRoots, resolveFileToolRootPolicy, } from "../utils/fileToolRoots.js";
|
|
3
4
|
import { defaultProviderFor } from "../factories/mediaHandlerCatalog.js";
|
|
4
5
|
import { DECISION_PROVIDERS, PROVIDER_DESCRIPTORS_BY_NAME, } from "../factories/providerDescriptors.js";
|
|
5
6
|
import { MiddlewareFactory } from "../middleware/factory.js";
|
|
@@ -120,6 +121,7 @@ export class BaseProvider {
|
|
|
120
121
|
? {}
|
|
121
122
|
: directAgentTools;
|
|
122
123
|
mcpTools; // MCP tools loaded dynamically when available
|
|
124
|
+
fileToolRootsBound = false;
|
|
123
125
|
customTools; // Custom tools from registerTool()
|
|
124
126
|
toolExecutor; // Tool executor from setupToolExecutor
|
|
125
127
|
sessionId;
|
|
@@ -225,6 +227,7 @@ export class BaseProvider {
|
|
|
225
227
|
// maxTokens (getSafeMaxTokens consults the discovered output ceiling).
|
|
226
228
|
await this.ensureModelLimits();
|
|
227
229
|
let options = this.normalizeStreamOptions(optionsOrPrompt);
|
|
230
|
+
this.applyFileToolRoots(options);
|
|
228
231
|
// Before anything else, and before a single byte leaves the process: an
|
|
229
232
|
// execution policy this provider cannot honour is an error, and a policy
|
|
230
233
|
// whose shape could be read two ways is an error. Both are silent bugs at
|
|
@@ -1292,6 +1295,7 @@ export class BaseProvider {
|
|
|
1292
1295
|
await this.ensureModelLimits();
|
|
1293
1296
|
const options = this.normalizeTextOptions(optionsOrPrompt);
|
|
1294
1297
|
this.validateOptions(options);
|
|
1298
|
+
this.applyFileToolRoots(options);
|
|
1295
1299
|
const startTime = Date.now();
|
|
1296
1300
|
// One span per attempt. runGenerateInActiveContext ends the span on the
|
|
1297
1301
|
// way out (success or failure), so a model-fallback retry must not reuse
|
|
@@ -2156,7 +2160,50 @@ export class BaseProvider {
|
|
|
2156
2160
|
/**
|
|
2157
2161
|
* Get all available tools - delegated to ToolsManager
|
|
2158
2162
|
*/
|
|
2163
|
+
/**
|
|
2164
|
+
* Bind the built-in file tools to one request's root policy. NeuroLink
|
|
2165
|
+
* calls this before every provider call that carries the caller's options,
|
|
2166
|
+
* because several providers override generate()/stream() and assemble
|
|
2167
|
+
* their tools without passing through BaseProvider's entry points.
|
|
2168
|
+
* Providers are created per request, so a bound policy never reaches
|
|
2169
|
+
* another request.
|
|
2170
|
+
*/
|
|
2171
|
+
setFileToolRootPolicy(policy) {
|
|
2172
|
+
if (policy === undefined || Object.keys(this.directTools).length === 0) {
|
|
2173
|
+
return;
|
|
2174
|
+
}
|
|
2175
|
+
this.fileToolRootsBound = true;
|
|
2176
|
+
this.toolsManager.setDirectTools(policy.roots === null ? this.directTools : createDirectAgentTools(policy));
|
|
2177
|
+
}
|
|
2178
|
+
/**
|
|
2179
|
+
* Resolve roots for a provider called directly, without NeuroLink. A
|
|
2180
|
+
* policy NeuroLink already bound is left alone unless these options carry
|
|
2181
|
+
* their own. An invalid root throws, before any model request.
|
|
2182
|
+
*/
|
|
2183
|
+
applyFileToolRoots(options) {
|
|
2184
|
+
if (Object.keys(this.directTools).length === 0) {
|
|
2185
|
+
return;
|
|
2186
|
+
}
|
|
2187
|
+
const bound = boundFileToolRoots(options);
|
|
2188
|
+
if (bound !== undefined) {
|
|
2189
|
+
this.setFileToolRootPolicy(bound);
|
|
2190
|
+
return;
|
|
2191
|
+
}
|
|
2192
|
+
if (this.fileToolRootsBound && options.toolRoots === undefined) {
|
|
2193
|
+
return;
|
|
2194
|
+
}
|
|
2195
|
+
this.setFileToolRootPolicy(resolveFileToolRootPolicy({
|
|
2196
|
+
perCall: options.toolRoots,
|
|
2197
|
+
instance: this.neurolink?.getToolsConfig()?.fileRoots,
|
|
2198
|
+
}));
|
|
2199
|
+
}
|
|
2159
2200
|
async getAllTools() {
|
|
2201
|
+
// Any path that reaches tool assembly without a bound policy — an internal
|
|
2202
|
+
// caller, or a provider whose generate()/stream() skips the base entry
|
|
2203
|
+
// points — gets the instance's roots rather than the working directory.
|
|
2204
|
+
if (!this.fileToolRootsBound) {
|
|
2205
|
+
this.applyFileToolRoots({});
|
|
2206
|
+
}
|
|
2160
2207
|
return this.toolsManager.getAllTools();
|
|
2161
2208
|
}
|
|
2162
2209
|
/**
|
|
@@ -20,7 +20,7 @@ export declare function buildMCPSchemaValidator(toolName: string, schema: Record
|
|
|
20
20
|
}) | undefined>;
|
|
21
21
|
export declare class ToolsManager {
|
|
22
22
|
private readonly providerName;
|
|
23
|
-
private
|
|
23
|
+
private directTools;
|
|
24
24
|
private readonly neurolink?;
|
|
25
25
|
private readonly utilities?;
|
|
26
26
|
protected mcpTools?: Record<string, Tool>;
|
|
@@ -112,6 +112,12 @@ export declare class ToolsManager {
|
|
|
112
112
|
* Get direct tools (built-in agent tools)
|
|
113
113
|
*/
|
|
114
114
|
getDirectTools(): Record<string, unknown>;
|
|
115
|
+
/**
|
|
116
|
+
* Replace the direct tools for this provider instance — used to bind the
|
|
117
|
+
* built-in file tools to one request's root policy. Providers are created
|
|
118
|
+
* per request, so this never leaks a boundary into another request.
|
|
119
|
+
*/
|
|
120
|
+
setDirectTools(tools: Record<string, unknown>): void;
|
|
115
121
|
/**
|
|
116
122
|
* Get MCP tools
|
|
117
123
|
*/
|
|
@@ -550,6 +550,14 @@ export class ToolsManager {
|
|
|
550
550
|
getDirectTools() {
|
|
551
551
|
return this.directTools;
|
|
552
552
|
}
|
|
553
|
+
/**
|
|
554
|
+
* Replace the direct tools for this provider instance — used to bind the
|
|
555
|
+
* built-in file tools to one request's root policy. Providers are created
|
|
556
|
+
* per request, so this never leaks a boundary into another request.
|
|
557
|
+
*/
|
|
558
|
+
setDirectTools(tools) {
|
|
559
|
+
this.directTools = tools;
|
|
560
|
+
}
|
|
553
561
|
/**
|
|
554
562
|
* Get MCP tools
|
|
555
563
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -504,5 +504,6 @@ export { validateResponse } from "./utils/responseValidator.js";
|
|
|
504
504
|
export { TripwireEvaluator, createDefaultTripwireEvaluator, commonTripwires, } from "./utils/tripwireEvaluator.js";
|
|
505
505
|
export { Agent } from "./agent/agent.js";
|
|
506
506
|
export { AgentNetwork } from "./agent/agentNetwork.js";
|
|
507
|
+
export { TERMINAL_AGENT_PROMPT_V1, TERMINAL_AGENT_PROMPT_V2, TERMINAL_AGENT_PROMPT_VERSION, } from "./agent/prompts/terminalAgentPrompt.js";
|
|
507
508
|
export { AgentCoordinator, TaskDistributor, MessageBus, NetworkOrchestrator, NetworkTopology, TopologyBuilder, } from "./agent/index.js";
|
|
508
509
|
export { createLocalUsageReader, getLocalUsageDescriptors, getRegisteredLocalUsageCliIds, readAllLocalUsage, registerLocalUsageReader, } from "./localUsage/index.js";
|
package/dist/index.js
CHANGED
|
@@ -823,6 +823,7 @@ export { TripwireEvaluator, createDefaultTripwireEvaluator, commonTripwires, } f
|
|
|
823
823
|
// ============================================================================
|
|
824
824
|
export { Agent } from "./agent/agent.js";
|
|
825
825
|
export { AgentNetwork } from "./agent/agentNetwork.js";
|
|
826
|
+
export { TERMINAL_AGENT_PROMPT_V1, TERMINAL_AGENT_PROMPT_V2, TERMINAL_AGENT_PROMPT_VERSION, } from "./agent/prompts/terminalAgentPrompt.js";
|
|
826
827
|
// Advanced agent orchestration exports
|
|
827
828
|
export {
|
|
828
829
|
// Coordination
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* MCP Tool Registry - Extended Registry with Tool Management
|
|
3
3
|
* Updated to match industry standard camelCase interfaces
|
|
4
4
|
*/
|
|
5
|
-
import type { MCPServerInfo, ToolImplementation, ToolInfo, ExecutionContext, HITLManager } from "../types/index.js";
|
|
5
|
+
import type { MCPServerInfo, ToolImplementation, ToolInfo, ExecutionContext, FileToolRootPolicy, HITLManager } from "../types/index.js";
|
|
6
6
|
import { MCPRegistry } from "./registry.js";
|
|
7
7
|
export declare class MCPToolRegistry extends MCPRegistry {
|
|
8
8
|
private tools;
|
|
@@ -10,6 +10,7 @@ export declare class MCPToolRegistry extends MCPRegistry {
|
|
|
10
10
|
private toolExecutionStats;
|
|
11
11
|
private builtInServerInfos;
|
|
12
12
|
private hitlManager?;
|
|
13
|
+
private fileToolRootResolver;
|
|
13
14
|
constructor();
|
|
14
15
|
/**
|
|
15
16
|
* Set HITL manager for human-in-the-loop safety mechanisms
|
|
@@ -20,6 +21,16 @@ export declare class MCPToolRegistry extends MCPRegistry {
|
|
|
20
21
|
* Get current HITL manager
|
|
21
22
|
*/
|
|
22
23
|
getHITLManager(): HITLManager | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Resolve file-tool roots for built-in tools executed on this registry
|
|
26
|
+
* without a per-call policy. Set by the NeuroLink instance that created it.
|
|
27
|
+
*/
|
|
28
|
+
setFileToolRootResolver(resolver: () => FileToolRootPolicy): void;
|
|
29
|
+
/**
|
|
30
|
+
* The built-in tool bound to the policy that applies to this execution: one
|
|
31
|
+
* NeuroLink bound on the context, else this registry's owner's roots.
|
|
32
|
+
*/
|
|
33
|
+
private directToolFor;
|
|
23
34
|
/**
|
|
24
35
|
* Register all direct tools from directAgentTools
|
|
25
36
|
*/
|
package/dist/mcp/toolRegistry.js
CHANGED
|
@@ -6,7 +6,8 @@ import { MCPRegistry } from "./registry.js";
|
|
|
6
6
|
import { registryLogger } from "../utils/logger.js";
|
|
7
7
|
import { randomUUID } from "crypto";
|
|
8
8
|
import { shouldDisableBuiltinTools } from "../utils/toolUtils.js";
|
|
9
|
-
import { directAgentTools } from "../agent/directTools.js";
|
|
9
|
+
import { createDirectAgentTools, directAgentTools, } from "../agent/directTools.js";
|
|
10
|
+
import { boundFileToolRoots, resolveFileToolRootPolicy, } from "../utils/fileToolRoots.js";
|
|
10
11
|
import { convertZodToJsonSchema } from "../utils/schemaConversion.js";
|
|
11
12
|
import { detectCategory, createMCPServerInfo } from "../utils/mcpDefaults.js";
|
|
12
13
|
import { FlexibleToolValidator } from "./flexibleToolValidator.js";
|
|
@@ -21,6 +22,9 @@ export class MCPToolRegistry extends MCPRegistry {
|
|
|
21
22
|
toolExecutionStats = new Map();
|
|
22
23
|
builtInServerInfos = []; // DIRECT storage for MCPServerInfo
|
|
23
24
|
hitlManager; // Optional HITL manager for safety mechanisms
|
|
25
|
+
// The owning NeuroLink's file-tool roots, for callers (HTTP tool routes, CLI)
|
|
26
|
+
// that execute built-in tools on this registry without a bound policy.
|
|
27
|
+
fileToolRootResolver = () => resolveFileToolRootPolicy({});
|
|
24
28
|
constructor() {
|
|
25
29
|
super();
|
|
26
30
|
if (!shouldDisableBuiltinTools()) {
|
|
@@ -46,6 +50,25 @@ export class MCPToolRegistry extends MCPRegistry {
|
|
|
46
50
|
getHITLManager() {
|
|
47
51
|
return this.hitlManager;
|
|
48
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Resolve file-tool roots for built-in tools executed on this registry
|
|
55
|
+
* without a per-call policy. Set by the NeuroLink instance that created it.
|
|
56
|
+
*/
|
|
57
|
+
setFileToolRootResolver(resolver) {
|
|
58
|
+
this.fileToolRootResolver = resolver;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The built-in tool bound to the policy that applies to this execution: one
|
|
62
|
+
* NeuroLink bound on the context, else this registry's owner's roots.
|
|
63
|
+
*/
|
|
64
|
+
directToolFor(toolName, fallback, context) {
|
|
65
|
+
const policy = boundFileToolRoots(context) ?? this.fileToolRootResolver();
|
|
66
|
+
if (policy.roots === null) {
|
|
67
|
+
return fallback;
|
|
68
|
+
}
|
|
69
|
+
const bound = createDirectAgentTools(policy);
|
|
70
|
+
return bound[toolName] ?? fallback;
|
|
71
|
+
}
|
|
49
72
|
/**
|
|
50
73
|
* Register all direct tools from directAgentTools
|
|
51
74
|
*/
|
|
@@ -75,7 +98,8 @@ export class MCPToolRegistry extends MCPRegistry {
|
|
|
75
98
|
try {
|
|
76
99
|
// Direct tools from AI SDK expect their specific parameter structure
|
|
77
100
|
// Each tool validates its own parameters, so we safely pass them through
|
|
78
|
-
const
|
|
101
|
+
const boundTool = this.directToolFor(toolName, toolDef, context);
|
|
102
|
+
const result = await boundTool.execute(params, {
|
|
79
103
|
toolCallId: context?.sessionId || "unknown",
|
|
80
104
|
messages: [],
|
|
81
105
|
});
|
package/dist/neurolink.d.ts
CHANGED
|
@@ -1388,6 +1388,19 @@ export declare class NeuroLink {
|
|
|
1388
1388
|
* Called by `BaseProvider.applyToolFiltering` so the tool gate composes the
|
|
1389
1389
|
* instance policy with per-call options on every generate/stream call.
|
|
1390
1390
|
*/
|
|
1391
|
+
/**
|
|
1392
|
+
* The policy an entry point bound to `options`, or — for an internal path
|
|
1393
|
+
* that built its own options — the instance policy narrowed by any
|
|
1394
|
+
* per-call `toolRoots`. Never trusts a public field.
|
|
1395
|
+
*/
|
|
1396
|
+
private fileToolRootsFor;
|
|
1397
|
+
/**
|
|
1398
|
+
* A worker's tool config: it inherits this instance's file-tool roots, and a
|
|
1399
|
+
* worker-level `fileRoots` may only narrow them (throws otherwise).
|
|
1400
|
+
*/
|
|
1401
|
+
private workerToolsConfig;
|
|
1402
|
+
/** File-tool roots for one call: per-call roots narrow the instance's `tools.fileRoots`. */
|
|
1403
|
+
private resolveFileToolRoots;
|
|
1391
1404
|
getToolsConfig(): ToolConfig | undefined;
|
|
1392
1405
|
/**
|
|
1393
1406
|
* Tools discovered via `search_tools` for a session (`tools.discovery`
|