@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.
Files changed (42) hide show
  1. package/CHANGELOG.md +2 -2
  2. package/dist/agent/directTools.d.ts +118 -94
  3. package/dist/agent/directTools.js +578 -446
  4. package/dist/agent/index.d.ts +1 -0
  5. package/dist/agent/index.js +1 -0
  6. package/dist/agent/prompts/terminalAgentPrompt.d.ts +13 -0
  7. package/dist/agent/prompts/terminalAgentPrompt.js +59 -0
  8. package/dist/browser/neurolink.min.js +384 -378
  9. package/dist/cli/factories/commandFactory.d.ts +25 -0
  10. package/dist/cli/factories/commandFactory.js +78 -8
  11. package/dist/cli/loop/optionsSchema.d.ts +1 -1
  12. package/dist/core/baseProvider.d.ts +17 -1
  13. package/dist/core/baseProvider.js +48 -1
  14. package/dist/core/modules/ToolsManager.d.ts +7 -1
  15. package/dist/core/modules/ToolsManager.js +8 -0
  16. package/dist/index.d.ts +1 -0
  17. package/dist/index.js +1 -0
  18. package/dist/mcp/toolRegistry.d.ts +12 -1
  19. package/dist/mcp/toolRegistry.js +26 -2
  20. package/dist/neurolink.d.ts +13 -0
  21. package/dist/neurolink.js +97 -10
  22. package/dist/session/globalSessionState.d.ts +8 -0
  23. package/dist/session/globalSessionState.js +17 -0
  24. package/dist/types/agentMode.d.ts +9 -0
  25. package/dist/types/agentMode.js +1 -0
  26. package/dist/types/cli.d.ts +6 -0
  27. package/dist/types/config.d.ts +9 -0
  28. package/dist/types/fileToolRoots.d.ts +17 -0
  29. package/dist/types/fileToolRoots.js +7 -0
  30. package/dist/types/generate.d.ts +17 -0
  31. package/dist/types/index.d.ts +2 -0
  32. package/dist/types/index.js +2 -0
  33. package/dist/types/providers.d.ts +6 -0
  34. package/dist/types/stream.d.ts +7 -0
  35. package/dist/types/tools.d.ts +7 -0
  36. package/dist/utils/fileToolRoots.d.ts +34 -0
  37. package/dist/utils/fileToolRoots.js +111 -0
  38. package/dist/utils/messageBuilder.js +32 -1
  39. package/dist/utils/pathSandbox.d.ts +9 -6
  40. package/dist/utils/pathSandbox.js +35 -9
  41. package/docs-site/static/search-index.json +6 -5
  42. package/package.json +6 -2
package/dist/neurolink.js CHANGED
@@ -62,6 +62,7 @@ import { createSkillCallTools, createSkillTools } from "./skills/skillTools.js";
62
62
  import { getMetricsAggregator, MetricsAggregator, } from "./observability/metricsAggregator.js";
63
63
  import { AnalyticsService, calculateAdvancedCost, parseAnalyticsQualityScore, } from "./analytics/index.js";
64
64
  import { SpanStatus, SpanType, CircuitBreakerOpenError, ConversationMemoryError, ModelAccessDeniedError, } from "./types/index.js";
65
+ import { resolveTerminalAgentMode } from "./agent/prompts/terminalAgentPrompt.js";
65
66
  import { SpanSerializer } from "./observability/utils/spanSerializer.js";
66
67
  import { withSpan } from "./telemetry/withSpan.js";
67
68
  import { getActiveTraceContext } from "./telemetry/traceContext.js";
@@ -99,6 +100,7 @@ import { isZodSchema, convertZodToJsonSchema, } from "./utils/schemaConversion.j
99
100
  import { resolveToolPolicy } from "./tools/toolPolicy.js";
100
101
  import { applyToolGate } from "./tools/toolGate.js";
101
102
  import { directAgentTools } from "./agent/directTools.js";
103
+ import { bindFileToolRoots, boundFileToolRoots, resolveFileToolRootPolicy, } from "./utils/fileToolRoots.js";
102
104
  import { BinaryTaskClassifier } from "./utils/taskClassifier.js";
103
105
  // Tool detection and execution imports
104
106
  // Transformation utilities
@@ -899,7 +901,15 @@ export class NeuroLink {
899
901
  return metricsTraceContextStorage.getStore() ?? null;
900
902
  }
901
903
  constructor(config) {
902
- this.toolRegistry = config?.toolRegistry || new MCPToolRegistry();
904
+ if (config?.toolRegistry) {
905
+ // A supplied registry (a host's, shared with a worker) keeps its owner's
906
+ // roots; per-call executeTool() binds this instance's policy anyway.
907
+ this.toolRegistry = config.toolRegistry;
908
+ }
909
+ else {
910
+ this.toolRegistry = new MCPToolRegistry();
911
+ this.toolRegistry.setFileToolRootResolver(() => this.resolveFileToolRoots(undefined));
912
+ }
903
913
  this.fileRegistry = new FileReferenceRegistry();
904
914
  this.observabilityConfig = config?.observability;
905
915
  this.analyticsService = new AnalyticsService();
@@ -3310,6 +3320,9 @@ Current user's request: ${currentInput}`;
3310
3320
  // String prompts are immutable, so they pass through.
3311
3321
  if (typeof optionsOrPrompt !== "string") {
3312
3322
  optionsOrPrompt = cloneOptionsForCallIsolation(optionsOrPrompt);
3323
+ // Resolved once per call and always overwrites a caller-supplied
3324
+ // policy; an invalid root fails here, before any model call.
3325
+ bindFileToolRoots(optionsOrPrompt, this.resolveFileToolRoots(optionsOrPrompt.toolRoots));
3313
3326
  // The deprecated `conversationHistory` field is not wired into message
3314
3327
  // building — messages passed there never reach the model, which reads
3315
3328
  // as "the SDK forgot my context" rather than a caller bug. Warn loudly
@@ -3321,6 +3334,20 @@ Current user's request: ${currentInput}`;
3321
3334
  logger.warn("[NeuroLink.generate] `conversationHistory` is deprecated and NOT passed to the model — use `conversationMessages` (ChatMessage[]) instead.");
3322
3335
  }
3323
3336
  }
3337
+ // Resolved once here and removed from the options, so no internal
3338
+ // re-entrant generate() can prepend the agent instructions twice.
3339
+ let agentModeVersion;
3340
+ if (typeof optionsOrPrompt !== "string") {
3341
+ const { agentMode, ...rest } = optionsOrPrompt;
3342
+ if (agentMode !== undefined) {
3343
+ const resolved = resolveTerminalAgentMode(agentMode, rest.systemPrompt);
3344
+ agentModeVersion = resolved.version;
3345
+ optionsOrPrompt = {
3346
+ ...rest,
3347
+ systemPrompt: resolved.systemPrompt,
3348
+ };
3349
+ }
3350
+ }
3324
3351
  // Retrieve once at the public call boundary so fallback attempts reuse the
3325
3352
  // same grounding block and internal preparation cannot inject it twice.
3326
3353
  const groundingOptions = typeof optionsOrPrompt === "string"
@@ -3348,6 +3375,9 @@ Current user's request: ${currentInput}`;
3348
3375
  if (knowledgeOutcome) {
3349
3376
  result.knowledge = knowledgeOutcome.metadata;
3350
3377
  }
3378
+ if (agentModeVersion) {
3379
+ result.agentModeVersion = agentModeVersion;
3380
+ }
3351
3381
  return result;
3352
3382
  }
3353
3383
  catch (error) {
@@ -4198,6 +4228,7 @@ Current user's request: ${currentInput}`;
4198
4228
  // (which spreads its options) honoured it.
4199
4229
  disableInternalFallback: options.disableInternalFallback,
4200
4230
  maxSteps: options.maxSteps,
4231
+ toolRoots: options.toolRoots,
4201
4232
  toolChoice: options.toolChoice,
4202
4233
  prepareStep: options.prepareStep,
4203
4234
  enabledToolNames: options.enabledToolNames,
@@ -4266,7 +4297,7 @@ Current user's request: ${currentInput}`;
4266
4297
  : {}),
4267
4298
  };
4268
4299
  }
4269
- const textOptions = enhanceTextGenerationOptions(baseOptions, factoryResult);
4300
+ const textOptions = bindFileToolRoots(enhanceTextGenerationOptions(baseOptions, factoryResult), this.fileToolRootsFor(options));
4270
4301
  if (this.conversationMemory) {
4271
4302
  textOptions.conversationMemoryConfig = this.conversationMemory.config;
4272
4303
  textOptions.originalPrompt = originalPrompt;
@@ -4943,10 +4974,15 @@ Current user's request: ${currentInput}`;
4943
4974
  options.prompt.trim() === "") {
4944
4975
  throw new Error("GenerateText options must include prompt as a non-empty string");
4945
4976
  }
4977
+ // Isolate from the caller's object, then resolve file-tool roots exactly
4978
+ // as generate() does: a widening or missing root rejects here, before any
4979
+ // model call, and the resolved policy travels on the private channel.
4980
+ const isolated = cloneOptionsForCallIsolation(options);
4946
4981
  // NL-004: Resolve model aliases/deprecations before processing
4947
- options.model = resolveModel(options.model, this.modelAliasConfig);
4982
+ isolated.model = resolveModel(isolated.model, this.modelAliasConfig);
4983
+ bindFileToolRoots(isolated, this.resolveFileToolRoots(isolated.toolRoots));
4948
4984
  // Use internal generation method directly
4949
- return await this.generateTextInternal(options);
4985
+ return await this.generateTextInternal(isolated);
4950
4986
  }
4951
4987
  /**
4952
4988
  * REDESIGNED INTERNAL GENERATION - NO CIRCULAR DEPENDENCIES
@@ -5940,6 +5976,7 @@ Current user's request: ${currentInput}`;
5940
5976
  maxSteps: options.maxSteps,
5941
5977
  skipToolPromptInjection: options.skipToolPromptInjection,
5942
5978
  });
5979
+ provider.setFileToolRootPolicy?.(this.fileToolRootsFor(options));
5943
5980
  const result = await provider.generate({
5944
5981
  ...options,
5945
5982
  systemPrompt: enhancedSystemPrompt,
@@ -6108,6 +6145,7 @@ Current user's request: ${currentInput}`;
6108
6145
  disableToolCache: options.disableToolCache,
6109
6146
  }),
6110
6147
  }, functionTag);
6148
+ poolProvider.setFileToolRootPolicy?.(this.fileToolRootsFor(options));
6111
6149
  const poolResult = await poolProvider.generate({
6112
6150
  ...options,
6113
6151
  conversationMessages: poolConversationMessages,
@@ -6482,6 +6520,7 @@ Current user's request: ${currentInput}`;
6482
6520
  disableToolCache: options.disableToolCache,
6483
6521
  }),
6484
6522
  }, functionTag);
6523
+ provider.setFileToolRootPolicy?.(this.fileToolRootsFor(options));
6485
6524
  const result = await provider.generate({
6486
6525
  ...options,
6487
6526
  conversationMessages, // Inject conversation history
@@ -6830,6 +6869,16 @@ Current user's request: ${currentInput}`;
6830
6869
  // shallow rebind at the orchestration site only covered the
6831
6870
  // top-level keys and left `options.input` shared with the caller.
6832
6871
  options = cloneOptionsForCallIsolation(options);
6872
+ let agentModeVersion;
6873
+ {
6874
+ const { agentMode, ...rest } = options;
6875
+ if (agentMode !== undefined) {
6876
+ const resolved = resolveTerminalAgentMode(agentMode, rest.systemPrompt);
6877
+ agentModeVersion = resolved.version;
6878
+ options = { ...rest, systemPrompt: resolved.systemPrompt };
6879
+ }
6880
+ }
6881
+ bindFileToolRoots(options, this.resolveFileToolRoots(options.toolRoots));
6833
6882
  const startedAt = Date.now();
6834
6883
  // Retrieve once before provider/model fallback orchestration. Every fallback
6835
6884
  // receives the same explicitly enriched options, without the retrieval helper
@@ -6847,6 +6896,9 @@ Current user's request: ${currentInput}`;
6847
6896
  if (knowledgeOutcome) {
6848
6897
  result.knowledge = knowledgeOutcome.metadata;
6849
6898
  }
6899
+ if (agentModeVersion) {
6900
+ result.agentModeVersion = agentModeVersion;
6901
+ }
6850
6902
  return result;
6851
6903
  }
6852
6904
  catch (error) {
@@ -8415,6 +8467,7 @@ Current user's request: ${currentInput}`;
8415
8467
  prompt: enhancedOptions.input.text,
8416
8468
  context: enhancedOptions.context,
8417
8469
  });
8470
+ fallbackProvider.setFileToolRootPolicy?.(this.fileToolRootsFor(enhancedOptions));
8418
8471
  const fallbackResult = await fallbackProvider.stream({
8419
8472
  ...this.deferProviderStreamTTS(enhancedOptions),
8420
8473
  model: fallbackRoute.model,
@@ -8846,6 +8899,7 @@ Current user's request: ${currentInput}`;
8846
8899
  disableToolCache: options.disableToolCache,
8847
8900
  }),
8848
8901
  }, "NeuroLink.createMCPStream");
8902
+ poolStreamProvider.setFileToolRootPolicy?.(this.fileToolRootsFor(options));
8849
8903
  const poolStreamResult = await poolStreamProvider.stream({
8850
8904
  ...this.deferProviderStreamTTS(options),
8851
8905
  provider: poolStreamProviderName,
@@ -8925,6 +8979,7 @@ Current user's request: ${currentInput}`;
8925
8979
  // ─── End ModelPool stream path ────────────────────────────────────────────
8926
8980
  // 🔧 FIX: Pass enhanced system prompt to real streaming
8927
8981
  // Tools will be accessed through the streamText call in executeStream
8982
+ provider.setFileToolRootPolicy?.(this.fileToolRootsFor(options));
8928
8983
  const streamResult = await provider.stream({
8929
8984
  ...this.deferProviderStreamTTS(options),
8930
8985
  systemPrompt: enhancedSystemPrompt, // Use enhanced prompt with tool descriptions
@@ -9048,6 +9103,7 @@ Current user's request: ${currentInput}`;
9048
9103
  const responseTime = Date.now() - startTime;
9049
9104
  const providerName = await getBestProvider(options.provider);
9050
9105
  const provider = await AIProviderFactory.createProvider(providerName, options.model, true, undefined, undefined, this.resolveCredentials(options.credentials));
9106
+ provider.setFileToolRootPolicy?.(this.fileToolRootsFor(options));
9051
9107
  const fallbackStreamResult = await provider.stream({
9052
9108
  input: { text: options.input.text },
9053
9109
  model: options.model,
@@ -9422,6 +9478,39 @@ Current user's request: ${currentInput}`;
9422
9478
  * Called by `BaseProvider.applyToolFiltering` so the tool gate composes the
9423
9479
  * instance policy with per-call options on every generate/stream call.
9424
9480
  */
9481
+ /**
9482
+ * The policy an entry point bound to `options`, or — for an internal path
9483
+ * that built its own options — the instance policy narrowed by any
9484
+ * per-call `toolRoots`. Never trusts a public field.
9485
+ */
9486
+ fileToolRootsFor(options) {
9487
+ return (boundFileToolRoots(options) ??
9488
+ this.resolveFileToolRoots(options.toolRoots));
9489
+ }
9490
+ /**
9491
+ * A worker's tool config: it inherits this instance's file-tool roots, and a
9492
+ * worker-level `fileRoots` may only narrow them (throws otherwise).
9493
+ */
9494
+ workerToolsConfig(override) {
9495
+ const hostRoots = this.toolsConfig?.fileRoots;
9496
+ if (override?.fileRoots === undefined) {
9497
+ return hostRoots === undefined
9498
+ ? override
9499
+ : { ...override, fileRoots: hostRoots };
9500
+ }
9501
+ const narrowed = resolveFileToolRootPolicy({
9502
+ perCall: override.fileRoots,
9503
+ instance: hostRoots,
9504
+ }).roots;
9505
+ return { ...override, fileRoots: narrowed ? [...narrowed] : [] };
9506
+ }
9507
+ /** File-tool roots for one call: per-call roots narrow the instance's `tools.fileRoots`. */
9508
+ resolveFileToolRoots(perCall) {
9509
+ return resolveFileToolRootPolicy({
9510
+ perCall,
9511
+ instance: this.toolsConfig?.fileRoots,
9512
+ });
9513
+ }
9425
9514
  getToolsConfig() {
9426
9515
  return this.toolsConfig;
9427
9516
  }
@@ -10679,11 +10768,8 @@ Current user's request: ${currentInput}`;
10679
10768
  try {
10680
10769
  const storedContext = this.toolExecutionContext || {};
10681
10770
  const passedAuthContext = options.authContext || {};
10682
- const context = {
10683
- ...storedContext,
10684
- ...passedAuthContext,
10685
- hitlState: HITLState,
10686
- };
10771
+ // This instance's roots, on the private channel (overwrites the caller's).
10772
+ const context = bindFileToolRoots({ ...storedContext, ...passedAuthContext, hitlState: HITLState }, this.resolveFileToolRoots(undefined));
10687
10773
  logger.debug(`[Using merged context for unified registry tool:`, {
10688
10774
  toolName,
10689
10775
  storedContextKeys: Object.keys(storedContext),
@@ -13206,7 +13292,8 @@ Current user's request: ${currentInput}`;
13206
13292
  toolRegistry: this.toolRegistry,
13207
13293
  }),
13208
13294
  };
13209
- const worker = new NeuroLink(workerConfig);
13295
+ const workerTools = this.workerToolsConfig(configOverrides.tools);
13296
+ const worker = new NeuroLink(workerTools ? { ...workerConfig, tools: workerTools } : workerConfig);
13210
13297
  // The cacheable:false flag lives BESIDE the registry, not in it, so a
13211
13298
  // shared registry alone would re-enable caching on the worker for exactly
13212
13299
  // the tools whose results are live state (tasks_list, command_status,
@@ -9,6 +9,7 @@ export declare class GlobalSessionManager {
9
9
  private _classifierRouterConfig;
10
10
  /** Optional skills config set by CLI handlers before SDK construction. */
11
11
  private _skillsConfig;
12
+ private _fileToolRoots;
12
13
  static getInstance(): GlobalSessionManager;
13
14
  setLoopSession(config?: ConversationMemoryConfig): string;
14
15
  /**
@@ -60,6 +61,13 @@ export declare class GlobalSessionManager {
60
61
  * already exists).
61
62
  */
62
63
  setSkillsConfig(config: SkillsConfig): void;
64
+ /**
65
+ * Store file-tool roots (`--tool-root`) to be injected at SDK construction
66
+ * time as `tools.fileRoots`. Call this BEFORE `getOrCreateNeuroLink()`.
67
+ * When a loop session is already active the roots are ignored (the
68
+ * instance already exists).
69
+ */
70
+ setFileToolRoots(roots: string[] | undefined): void;
63
71
  getOrCreateNeuroLink(): NeuroLink;
64
72
  getCurrentSessionId(): string | undefined;
65
73
  setSessionVariable(key: string, value: SessionVariableValue): void;
@@ -37,6 +37,7 @@ export class GlobalSessionManager {
37
37
  _classifierRouterConfig = undefined;
38
38
  /** Optional skills config set by CLI handlers before SDK construction. */
39
39
  _skillsConfig = undefined;
40
+ _fileToolRoots = undefined;
40
41
  static getInstance() {
41
42
  if (!GlobalSessionManager.instance) {
42
43
  GlobalSessionManager.instance = new GlobalSessionManager();
@@ -169,6 +170,18 @@ export class GlobalSessionManager {
169
170
  }
170
171
  this._skillsConfig = config;
171
172
  }
173
+ /**
174
+ * Store file-tool roots (`--tool-root`) to be injected at SDK construction
175
+ * time as `tools.fileRoots`. Call this BEFORE `getOrCreateNeuroLink()`.
176
+ * When a loop session is already active the roots are ignored (the
177
+ * instance already exists).
178
+ */
179
+ setFileToolRoots(roots) {
180
+ if (this.hasActiveSession() || !roots?.length) {
181
+ return;
182
+ }
183
+ this._fileToolRoots = roots;
184
+ }
172
185
  getOrCreateNeuroLink() {
173
186
  const session = this.getLoopSession();
174
187
  if (session) {
@@ -196,6 +209,10 @@ export class GlobalSessionManager {
196
209
  options.skills = this._skillsConfig;
197
210
  this._skillsConfig = undefined;
198
211
  }
212
+ if (this._fileToolRoots) {
213
+ options.tools = { ...options.tools, fileRoots: this._fileToolRoots };
214
+ this._fileToolRoots = undefined;
215
+ }
199
216
  return new NeuroLink(Object.keys(options).length ? options : undefined);
200
217
  }
201
218
  getCurrentSessionId() {
@@ -0,0 +1,9 @@
1
+ /** Version of the terminal agent instructions applied by `agentMode`. */
2
+ export type TerminalAgentModeVersion = "1" | "2";
3
+ /**
4
+ * Opt-in terminal agent mode. `true` applies the current instructions; the
5
+ * object form pins a version so results stay comparable across releases.
6
+ */
7
+ export type TerminalAgentModeOption = boolean | {
8
+ version?: TerminalAgentModeVersion;
9
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -55,6 +55,8 @@ export type GenerateCommandArgs = BaseCommandArgs & CliToolRoutingFlags & CliCla
55
55
  model?: string;
56
56
  /** System prompt */
57
57
  system?: string;
58
+ /** Prepend Neurolink's versioned terminal agent instructions */
59
+ agentMode?: boolean;
58
60
  /** Temperature setting */
59
61
  temperature?: number;
60
62
  /** Maximum tokens */
@@ -120,6 +122,10 @@ export type StreamCommandArgs = BaseCommandArgs & CliToolRoutingFlags & CliClass
120
122
  model?: string;
121
123
  /** System prompt */
122
124
  system?: string;
125
+ /** Prepend Neurolink's versioned terminal agent instructions */
126
+ agentMode?: boolean;
127
+ /** Maximum tool-calling steps */
128
+ maxSteps?: number;
123
129
  /** Temperature setting */
124
130
  temperature?: number;
125
131
  /** Maximum tokens */
@@ -427,6 +427,15 @@ export type ToolConfig = {
427
427
  enableMCPTools?: boolean;
428
428
  /** Whether the bash command execution tool should be enabled (opt-in, defaults to false) */
429
429
  enableBashTool?: boolean;
430
+ /**
431
+ * Directories the built-in file tools (readFile, listDirectory, writeFile,
432
+ * analyzeCSV) and bash's `cwd` argument may touch. Resolved through
433
+ * symlinks; each must be an existing directory. Default: the process
434
+ * working directory. An empty array denies all file access. Per-call
435
+ * `toolRoots` can only narrow this list. Roots do not sandbox the shell
436
+ * commands themselves — a command can still `cd` anywhere.
437
+ */
438
+ fileRoots?: string[];
430
439
  /**
431
440
  * Byte ceiling for the safety-net truncation `ToolsManager` applies to
432
441
  * every direct/custom/external-MCP tool result before it reaches the AI
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Filesystem roots for the built-in file tools — types.
3
+ *
4
+ * Naming: `pathSandbox.ts` owns `PathSandbox*` and `file.ts` owns `FilePath*`,
5
+ * so this carries the `FileToolRoot` prefix (Critical Rule 9).
6
+ */
7
+ /**
8
+ * The directories the built-in file tools (readFile, listDirectory,
9
+ * writeFile, analyzeCSV) and bash's `cwd` argument may touch for one request.
10
+ *
11
+ * `roots` are real, existing directories resolved once when the request
12
+ * starts. `null` means the historical default: the process working
13
+ * directory, read at call time. An empty array denies all file access.
14
+ */
15
+ export type FileToolRootPolicy = {
16
+ readonly roots: readonly string[] | null;
17
+ };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Filesystem roots for the built-in file tools — types.
3
+ *
4
+ * Naming: `pathSandbox.ts` owns `PathSandbox*` and `file.ts` owns `FilePath*`,
5
+ * so this carries the `FileToolRoot` prefix (Critical Rule 9).
6
+ */
7
+ export {};
@@ -5,6 +5,7 @@ import type { SkillsCallOptions } from "./skills.js";
5
5
  import type { AnalyticsData, TokenUsage } from "./analytics.js";
6
6
  import type { ClaudeLimitSnapshot } from "./subscription.js";
7
7
  import type { JsonValue } from "./common.js";
8
+ import type { TerminalAgentModeOption, TerminalAgentModeVersion } from "./agentMode.js";
8
9
  import type { Content, ImageWithAltText } from "./content.js";
9
10
  import type { ChatMessage, ConversationMemoryConfig } from "./conversation.js";
10
11
  import type { EvaluationData } from "./evaluation.js";
@@ -310,6 +311,11 @@ export type GenerateOptions = {
310
311
  /** Stop sequences that will halt generation when encountered. */
311
312
  stopSequences?: string[];
312
313
  systemPrompt?: string;
314
+ /**
315
+ * Opt-in terminal agent mode: prepends Neurolink's versioned autonomous-agent
316
+ * instructions to `systemPrompt`. Omitted means no change in behaviour.
317
+ */
318
+ agentMode?: TerminalAgentModeOption;
313
319
  /**
314
320
  * Zod schema for structured output validation
315
321
  *
@@ -517,6 +523,13 @@ export type GenerateOptions = {
517
523
  disableInternalFallback?: boolean;
518
524
  /** Maximum number of tool execution steps (default: 200) */
519
525
  maxSteps?: number;
526
+ /**
527
+ * Directories the built-in file tools and bash's `cwd` argument may touch
528
+ * for this call. Can only narrow the instance's `tools.fileRoots` (or the
529
+ * working-directory default); a root outside them is rejected before any
530
+ * model call. An empty array denies all file access.
531
+ */
532
+ toolRoots?: string[];
520
533
  /**
521
534
  * Tool choice configuration for the generation.
522
535
  * Controls whether and which tools the model must call.
@@ -985,6 +998,8 @@ export type GenerateResult = {
985
998
  content: string;
986
999
  /** Knowledge-grounding diagnostics for this turn (present only when grounding ran). */
987
1000
  knowledge?: KnowledgeGroundingMetadata;
1001
+ /** Terminal agent instructions version applied (present only with `agentMode`). */
1002
+ agentModeVersion?: TerminalAgentModeVersion;
988
1003
  /**
989
1004
  * Parsed structured object when a `schema` was requested. Populated from
990
1005
  * AI-SDK experimental_output, or from text-mode coercion (balanced-scan +
@@ -1281,6 +1296,8 @@ export type TextGenerationOptions = {
1281
1296
  /** Disable the schema-driven tool call repair mechanism (BZ-665). Default: false (repair enabled). */
1282
1297
  disableToolCallRepair?: boolean;
1283
1298
  maxSteps?: number;
1299
+ /** Directories the built-in file tools may touch for this call; see GenerateOptions.toolRoots. */
1300
+ toolRoots?: string[];
1284
1301
  /** Include only these tools by name (whitelist). If set, only matching tools are available. */
1285
1302
  toolFilter?: string[];
1286
1303
  /** Exclude these tools by name (blacklist). Applied after toolFilter. */
@@ -4,6 +4,7 @@
4
4
  */
5
5
  export * from "./enums.js";
6
6
  export * from "./action.js";
7
+ export * from "./agentMode.js";
7
8
  export * from "./aliases.js";
8
9
  export * from "./analytics.js";
9
10
  export * from "./artifact.js";
@@ -23,6 +24,7 @@ export * from "./delegation.js";
23
24
  export * from "./backgroundCommand.js";
24
25
  export * from "./gitTools.js";
25
26
  export * from "./pathSandbox.js";
27
+ export * from "./fileToolRoots.js";
26
28
  export * from "./domain.js";
27
29
  export * from "./errors.js";
28
30
  export * from "./evaluation.js";
@@ -5,6 +5,7 @@
5
5
  // All type files (alphabetical)
6
6
  export * from "./enums.js";
7
7
  export * from "./action.js";
8
+ export * from "./agentMode.js";
8
9
  export * from "./aliases.js";
9
10
  export * from "./analytics.js";
10
11
  export * from "./artifact.js";
@@ -27,6 +28,7 @@ export * from "./backgroundCommand.js";
27
28
  export * from "./gitTools.js";
28
29
  // Path containment guard shared by the sandboxed execution paths
29
30
  export * from "./pathSandbox.js";
31
+ export * from "./fileToolRoots.js";
30
32
  export * from "./domain.js";
31
33
  export * from "./errors.js";
32
34
  export * from "./evaluation.js";
@@ -6,6 +6,7 @@ import type { NeuroLink } from "../neurolink.js";
6
6
  import { AIProviderName, AnthropicModels, BedrockModels, DeepSeekModels, GoogleAIModels, LlamaCppModels, LMStudioModels, NvidiaNimModels, OpenAIModels, VertexModels } from "../constants/enums.js";
7
7
  import type { ValidationSchema } from "./aliases.js";
8
8
  import type { DecisionLimits, DecisionRequest, DecisionResult } from "./decision.js";
9
+ import type { FileToolRootPolicy } from "./fileToolRoots.js";
9
10
  import type { EnhancedGenerateResult, TextGenerationOptions } from "./generate.js";
10
11
  import type { MultimodalAudioEntry, MultimodalVideoEntry } from "./file.js";
11
12
  import type { StreamOptions, StreamResult } from "./stream.js";
@@ -833,6 +834,11 @@ export type AIProvider = {
833
834
  traceId: string;
834
835
  parentSpanId: string;
835
836
  } | null): void;
837
+ /**
838
+ * Bind the built-in file tools to one request's root policy. Optional so
839
+ * custom provider implementations keep compiling; BaseProvider implements it.
840
+ */
841
+ setFileToolRootPolicy?(policy: FileToolRootPolicy | undefined): void;
836
842
  /**
837
843
  * Whether this provider supports native tool/function calling for the
838
844
  * current model. Implemented by BaseProvider (default true); overridden by
@@ -7,6 +7,7 @@ import type { AnalyticsData, ToolExecutionEvent, ToolExecutionSummary } from "..
7
7
  import type { MiddlewareFactoryOptions, OnChunkCallback, OnErrorCallback, OnFinishCallback } from "../types/middleware.js";
8
8
  import type { TokenUsage } from "./analytics.js";
9
9
  import type { JsonValue, UnknownRecord } from "./common.js";
10
+ import type { TerminalAgentModeOption, TerminalAgentModeVersion } from "./agentMode.js";
10
11
  import type { Content, ImageWithAltText } from "./content.js";
11
12
  import type { ChatMessage } from "./conversation.js";
12
13
  import type { StreamNoOutputSentinel } from "./noOutputSentinel.js";
@@ -504,6 +505,8 @@ export type StreamOptions = {
504
505
  /** Stop sequences that will halt generation when encountered. */
505
506
  stopSequences?: string[];
506
507
  systemPrompt?: string;
508
+ /** Opt-in terminal agent mode. See GenerateOptions.agentMode. */
509
+ agentMode?: TerminalAgentModeOption;
507
510
  schema?: ValidationSchema;
508
511
  tools?: Record<string, Tool>;
509
512
  timeout?: number | string;
@@ -550,6 +553,8 @@ export type StreamOptions = {
550
553
  /** Disable the schema-driven tool call repair mechanism (BZ-665). Default: false (repair enabled). */
551
554
  disableToolCallRepair?: boolean;
552
555
  maxSteps?: number;
556
+ /** Directories the built-in file tools may touch for this call; see GenerateOptions.toolRoots; can only narrow tools.fileRoots. */
557
+ toolRoots?: string[];
553
558
  /**
554
559
  * Tool choice configuration for streaming generation.
555
560
  * Mirrors generate() so translated/fallback requests can preserve forced tool use.
@@ -777,6 +782,8 @@ export type StreamOptions = {
777
782
  export type StreamResult = {
778
783
  /** Knowledge-grounding diagnostics for this turn (present only when grounding ran). */
779
784
  knowledge?: KnowledgeGroundingMetadata;
785
+ /** Terminal agent instructions version applied (present only with `agentMode`). */
786
+ agentModeVersion?: TerminalAgentModeVersion;
780
787
  stream: AsyncIterable<{
781
788
  content: string;
782
789
  reasoning?: string;
@@ -412,6 +412,13 @@ export type SdkSimpleTool<TArgs = ToolArgs, TResult = JsonValue> = Omit<SimpleTo
412
412
  [key: string]: JsonValue | undefined;
413
413
  };
414
414
  };
415
+ /** Arguments of the built-in analyzeCSV tool, after schema defaults. */
416
+ export type AnalyzeCsvToolArgs = {
417
+ filePath: string;
418
+ operation: "count_by_column" | "sum_by_column" | "average_by_column" | "min_max_by_column" | "describe";
419
+ column: string;
420
+ maxRows?: number;
421
+ };
415
422
  /** Subset of directAgentTools exposing only the "basic" category. */
416
423
  export type BasicToolsMap = {
417
424
  getCurrentTime: Tool;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Resolve which directories the built-in file tools may touch for a request.
3
+ *
4
+ * Precedence follows the credential pattern: per-call beats instance, and
5
+ * instance beats the `NEUROLINK_TOOL_ROOTS` environment variable. The
6
+ * instance list (or the environment, or the working directory) is a
7
+ * ceiling — per-call roots may only narrow it, so a server that forwards
8
+ * caller options cannot be talked into widening file access.
9
+ *
10
+ * Every root is resolved through realpath once, here, so a root reached
11
+ * through a symlink (`/home/user` → `/home/agent`) admits its own files, and
12
+ * a later `chdir` cannot move the boundary mid-request.
13
+ *
14
+ * @module utils/fileToolRoots
15
+ */
16
+ import type { FileToolRootPolicy } from "../types/index.js";
17
+ /**
18
+ * The file-tool root policy for one request.
19
+ *
20
+ * Returns `{ roots: null }` when nothing is configured anywhere, which keeps
21
+ * the historical behaviour: the working directory, read at call time.
22
+ *
23
+ * @throws when a root does not exist, is not a directory, or a per-call root
24
+ * lies outside the instance ceiling. Callers invoke this before any model
25
+ * request so a misconfiguration fails fast.
26
+ */
27
+ export declare function resolveFileToolRootPolicy(input: {
28
+ perCall?: readonly string[];
29
+ instance?: readonly string[];
30
+ }): FileToolRootPolicy;
31
+ /** Attach a resolved policy to `target` (an options bag or execution context). */
32
+ export declare function bindFileToolRoots<T extends object>(target: T, policy: FileToolRootPolicy): T;
33
+ /** The policy bound by {@link bindFileToolRoots}, if any. */
34
+ export declare function boundFileToolRoots(source: unknown): FileToolRootPolicy | undefined;