@juspay/neurolink 7.30.1 → 7.32.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.
Files changed (37) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cli/factories/commandFactory.js +16 -2
  3. package/dist/core/baseProvider.d.ts +6 -6
  4. package/dist/core/baseProvider.js +30 -34
  5. package/dist/core/types.d.ts +2 -0
  6. package/dist/index.d.ts +1 -1
  7. package/dist/lib/core/baseProvider.d.ts +6 -6
  8. package/dist/lib/core/baseProvider.js +30 -34
  9. package/dist/lib/core/types.d.ts +2 -0
  10. package/dist/lib/index.d.ts +1 -1
  11. package/dist/lib/middleware/builtin/analytics.d.ts +1 -1
  12. package/dist/lib/middleware/builtin/guardrails.d.ts +1 -1
  13. package/dist/lib/middleware/factory.d.ts +1 -1
  14. package/dist/lib/middleware/index.d.ts +1 -1
  15. package/dist/lib/middleware/registry.d.ts +1 -1
  16. package/dist/lib/neurolink.js +32 -18
  17. package/dist/lib/providers/googleAiStudio.d.ts +1 -0
  18. package/dist/lib/providers/googleAiStudio.js +196 -0
  19. package/dist/lib/providers/googleVertex.js +4 -1
  20. package/dist/lib/types/streamTypes.d.ts +20 -1
  21. package/dist/lib/utils/optionsConversion.js +1 -1
  22. package/dist/middleware/builtin/analytics.d.ts +1 -1
  23. package/dist/middleware/builtin/guardrails.d.ts +1 -1
  24. package/dist/middleware/factory.d.ts +1 -1
  25. package/dist/middleware/index.d.ts +1 -1
  26. package/dist/middleware/registry.d.ts +1 -1
  27. package/dist/neurolink.js +32 -18
  28. package/dist/providers/googleAiStudio.d.ts +1 -0
  29. package/dist/providers/googleAiStudio.js +196 -0
  30. package/dist/providers/googleVertex.js +4 -1
  31. package/dist/types/streamTypes.d.ts +20 -1
  32. package/dist/utils/optionsConversion.js +1 -1
  33. package/package.json +3 -1
  34. /package/dist/lib/{middleware/types.d.ts → types/middlewareTypes.d.ts} +0 -0
  35. /package/dist/lib/{middleware/types.js → types/middlewareTypes.js} +0 -0
  36. /package/dist/{middleware/types.d.ts → types/middlewareTypes.d.ts} +0 -0
  37. /package/dist/{middleware/types.js → types/middlewareTypes.js} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## [7.32.0](https://github.com/juspay/neurolink/compare/v7.31.0...v7.32.0) (2025-09-03)
2
+
3
+ ### Features
4
+
5
+ - **(sdk):** Add Speech to Speech agents implementation ([a8bf953](https://github.com/juspay/neurolink/commit/a8bf953993a16303d3c4a5b3a94d5ea5b6bd83d7))
6
+
7
+ ## [7.31.0](https://github.com/juspay/neurolink/compare/v7.30.1...v7.31.0) (2025-09-01)
8
+
9
+ ### Features
10
+
11
+ - **(core):** implement global middleware architecture ([8eb711a](https://github.com/juspay/neurolink/commit/8eb711ae827773c3fbc5339402d6cbee4e0bc8d4))
12
+
1
13
  ## [7.30.1](https://github.com/juspay/neurolink/compare/v7.30.0...v7.30.1) (2025-08-31)
2
14
 
3
15
  ### Bug Fixes
@@ -1054,8 +1054,22 @@ export class CLICommandFactory {
1054
1054
  // Demo mode - add delay between chunks
1055
1055
  await new Promise((resolve) => setTimeout(resolve, options.delay));
1056
1056
  }
1057
- process.stdout.write(nextResult.value.content);
1058
- fullContent += nextResult.value.content;
1057
+ const evt = nextResult.value;
1058
+ const isText = (o) => !!o &&
1059
+ typeof o === "object" &&
1060
+ typeof o.content === "string";
1061
+ const isAudio = (o) => !!o &&
1062
+ typeof o === "object" &&
1063
+ o.type === "audio";
1064
+ if (isText(evt)) {
1065
+ process.stdout.write(evt.content);
1066
+ fullContent += evt.content;
1067
+ }
1068
+ else if (isAudio(evt)) {
1069
+ if (options.debug && !options.quiet) {
1070
+ process.stdout.write("[audio-chunk]");
1071
+ }
1072
+ }
1059
1073
  }
1060
1074
  }
1061
1075
  catch (error) {
@@ -2,6 +2,7 @@ import type { ValidationSchema } from "../types/typeAliases.js";
2
2
  import type { Tool, LanguageModelV1 } from "ai";
3
3
  import type { AIProvider, TextGenerationOptions, TextGenerationResult, EnhancedGenerateResult, AnalyticsData, AIProviderName } from "../core/types.js";
4
4
  import type { EvaluationData } from "../index.js";
5
+ import type { MiddlewareFactoryOptions } from "../types/middlewareTypes.js";
5
6
  import type { StreamOptions, StreamResult } from "../types/streamTypes.js";
6
7
  import type { UnknownRecord } from "../types/common.js";
7
8
  import type { NeuroLink } from "../neurolink.js";
@@ -13,6 +14,7 @@ export declare abstract class BaseProvider implements AIProvider {
13
14
  protected readonly modelName: string;
14
15
  protected readonly providerName: AIProviderName;
15
16
  protected readonly defaultTimeout: number;
17
+ protected middlewareOptions?: MiddlewareFactoryOptions;
16
18
  protected readonly directTools: {};
17
19
  protected mcpTools?: Record<string, Tool>;
18
20
  protected customTools?: Map<string, unknown>;
@@ -20,7 +22,7 @@ export declare abstract class BaseProvider implements AIProvider {
20
22
  protected sessionId?: string;
21
23
  protected userId?: string;
22
24
  protected neurolink?: NeuroLink;
23
- constructor(modelName?: string, providerName?: AIProviderName, neurolink?: NeuroLink);
25
+ constructor(modelName?: string, providerName?: AIProviderName, neurolink?: NeuroLink, middleware?: MiddlewareFactoryOptions);
24
26
  /**
25
27
  * Check if this provider supports tool/function calling
26
28
  * Override in subclasses to disable tools for specific providers or models
@@ -67,16 +69,14 @@ export declare abstract class BaseProvider implements AIProvider {
67
69
  /**
68
70
  * Get AI SDK model with middleware applied
69
71
  * This method wraps the base model with any configured middleware
72
+ * TODO: Implement global level middlewares that can be used
70
73
  */
71
74
  protected getAISDKModelWithMiddleware(options?: TextGenerationOptions | StreamOptions): Promise<LanguageModelV1>;
72
75
  /**
73
- * Extract middleware options from generation options
76
+ * Extract middleware options from generation options. This is the single
77
+ * source of truth for deciding if middleware should be applied.
74
78
  */
75
79
  private extractMiddlewareOptions;
76
- /**
77
- * Determine if middleware should be skipped for this request
78
- */
79
- private shouldSkipMiddleware;
80
80
  /**
81
81
  * Check if a schema is a Zod schema
82
82
  */
@@ -18,6 +18,7 @@ export class BaseProvider {
18
18
  modelName;
19
19
  providerName;
20
20
  defaultTimeout = 30000; // 30 seconds
21
+ middlewareOptions; // TODO: Implement global level middlewares that can be used
21
22
  // Tools are conditionally included based on centralized configuration
22
23
  directTools = shouldDisableBuiltinTools()
23
24
  ? {}
@@ -28,10 +29,11 @@ export class BaseProvider {
28
29
  sessionId;
29
30
  userId;
30
31
  neurolink; // Reference to actual NeuroLink instance for MCP tools
31
- constructor(modelName, providerName, neurolink) {
32
+ constructor(modelName, providerName, neurolink, middleware) {
32
33
  this.modelName = modelName || this.getDefaultModel();
33
34
  this.providerName = providerName || this.getProviderName();
34
35
  this.neurolink = neurolink;
36
+ this.middlewareOptions = middleware;
35
37
  }
36
38
  /**
37
39
  * Check if this provider supports tool/function calling
@@ -170,8 +172,7 @@ export class BaseProvider {
170
172
  totalTools: getKeyCount(tools),
171
173
  totalToolNames: getKeysAsString(tools),
172
174
  });
173
- // EVERY provider uses Vercel AI SDK - no exceptions
174
- const model = await this.getAISDKModel(); // This method is now REQUIRED
175
+ const model = await this.getAISDKModelWithMiddleware(options);
175
176
  // Build proper message array with conversation history
176
177
  const messages = buildMessagesArray(options);
177
178
  const result = await generateText({
@@ -402,13 +403,14 @@ export class BaseProvider {
402
403
  /**
403
404
  * Get AI SDK model with middleware applied
404
405
  * This method wraps the base model with any configured middleware
406
+ * TODO: Implement global level middlewares that can be used
405
407
  */
406
408
  async getAISDKModelWithMiddleware(options = {}) {
407
409
  // Get the base model
408
410
  const baseModel = await this.getAISDKModel();
409
411
  // Check if middleware should be applied
410
412
  const middlewareOptions = this.extractMiddlewareOptions(options);
411
- if (!middlewareOptions || this.shouldSkipMiddleware(options)) {
413
+ if (!middlewareOptions) {
412
414
  return baseModel;
413
415
  }
414
416
  try {
@@ -437,47 +439,41 @@ export class BaseProvider {
437
439
  }
438
440
  }
439
441
  /**
440
- * Extract middleware options from generation options
442
+ * Extract middleware options from generation options. This is the single
443
+ * source of truth for deciding if middleware should be applied.
441
444
  */
442
445
  extractMiddlewareOptions(options) {
443
- // Check for middleware configuration in options
444
- const optionsRecord = options;
445
- const middlewareConfig = optionsRecord.middlewareConfig;
446
- const enabledMiddleware = optionsRecord.enabledMiddleware;
447
- const disabledMiddleware = optionsRecord.disabledMiddleware;
448
- const preset = optionsRecord.middlewarePreset;
449
- // If no middleware configuration is present, return null
450
- if (!middlewareConfig &&
451
- !enabledMiddleware &&
452
- !disabledMiddleware &&
453
- !preset) {
446
+ // 1. Determine effective middleware config: per-request overrides global.
447
+ const middlewareOpts = options.middleware ??
448
+ this.middlewareOptions;
449
+ if (!middlewareOpts) {
454
450
  return null;
455
451
  }
452
+ // 2. The middleware property must be an object with configuration.
453
+ if (typeof middlewareOpts !== "object" || middlewareOpts === null) {
454
+ return null;
455
+ }
456
+ // 3. Check if the middleware object has any actual configuration keys.
457
+ const fullOpts = middlewareOpts;
458
+ const hasArray = (arr) => Array.isArray(arr) && arr.length > 0;
459
+ const hasConfig = !!fullOpts.middlewareConfig ||
460
+ hasArray(fullOpts.enabledMiddleware) ||
461
+ hasArray(fullOpts.disabledMiddleware) ||
462
+ !!fullOpts.preset ||
463
+ hasArray(fullOpts.middleware);
464
+ if (!hasConfig) {
465
+ return null;
466
+ }
467
+ // 4. Return the formatted options if configuration is present.
456
468
  return {
457
- middlewareConfig,
458
- enabledMiddleware,
459
- disabledMiddleware,
460
- preset,
469
+ ...fullOpts,
461
470
  global: {
462
471
  collectStats: true,
463
472
  continueOnError: true,
473
+ ...(fullOpts.global || {}),
464
474
  },
465
475
  };
466
476
  }
467
- /**
468
- * Determine if middleware should be skipped for this request
469
- */
470
- shouldSkipMiddleware(options) {
471
- // Skip middleware if explicitly disabled
472
- if (options.disableMiddleware === true) {
473
- return true;
474
- }
475
- // Skip middleware for tool-disabled requests to avoid conflicts
476
- if (options.disableTools === true) {
477
- return true;
478
- }
479
- return false;
480
- }
481
477
  // ===================
482
478
  // TOOL MANAGEMENT
483
479
  // ===================
@@ -7,6 +7,7 @@ import type { ChatMessage, ConversationMemoryConfig } from "../types/conversatio
7
7
  import type { TokenUsage, AnalyticsData } from "../types/providers.js";
8
8
  import type { EvaluationData } from "../index.js";
9
9
  export type { EvaluationData };
10
+ import type { MiddlewareFactoryOptions } from "../types/middlewareTypes.js";
10
11
  export interface TextGenerationResult {
11
12
  content: string;
12
13
  provider?: string;
@@ -157,6 +158,7 @@ export interface TextGenerationOptions {
157
158
  conversationMessages?: ChatMessage[];
158
159
  conversationMemoryConfig?: Partial<ConversationMemoryConfig>;
159
160
  originalPrompt?: string;
161
+ middleware?: MiddlewareFactoryOptions;
160
162
  expectedOutcome?: string;
161
163
  evaluationCriteria?: string[];
162
164
  }
package/dist/index.d.ts CHANGED
@@ -20,7 +20,7 @@ export type { ModelConfig, ModelRegistry } from "./core/dynamicModels.js";
20
20
  export { NeuroLink } from "./neurolink.js";
21
21
  export type { ProviderStatus, MCPStatus } from "./neurolink.js";
22
22
  export type { MCPServerInfo } from "./types/mcpTypes.js";
23
- export type { NeuroLinkMiddleware, MiddlewareContext, MiddlewareFactoryOptions, MiddlewarePreset, MiddlewareConfig, } from "./middleware/types.js";
23
+ export type { NeuroLinkMiddleware, MiddlewareContext, MiddlewareFactoryOptions, MiddlewarePreset, MiddlewareConfig, } from "./types/middlewareTypes.js";
24
24
  export { MiddlewareFactory } from "./middleware/factory.js";
25
25
  export declare const VERSION = "1.0.0";
26
26
  /**
@@ -2,6 +2,7 @@ import type { ValidationSchema } from "../types/typeAliases.js";
2
2
  import type { Tool, LanguageModelV1 } from "ai";
3
3
  import type { AIProvider, TextGenerationOptions, TextGenerationResult, EnhancedGenerateResult, AnalyticsData, AIProviderName } from "../core/types.js";
4
4
  import type { EvaluationData } from "../index.js";
5
+ import type { MiddlewareFactoryOptions } from "../types/middlewareTypes.js";
5
6
  import type { StreamOptions, StreamResult } from "../types/streamTypes.js";
6
7
  import type { UnknownRecord } from "../types/common.js";
7
8
  import type { NeuroLink } from "../neurolink.js";
@@ -13,6 +14,7 @@ export declare abstract class BaseProvider implements AIProvider {
13
14
  protected readonly modelName: string;
14
15
  protected readonly providerName: AIProviderName;
15
16
  protected readonly defaultTimeout: number;
17
+ protected middlewareOptions?: MiddlewareFactoryOptions;
16
18
  protected readonly directTools: {};
17
19
  protected mcpTools?: Record<string, Tool>;
18
20
  protected customTools?: Map<string, unknown>;
@@ -20,7 +22,7 @@ export declare abstract class BaseProvider implements AIProvider {
20
22
  protected sessionId?: string;
21
23
  protected userId?: string;
22
24
  protected neurolink?: NeuroLink;
23
- constructor(modelName?: string, providerName?: AIProviderName, neurolink?: NeuroLink);
25
+ constructor(modelName?: string, providerName?: AIProviderName, neurolink?: NeuroLink, middleware?: MiddlewareFactoryOptions);
24
26
  /**
25
27
  * Check if this provider supports tool/function calling
26
28
  * Override in subclasses to disable tools for specific providers or models
@@ -67,16 +69,14 @@ export declare abstract class BaseProvider implements AIProvider {
67
69
  /**
68
70
  * Get AI SDK model with middleware applied
69
71
  * This method wraps the base model with any configured middleware
72
+ * TODO: Implement global level middlewares that can be used
70
73
  */
71
74
  protected getAISDKModelWithMiddleware(options?: TextGenerationOptions | StreamOptions): Promise<LanguageModelV1>;
72
75
  /**
73
- * Extract middleware options from generation options
76
+ * Extract middleware options from generation options. This is the single
77
+ * source of truth for deciding if middleware should be applied.
74
78
  */
75
79
  private extractMiddlewareOptions;
76
- /**
77
- * Determine if middleware should be skipped for this request
78
- */
79
- private shouldSkipMiddleware;
80
80
  /**
81
81
  * Check if a schema is a Zod schema
82
82
  */
@@ -18,6 +18,7 @@ export class BaseProvider {
18
18
  modelName;
19
19
  providerName;
20
20
  defaultTimeout = 30000; // 30 seconds
21
+ middlewareOptions; // TODO: Implement global level middlewares that can be used
21
22
  // Tools are conditionally included based on centralized configuration
22
23
  directTools = shouldDisableBuiltinTools()
23
24
  ? {}
@@ -28,10 +29,11 @@ export class BaseProvider {
28
29
  sessionId;
29
30
  userId;
30
31
  neurolink; // Reference to actual NeuroLink instance for MCP tools
31
- constructor(modelName, providerName, neurolink) {
32
+ constructor(modelName, providerName, neurolink, middleware) {
32
33
  this.modelName = modelName || this.getDefaultModel();
33
34
  this.providerName = providerName || this.getProviderName();
34
35
  this.neurolink = neurolink;
36
+ this.middlewareOptions = middleware;
35
37
  }
36
38
  /**
37
39
  * Check if this provider supports tool/function calling
@@ -170,8 +172,7 @@ export class BaseProvider {
170
172
  totalTools: getKeyCount(tools),
171
173
  totalToolNames: getKeysAsString(tools),
172
174
  });
173
- // EVERY provider uses Vercel AI SDK - no exceptions
174
- const model = await this.getAISDKModel(); // This method is now REQUIRED
175
+ const model = await this.getAISDKModelWithMiddleware(options);
175
176
  // Build proper message array with conversation history
176
177
  const messages = buildMessagesArray(options);
177
178
  const result = await generateText({
@@ -402,13 +403,14 @@ export class BaseProvider {
402
403
  /**
403
404
  * Get AI SDK model with middleware applied
404
405
  * This method wraps the base model with any configured middleware
406
+ * TODO: Implement global level middlewares that can be used
405
407
  */
406
408
  async getAISDKModelWithMiddleware(options = {}) {
407
409
  // Get the base model
408
410
  const baseModel = await this.getAISDKModel();
409
411
  // Check if middleware should be applied
410
412
  const middlewareOptions = this.extractMiddlewareOptions(options);
411
- if (!middlewareOptions || this.shouldSkipMiddleware(options)) {
413
+ if (!middlewareOptions) {
412
414
  return baseModel;
413
415
  }
414
416
  try {
@@ -437,47 +439,41 @@ export class BaseProvider {
437
439
  }
438
440
  }
439
441
  /**
440
- * Extract middleware options from generation options
442
+ * Extract middleware options from generation options. This is the single
443
+ * source of truth for deciding if middleware should be applied.
441
444
  */
442
445
  extractMiddlewareOptions(options) {
443
- // Check for middleware configuration in options
444
- const optionsRecord = options;
445
- const middlewareConfig = optionsRecord.middlewareConfig;
446
- const enabledMiddleware = optionsRecord.enabledMiddleware;
447
- const disabledMiddleware = optionsRecord.disabledMiddleware;
448
- const preset = optionsRecord.middlewarePreset;
449
- // If no middleware configuration is present, return null
450
- if (!middlewareConfig &&
451
- !enabledMiddleware &&
452
- !disabledMiddleware &&
453
- !preset) {
446
+ // 1. Determine effective middleware config: per-request overrides global.
447
+ const middlewareOpts = options.middleware ??
448
+ this.middlewareOptions;
449
+ if (!middlewareOpts) {
454
450
  return null;
455
451
  }
452
+ // 2. The middleware property must be an object with configuration.
453
+ if (typeof middlewareOpts !== "object" || middlewareOpts === null) {
454
+ return null;
455
+ }
456
+ // 3. Check if the middleware object has any actual configuration keys.
457
+ const fullOpts = middlewareOpts;
458
+ const hasArray = (arr) => Array.isArray(arr) && arr.length > 0;
459
+ const hasConfig = !!fullOpts.middlewareConfig ||
460
+ hasArray(fullOpts.enabledMiddleware) ||
461
+ hasArray(fullOpts.disabledMiddleware) ||
462
+ !!fullOpts.preset ||
463
+ hasArray(fullOpts.middleware);
464
+ if (!hasConfig) {
465
+ return null;
466
+ }
467
+ // 4. Return the formatted options if configuration is present.
456
468
  return {
457
- middlewareConfig,
458
- enabledMiddleware,
459
- disabledMiddleware,
460
- preset,
469
+ ...fullOpts,
461
470
  global: {
462
471
  collectStats: true,
463
472
  continueOnError: true,
473
+ ...(fullOpts.global || {}),
464
474
  },
465
475
  };
466
476
  }
467
- /**
468
- * Determine if middleware should be skipped for this request
469
- */
470
- shouldSkipMiddleware(options) {
471
- // Skip middleware if explicitly disabled
472
- if (options.disableMiddleware === true) {
473
- return true;
474
- }
475
- // Skip middleware for tool-disabled requests to avoid conflicts
476
- if (options.disableTools === true) {
477
- return true;
478
- }
479
- return false;
480
- }
481
477
  // ===================
482
478
  // TOOL MANAGEMENT
483
479
  // ===================
@@ -7,6 +7,7 @@ import type { ChatMessage, ConversationMemoryConfig } from "../types/conversatio
7
7
  import type { TokenUsage, AnalyticsData } from "../types/providers.js";
8
8
  import type { EvaluationData } from "../index.js";
9
9
  export type { EvaluationData };
10
+ import type { MiddlewareFactoryOptions } from "../types/middlewareTypes.js";
10
11
  export interface TextGenerationResult {
11
12
  content: string;
12
13
  provider?: string;
@@ -157,6 +158,7 @@ export interface TextGenerationOptions {
157
158
  conversationMessages?: ChatMessage[];
158
159
  conversationMemoryConfig?: Partial<ConversationMemoryConfig>;
159
160
  originalPrompt?: string;
161
+ middleware?: MiddlewareFactoryOptions;
160
162
  expectedOutcome?: string;
161
163
  evaluationCriteria?: string[];
162
164
  }
@@ -20,7 +20,7 @@ export type { ModelConfig, ModelRegistry } from "./core/dynamicModels.js";
20
20
  export { NeuroLink } from "./neurolink.js";
21
21
  export type { ProviderStatus, MCPStatus } from "./neurolink.js";
22
22
  export type { MCPServerInfo } from "./types/mcpTypes.js";
23
- export type { NeuroLinkMiddleware, MiddlewareContext, MiddlewareFactoryOptions, MiddlewarePreset, MiddlewareConfig, } from "./middleware/types.js";
23
+ export type { NeuroLinkMiddleware, MiddlewareContext, MiddlewareFactoryOptions, MiddlewarePreset, MiddlewareConfig, } from "./types/middlewareTypes.js";
24
24
  export { MiddlewareFactory } from "./middleware/factory.js";
25
25
  export declare const VERSION = "1.0.0";
26
26
  /**
@@ -1,4 +1,4 @@
1
- import type { NeuroLinkMiddleware } from "../types.js";
1
+ import type { NeuroLinkMiddleware } from "../../types/middlewareTypes.js";
2
2
  /**
3
3
  * Create analytics middleware for tracking AI model usage
4
4
  * Collects metrics on token usage, response times, and model performance
@@ -1,5 +1,5 @@
1
1
  import type { LanguageModelV1 } from "ai";
2
- import type { NeuroLinkMiddleware } from "../types.js";
2
+ import type { NeuroLinkMiddleware } from "../../types/middlewareTypes.js";
3
3
  /**
4
4
  * Configuration for the Guardrails middleware.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  import type { LanguageModelV1 } from "ai";
2
- import type { MiddlewareContext, MiddlewareConfig, MiddlewareFactoryOptions, MiddlewareChainStats, MiddlewarePreset, NeuroLinkMiddleware, MiddlewareRegistrationOptions } from "./types.js";
2
+ import type { MiddlewareContext, MiddlewareConfig, MiddlewareFactoryOptions, MiddlewareChainStats, MiddlewarePreset, NeuroLinkMiddleware, MiddlewareRegistrationOptions } from "../types/middlewareTypes.js";
3
3
  import { MiddlewareRegistry } from "./registry.js";
4
4
  /**
5
5
  * Middleware factory for creating and applying middleware chains.
@@ -6,7 +6,7 @@
6
6
  * of language models with features like analytics, guardrails, caching, and more.
7
7
  */
8
8
  import { MiddlewareFactory } from "./factory.js";
9
- export type { NeuroLinkMiddleware, MiddlewareConfig, MiddlewareContext, MiddlewareConditions, MiddlewareRegistrationOptions, MiddlewareExecutionResult, MiddlewareChainStats, MiddlewarePreset, MiddlewareFactoryOptions, BuiltInMiddlewareType, } from "./types.js";
9
+ export type { NeuroLinkMiddleware, MiddlewareConfig, MiddlewareContext, MiddlewareConditions, MiddlewareRegistrationOptions, MiddlewareExecutionResult, MiddlewareChainStats, MiddlewarePreset, MiddlewareFactoryOptions, BuiltInMiddlewareType, } from "../types/middlewareTypes.js";
10
10
  export type { LanguageModelV1Middleware } from "ai";
11
11
  export { MiddlewareFactory };
12
12
  export default MiddlewareFactory;
@@ -1,5 +1,5 @@
1
1
  import type { LanguageModelV1Middleware } from "ai";
2
- import type { NeuroLinkMiddleware, MiddlewareConfig, MiddlewareContext, MiddlewareRegistrationOptions, MiddlewareExecutionResult } from "./types.js";
2
+ import type { NeuroLinkMiddleware, MiddlewareConfig, MiddlewareContext, MiddlewareRegistrationOptions, MiddlewareExecutionResult } from "../types/middlewareTypes.js";
3
3
  /**
4
4
  * Manages the registration, configuration, and execution of middleware for a single factory instance.
5
5
  */
@@ -1312,8 +1312,10 @@ export class NeuroLink {
1312
1312
  needsInitialization: !this.mcpInitialized,
1313
1313
  message: "Checking MCP initialization status before generation",
1314
1314
  });
1315
- // Initialize MCP if needed
1316
- await this.initializeMCP();
1315
+ // Initialize MCP only when tools are enabled
1316
+ if (!options.disableTools) {
1317
+ await this.initializeMCP();
1318
+ }
1317
1319
  const mcpInitCheckEndTime = process.hrtime.bigint();
1318
1320
  const mcpInitCheckDurationNs = mcpInitCheckEndTime - mcpInitCheckStartTime;
1319
1321
  logger.debug(`[NeuroLink] ✅ LOG_POINT_T003_MCP_INIT_CHECK_COMPLETE`, {
@@ -1573,10 +1575,16 @@ export class NeuroLink {
1573
1575
  };
1574
1576
  // Call the new stream method
1575
1577
  const result = await this.stream(streamOptions);
1576
- // Convert StreamResult to simple string async iterable
1578
+ // Convert StreamResult to simple string async iterable (filter text events only)
1577
1579
  async function* stringStream() {
1578
- for await (const chunk of result.stream) {
1579
- yield chunk.content;
1580
+ for await (const evt of result.stream) {
1581
+ const anyEvt = evt;
1582
+ if (anyEvt && typeof anyEvt === "object" && "content" in anyEvt) {
1583
+ const content = anyEvt.content;
1584
+ if (typeof content === "string") {
1585
+ yield content;
1586
+ }
1587
+ }
1580
1588
  }
1581
1589
  }
1582
1590
  return stringStream();
@@ -1646,12 +1654,13 @@ export class NeuroLink {
1646
1654
  let factoryResult;
1647
1655
  try {
1648
1656
  await this.initializeMCP();
1649
- const _originalPrompt = options.input.text;
1650
1657
  factoryResult = processStreamingFactoryOptions(options);
1651
1658
  enhancedOptions = createCleanStreamOptions(options);
1652
- const { toolResults: _toolResults, enhancedPrompt } = await this.detectAndExecuteTools(options.input.text, undefined);
1653
- if (enhancedPrompt !== options.input.text) {
1654
- enhancedOptions.input.text = enhancedPrompt;
1659
+ if (options.input?.text) {
1660
+ const { toolResults: _toolResults, enhancedPrompt } = await this.detectAndExecuteTools(options.input.text, undefined);
1661
+ if (enhancedPrompt !== options.input.text) {
1662
+ enhancedOptions.input.text = enhancedPrompt;
1663
+ }
1655
1664
  }
1656
1665
  const { stream: mcpStream, provider: providerName } = await this.createMCPStream(enhancedOptions);
1657
1666
  const streamResult = await this.processStreamResult(mcpStream, enhancedOptions, factoryResult);
@@ -1756,9 +1765,13 @@ export class NeuroLink {
1756
1765
  validationStartTimeNs: validationStartTime.toString(),
1757
1766
  message: "Starting comprehensive input validation process",
1758
1767
  });
1759
- if (!options?.input?.text ||
1760
- typeof options.input.text !== "string" ||
1761
- options.input.text.trim() === "") {
1768
+ const hasText = typeof options?.input?.text === "string" &&
1769
+ options.input.text.trim().length > 0;
1770
+ // Accept audio when frames are present; sampleRateHz is optional (defaults applied later)
1771
+ const hasAudio = !!(options?.input?.audio &&
1772
+ options.input.audio.frames &&
1773
+ typeof options.input.audio.frames[Symbol.asyncIterator] !== "undefined");
1774
+ if (!hasText && !hasAudio) {
1762
1775
  const validationFailTime = process.hrtime.bigint();
1763
1776
  const validationDurationNs = validationFailTime - validationStartTime;
1764
1777
  logger.debug(`[NeuroLink] 💥 LOG_POINT_005_VALIDATION_FAILED`, {
@@ -1769,10 +1782,10 @@ export class NeuroLink {
1769
1782
  elapsedNs: (process.hrtime.bigint() - hrTimeStart).toString(),
1770
1783
  validationDurationNs: validationDurationNs.toString(),
1771
1784
  validationDurationMs: Number(validationDurationNs) / 1000000,
1772
- validationError: "Stream options must include input.text as a non-empty string",
1785
+ validationError: "Stream options must include either input.text or input.audio",
1773
1786
  message: "EXHAUSTIVE validation failure analysis with character-level debugging",
1774
1787
  });
1775
- throw new Error("Stream options must include input.text as a non-empty string");
1788
+ throw new Error("Stream options must include either input.text or input.audio");
1776
1789
  }
1777
1790
  const validationSuccessTime = process.hrtime.bigint();
1778
1791
  const validationDurationNs = validationSuccessTime - validationStartTime;
@@ -1784,10 +1797,11 @@ export class NeuroLink {
1784
1797
  elapsedNs: (process.hrtime.bigint() - hrTimeStart).toString(),
1785
1798
  validationDurationNs: validationDurationNs.toString(),
1786
1799
  validationDurationMs: Number(validationDurationNs) / 1000000,
1787
- inputTextValid: true,
1788
- inputTextLength: options.input.text.length,
1789
- inputTextTrimmedLength: options.input.text.trim().length,
1790
- inputTextPreview: options.input.text.substring(0, 100),
1800
+ inputTextValid: hasText,
1801
+ inputAudioPresent: hasAudio,
1802
+ inputTextLength: hasText ? options.input.text.length : 0,
1803
+ inputTextTrimmedLength: hasText ? options.input.text.trim().length : 0,
1804
+ inputTextPreview: hasText ? options.input.text.substring(0, 100) : "",
1791
1805
  message: "EXHAUSTIVE validation success - proceeding with stream processing",
1792
1806
  });
1793
1807
  }
@@ -17,6 +17,7 @@ export declare class GoogleAIStudioProvider extends BaseProvider {
17
17
  protected getAISDKModel(): LanguageModelV1;
18
18
  protected handleProviderError(error: unknown): Error;
19
19
  protected executeStream(options: StreamOptions, _analysisSchema?: ZodUnknownSchema | Schema<unknown>): Promise<StreamResult>;
20
+ private executeAudioStreamViaGeminiLive;
20
21
  private getApiKey;
21
22
  }
22
23
  export default GoogleAIStudioProvider;