@juspay/neurolink 7.24.1 → 7.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/core/baseProvider.d.ts +13 -0
- package/dist/core/baseProvider.js +79 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/lib/core/baseProvider.d.ts +13 -0
- package/dist/lib/core/baseProvider.js +79 -1
- package/dist/lib/index.d.ts +3 -0
- package/dist/lib/index.js +2 -0
- package/dist/lib/middleware/builtin/analytics.d.ts +16 -0
- package/dist/lib/middleware/builtin/analytics.js +130 -0
- package/dist/lib/middleware/factory.d.ts +54 -0
- package/dist/lib/middleware/factory.js +289 -0
- package/dist/lib/middleware/index.d.ts +58 -0
- package/dist/lib/middleware/index.js +67 -0
- package/dist/lib/middleware/registry.d.ts +78 -0
- package/dist/lib/middleware/registry.js +283 -0
- package/dist/lib/middleware/types.d.ts +144 -0
- package/dist/lib/middleware/types.js +1 -0
- package/dist/middleware/builtin/analytics.d.ts +16 -0
- package/dist/middleware/builtin/analytics.js +130 -0
- package/dist/middleware/factory.d.ts +54 -0
- package/dist/middleware/factory.js +289 -0
- package/dist/middleware/index.d.ts +58 -0
- package/dist/middleware/index.js +67 -0
- package/dist/middleware/registry.d.ts +78 -0
- package/dist/middleware/registry.js +283 -0
- package/dist/middleware/types.d.ts +144 -0
- package/dist/middleware/types.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [7.25.0](https://github.com/juspay/neurolink/compare/v7.24.1...v7.25.0) (2025-08-21)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
- **(middleware):** add custom middleware development guide ([ffd0343](https://github.com/juspay/neurolink/commit/ffd0343a589b267a5b8349a06cdfe2664a942e4c))
|
|
6
|
+
|
|
1
7
|
## [7.24.1](https://github.com/juspay/neurolink/compare/v7.24.0...v7.24.1) (2025-08-21)
|
|
2
8
|
|
|
3
9
|
## [7.24.0](https://github.com/juspay/neurolink/compare/v7.23.0...v7.24.0) (2025-08-20)
|
|
@@ -63,6 +63,19 @@ export declare abstract class BaseProvider implements AIProvider {
|
|
|
63
63
|
* Returns the Vercel AI SDK model instance for this provider
|
|
64
64
|
*/
|
|
65
65
|
protected abstract getAISDKModel(): LanguageModelV1 | Promise<LanguageModelV1>;
|
|
66
|
+
/**
|
|
67
|
+
* Get AI SDK model with middleware applied
|
|
68
|
+
* This method wraps the base model with any configured middleware
|
|
69
|
+
*/
|
|
70
|
+
protected getAISDKModelWithMiddleware(options?: TextGenerationOptions | StreamOptions): Promise<LanguageModelV1>;
|
|
71
|
+
/**
|
|
72
|
+
* Extract middleware options from generation options
|
|
73
|
+
*/
|
|
74
|
+
private extractMiddlewareOptions;
|
|
75
|
+
/**
|
|
76
|
+
* Determine if middleware should be skipped for this request
|
|
77
|
+
*/
|
|
78
|
+
private shouldSkipMiddleware;
|
|
66
79
|
/**
|
|
67
80
|
* Get all available tools - direct tools are ALWAYS available
|
|
68
81
|
* MCP tools are added when available (without blocking)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { MiddlewareFactory } from "../middleware/factory.js";
|
|
2
3
|
import { logger } from "../utils/logger.js";
|
|
3
4
|
import { DEFAULT_MAX_STEPS, STEP_LIMITS } from "../core/constants.js";
|
|
4
5
|
import { directAgentTools } from "../agent/directTools.js";
|
|
@@ -357,6 +358,83 @@ export class BaseProvider {
|
|
|
357
358
|
evaluation: result.evaluation,
|
|
358
359
|
};
|
|
359
360
|
}
|
|
361
|
+
/**
|
|
362
|
+
* Get AI SDK model with middleware applied
|
|
363
|
+
* This method wraps the base model with any configured middleware
|
|
364
|
+
*/
|
|
365
|
+
async getAISDKModelWithMiddleware(options = {}) {
|
|
366
|
+
// Get the base model
|
|
367
|
+
const baseModel = await this.getAISDKModel();
|
|
368
|
+
// Check if middleware should be applied
|
|
369
|
+
const middlewareOptions = this.extractMiddlewareOptions(options);
|
|
370
|
+
if (!middlewareOptions || this.shouldSkipMiddleware(options)) {
|
|
371
|
+
return baseModel;
|
|
372
|
+
}
|
|
373
|
+
try {
|
|
374
|
+
// Create middleware context
|
|
375
|
+
const context = MiddlewareFactory.createContext(this.providerName, this.modelName, options, {
|
|
376
|
+
sessionId: this.sessionId,
|
|
377
|
+
userId: this.userId,
|
|
378
|
+
});
|
|
379
|
+
// Apply middleware to the model
|
|
380
|
+
const wrappedModel = MiddlewareFactory.applyMiddleware(baseModel, context, middlewareOptions);
|
|
381
|
+
logger.debug(`Applied middleware to ${this.providerName} model`, {
|
|
382
|
+
provider: this.providerName,
|
|
383
|
+
model: this.modelName,
|
|
384
|
+
hasMiddleware: true,
|
|
385
|
+
});
|
|
386
|
+
return wrappedModel;
|
|
387
|
+
}
|
|
388
|
+
catch (error) {
|
|
389
|
+
logger.warn(`Failed to apply middleware to ${this.providerName}, using base model`, {
|
|
390
|
+
error: error instanceof Error ? error.message : String(error),
|
|
391
|
+
});
|
|
392
|
+
// Return base model on middleware failure to maintain functionality
|
|
393
|
+
return baseModel;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Extract middleware options from generation options
|
|
398
|
+
*/
|
|
399
|
+
extractMiddlewareOptions(options) {
|
|
400
|
+
// Check for middleware configuration in options
|
|
401
|
+
const optionsRecord = options;
|
|
402
|
+
const middlewareConfig = optionsRecord.middlewareConfig;
|
|
403
|
+
const enabledMiddleware = optionsRecord.enabledMiddleware;
|
|
404
|
+
const disabledMiddleware = optionsRecord.disabledMiddleware;
|
|
405
|
+
const preset = optionsRecord.middlewarePreset;
|
|
406
|
+
// If no middleware configuration is present, return null
|
|
407
|
+
if (!middlewareConfig &&
|
|
408
|
+
!enabledMiddleware &&
|
|
409
|
+
!disabledMiddleware &&
|
|
410
|
+
!preset) {
|
|
411
|
+
return null;
|
|
412
|
+
}
|
|
413
|
+
return {
|
|
414
|
+
middlewareConfig,
|
|
415
|
+
enabledMiddleware,
|
|
416
|
+
disabledMiddleware,
|
|
417
|
+
preset,
|
|
418
|
+
global: {
|
|
419
|
+
collectStats: true,
|
|
420
|
+
continueOnError: true,
|
|
421
|
+
},
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Determine if middleware should be skipped for this request
|
|
426
|
+
*/
|
|
427
|
+
shouldSkipMiddleware(options) {
|
|
428
|
+
// Skip middleware if explicitly disabled
|
|
429
|
+
if (options.disableMiddleware === true) {
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
// Skip middleware for tool-disabled requests to avoid conflicts
|
|
433
|
+
if (options.disableTools === true) {
|
|
434
|
+
return true;
|
|
435
|
+
}
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
360
438
|
// ===================
|
|
361
439
|
// TOOL MANAGEMENT
|
|
362
440
|
// ===================
|
|
@@ -428,7 +506,7 @@ export class BaseProvider {
|
|
|
428
506
|
timestamp: new Date().toISOString(),
|
|
429
507
|
params: params,
|
|
430
508
|
// Keep it simple - just indicate an error occurred
|
|
431
|
-
message: `Error calling ${toolName}: ${error instanceof Error ? error.message : String(error)}
|
|
509
|
+
message: `Error calling ${toolName}: ${error instanceof Error ? error.message : String(error)}`,
|
|
432
510
|
};
|
|
433
511
|
}
|
|
434
512
|
},
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,9 @@ export { getBestProvider, getAvailableProviders, isValidProvider, } from "./util
|
|
|
18
18
|
export { NeuroLink } from "./neurolink.js";
|
|
19
19
|
export type { ProviderStatus, MCPStatus } from "./neurolink.js";
|
|
20
20
|
export type { MCPServerInfo } from "./types/mcpTypes.js";
|
|
21
|
+
export type { NeuroLinkMiddleware, MiddlewareContext, MiddlewareFactoryOptions, } from "./middleware/types.js";
|
|
22
|
+
export { MiddlewareRegistry, MiddlewareFactory } from "./middleware/index.js";
|
|
23
|
+
export { createAnalyticsMiddleware } from "./middleware/builtin/analytics.js";
|
|
21
24
|
export declare const VERSION = "1.0.0";
|
|
22
25
|
/**
|
|
23
26
|
* Quick start factory function
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,8 @@ export { BedrockModels, OpenAIModels, VertexModels, DEFAULT_PROVIDER_CONFIGS, }
|
|
|
16
16
|
export { getBestProvider, getAvailableProviders, isValidProvider, } from "./utils/providerUtils.js";
|
|
17
17
|
// Main NeuroLink wrapper class and diagnostic types
|
|
18
18
|
export { NeuroLink } from "./neurolink.js";
|
|
19
|
+
export { MiddlewareRegistry, MiddlewareFactory } from "./middleware/index.js";
|
|
20
|
+
export { createAnalyticsMiddleware } from "./middleware/builtin/analytics.js";
|
|
19
21
|
// Version
|
|
20
22
|
export const VERSION = "1.0.0";
|
|
21
23
|
/**
|
|
@@ -63,6 +63,19 @@ export declare abstract class BaseProvider implements AIProvider {
|
|
|
63
63
|
* Returns the Vercel AI SDK model instance for this provider
|
|
64
64
|
*/
|
|
65
65
|
protected abstract getAISDKModel(): LanguageModelV1 | Promise<LanguageModelV1>;
|
|
66
|
+
/**
|
|
67
|
+
* Get AI SDK model with middleware applied
|
|
68
|
+
* This method wraps the base model with any configured middleware
|
|
69
|
+
*/
|
|
70
|
+
protected getAISDKModelWithMiddleware(options?: TextGenerationOptions | StreamOptions): Promise<LanguageModelV1>;
|
|
71
|
+
/**
|
|
72
|
+
* Extract middleware options from generation options
|
|
73
|
+
*/
|
|
74
|
+
private extractMiddlewareOptions;
|
|
75
|
+
/**
|
|
76
|
+
* Determine if middleware should be skipped for this request
|
|
77
|
+
*/
|
|
78
|
+
private shouldSkipMiddleware;
|
|
66
79
|
/**
|
|
67
80
|
* Get all available tools - direct tools are ALWAYS available
|
|
68
81
|
* MCP tools are added when available (without blocking)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { MiddlewareFactory } from "../middleware/factory.js";
|
|
2
3
|
import { logger } from "../utils/logger.js";
|
|
3
4
|
import { DEFAULT_MAX_STEPS, STEP_LIMITS } from "../core/constants.js";
|
|
4
5
|
import { directAgentTools } from "../agent/directTools.js";
|
|
@@ -357,6 +358,83 @@ export class BaseProvider {
|
|
|
357
358
|
evaluation: result.evaluation,
|
|
358
359
|
};
|
|
359
360
|
}
|
|
361
|
+
/**
|
|
362
|
+
* Get AI SDK model with middleware applied
|
|
363
|
+
* This method wraps the base model with any configured middleware
|
|
364
|
+
*/
|
|
365
|
+
async getAISDKModelWithMiddleware(options = {}) {
|
|
366
|
+
// Get the base model
|
|
367
|
+
const baseModel = await this.getAISDKModel();
|
|
368
|
+
// Check if middleware should be applied
|
|
369
|
+
const middlewareOptions = this.extractMiddlewareOptions(options);
|
|
370
|
+
if (!middlewareOptions || this.shouldSkipMiddleware(options)) {
|
|
371
|
+
return baseModel;
|
|
372
|
+
}
|
|
373
|
+
try {
|
|
374
|
+
// Create middleware context
|
|
375
|
+
const context = MiddlewareFactory.createContext(this.providerName, this.modelName, options, {
|
|
376
|
+
sessionId: this.sessionId,
|
|
377
|
+
userId: this.userId,
|
|
378
|
+
});
|
|
379
|
+
// Apply middleware to the model
|
|
380
|
+
const wrappedModel = MiddlewareFactory.applyMiddleware(baseModel, context, middlewareOptions);
|
|
381
|
+
logger.debug(`Applied middleware to ${this.providerName} model`, {
|
|
382
|
+
provider: this.providerName,
|
|
383
|
+
model: this.modelName,
|
|
384
|
+
hasMiddleware: true,
|
|
385
|
+
});
|
|
386
|
+
return wrappedModel;
|
|
387
|
+
}
|
|
388
|
+
catch (error) {
|
|
389
|
+
logger.warn(`Failed to apply middleware to ${this.providerName}, using base model`, {
|
|
390
|
+
error: error instanceof Error ? error.message : String(error),
|
|
391
|
+
});
|
|
392
|
+
// Return base model on middleware failure to maintain functionality
|
|
393
|
+
return baseModel;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Extract middleware options from generation options
|
|
398
|
+
*/
|
|
399
|
+
extractMiddlewareOptions(options) {
|
|
400
|
+
// Check for middleware configuration in options
|
|
401
|
+
const optionsRecord = options;
|
|
402
|
+
const middlewareConfig = optionsRecord.middlewareConfig;
|
|
403
|
+
const enabledMiddleware = optionsRecord.enabledMiddleware;
|
|
404
|
+
const disabledMiddleware = optionsRecord.disabledMiddleware;
|
|
405
|
+
const preset = optionsRecord.middlewarePreset;
|
|
406
|
+
// If no middleware configuration is present, return null
|
|
407
|
+
if (!middlewareConfig &&
|
|
408
|
+
!enabledMiddleware &&
|
|
409
|
+
!disabledMiddleware &&
|
|
410
|
+
!preset) {
|
|
411
|
+
return null;
|
|
412
|
+
}
|
|
413
|
+
return {
|
|
414
|
+
middlewareConfig,
|
|
415
|
+
enabledMiddleware,
|
|
416
|
+
disabledMiddleware,
|
|
417
|
+
preset,
|
|
418
|
+
global: {
|
|
419
|
+
collectStats: true,
|
|
420
|
+
continueOnError: true,
|
|
421
|
+
},
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Determine if middleware should be skipped for this request
|
|
426
|
+
*/
|
|
427
|
+
shouldSkipMiddleware(options) {
|
|
428
|
+
// Skip middleware if explicitly disabled
|
|
429
|
+
if (options.disableMiddleware === true) {
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
// Skip middleware for tool-disabled requests to avoid conflicts
|
|
433
|
+
if (options.disableTools === true) {
|
|
434
|
+
return true;
|
|
435
|
+
}
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
360
438
|
// ===================
|
|
361
439
|
// TOOL MANAGEMENT
|
|
362
440
|
// ===================
|
|
@@ -428,7 +506,7 @@ export class BaseProvider {
|
|
|
428
506
|
timestamp: new Date().toISOString(),
|
|
429
507
|
params: params,
|
|
430
508
|
// Keep it simple - just indicate an error occurred
|
|
431
|
-
message: `Error calling ${toolName}: ${error instanceof Error ? error.message : String(error)}
|
|
509
|
+
message: `Error calling ${toolName}: ${error instanceof Error ? error.message : String(error)}`,
|
|
432
510
|
};
|
|
433
511
|
}
|
|
434
512
|
},
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -18,6 +18,9 @@ export { getBestProvider, getAvailableProviders, isValidProvider, } from "./util
|
|
|
18
18
|
export { NeuroLink } from "./neurolink.js";
|
|
19
19
|
export type { ProviderStatus, MCPStatus } from "./neurolink.js";
|
|
20
20
|
export type { MCPServerInfo } from "./types/mcpTypes.js";
|
|
21
|
+
export type { NeuroLinkMiddleware, MiddlewareContext, MiddlewareFactoryOptions, } from "./middleware/types.js";
|
|
22
|
+
export { MiddlewareRegistry, MiddlewareFactory } from "./middleware/index.js";
|
|
23
|
+
export { createAnalyticsMiddleware } from "./middleware/builtin/analytics.js";
|
|
21
24
|
export declare const VERSION = "1.0.0";
|
|
22
25
|
/**
|
|
23
26
|
* Quick start factory function
|
package/dist/lib/index.js
CHANGED
|
@@ -16,6 +16,8 @@ export { BedrockModels, OpenAIModels, VertexModels, DEFAULT_PROVIDER_CONFIGS, }
|
|
|
16
16
|
export { getBestProvider, getAvailableProviders, isValidProvider, } from "./utils/providerUtils.js";
|
|
17
17
|
// Main NeuroLink wrapper class and diagnostic types
|
|
18
18
|
export { NeuroLink } from "./neurolink.js";
|
|
19
|
+
export { MiddlewareRegistry, MiddlewareFactory } from "./middleware/index.js";
|
|
20
|
+
export { createAnalyticsMiddleware } from "./middleware/builtin/analytics.js";
|
|
19
21
|
// Version
|
|
20
22
|
export const VERSION = "1.0.0";
|
|
21
23
|
/**
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { NeuroLinkMiddleware } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Create analytics middleware for tracking AI model usage
|
|
4
|
+
* Collects metrics on token usage, response times, and model performance
|
|
5
|
+
*/
|
|
6
|
+
export declare function createAnalyticsMiddleware(): NeuroLinkMiddleware;
|
|
7
|
+
/**
|
|
8
|
+
* Get collected metrics from analytics middleware
|
|
9
|
+
* Note: This is a utility function for accessing metrics
|
|
10
|
+
*/
|
|
11
|
+
export declare function getAnalyticsMetrics(): Map<string, Record<string, unknown>>;
|
|
12
|
+
/**
|
|
13
|
+
* Clear collected metrics from analytics middleware
|
|
14
|
+
* Note: This is a utility function for clearing metrics
|
|
15
|
+
*/
|
|
16
|
+
export declare function clearAnalyticsMetrics(): void;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { logger } from "../../utils/logger.js";
|
|
2
|
+
/**
|
|
3
|
+
* Create analytics middleware for tracking AI model usage
|
|
4
|
+
* Collects metrics on token usage, response times, and model performance
|
|
5
|
+
*/
|
|
6
|
+
export function createAnalyticsMiddleware() {
|
|
7
|
+
const requestMetrics = new Map();
|
|
8
|
+
const metadata = {
|
|
9
|
+
id: "analytics",
|
|
10
|
+
name: "Analytics Tracking",
|
|
11
|
+
description: "Tracks token usage, response times, and model performance metrics",
|
|
12
|
+
priority: 100, // High priority to ensure analytics are captured
|
|
13
|
+
defaultEnabled: true,
|
|
14
|
+
};
|
|
15
|
+
const middleware = {
|
|
16
|
+
wrapGenerate: async ({ doGenerate, params }) => {
|
|
17
|
+
const requestId = `analytics-${Date.now()}`;
|
|
18
|
+
const startTime = Date.now();
|
|
19
|
+
logger.debug(`[AnalyticsMiddleware] Starting request tracking`, {
|
|
20
|
+
requestId,
|
|
21
|
+
hasPrompt: !!params.prompt,
|
|
22
|
+
});
|
|
23
|
+
try {
|
|
24
|
+
// Execute the generation
|
|
25
|
+
const result = await doGenerate();
|
|
26
|
+
// Calculate metrics
|
|
27
|
+
const responseTime = Date.now() - startTime;
|
|
28
|
+
const analytics = {
|
|
29
|
+
requestId,
|
|
30
|
+
responseTime,
|
|
31
|
+
timestamp: new Date().toISOString(),
|
|
32
|
+
usage: {
|
|
33
|
+
inputTokens: result.usage?.promptTokens || 0,
|
|
34
|
+
outputTokens: result.usage?.completionTokens || 0,
|
|
35
|
+
totalTokens: (result.usage?.promptTokens || 0) +
|
|
36
|
+
(result.usage?.completionTokens || 0),
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
// Store metrics for potential retrieval
|
|
40
|
+
requestMetrics.set(requestId, analytics);
|
|
41
|
+
logger.debug(`[AnalyticsMiddleware] Request completed`, analytics);
|
|
42
|
+
// Add analytics to the result
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
|
+
const updatedResult = { ...result };
|
|
45
|
+
if (!updatedResult.experimental_providerMetadata) {
|
|
46
|
+
updatedResult.experimental_providerMetadata = {};
|
|
47
|
+
}
|
|
48
|
+
if (!updatedResult.experimental_providerMetadata.neurolink) {
|
|
49
|
+
updatedResult.experimental_providerMetadata.neurolink = {};
|
|
50
|
+
}
|
|
51
|
+
updatedResult.experimental_providerMetadata.neurolink.analytics =
|
|
52
|
+
analytics;
|
|
53
|
+
return updatedResult;
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
const responseTime = Date.now() - startTime;
|
|
57
|
+
logger.error(`[AnalyticsMiddleware] Request failed`, {
|
|
58
|
+
requestId,
|
|
59
|
+
responseTime,
|
|
60
|
+
error: error instanceof Error ? error.message : String(error),
|
|
61
|
+
});
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
wrapStream: async ({ doStream, params }) => {
|
|
66
|
+
const requestId = `analytics-stream-${Date.now()}`;
|
|
67
|
+
const startTime = Date.now();
|
|
68
|
+
logger.debug(`[AnalyticsMiddleware] Starting stream tracking`, {
|
|
69
|
+
requestId,
|
|
70
|
+
hasPrompt: !!params.prompt,
|
|
71
|
+
});
|
|
72
|
+
try {
|
|
73
|
+
const result = await doStream();
|
|
74
|
+
const streamAnalytics = {
|
|
75
|
+
requestId,
|
|
76
|
+
startTime,
|
|
77
|
+
timestamp: new Date().toISOString(),
|
|
78
|
+
streamingMode: true,
|
|
79
|
+
};
|
|
80
|
+
requestMetrics.set(requestId, streamAnalytics);
|
|
81
|
+
// The 'result' is a stream, so we can't directly modify it.
|
|
82
|
+
// Analytics for streams are typically handled after the stream is consumed.
|
|
83
|
+
// For this middleware, we'll log the start and rely on other mechanisms
|
|
84
|
+
// to capture the end-to-end stream metrics if needed.
|
|
85
|
+
// We will pass a new property in the `rawResponse`
|
|
86
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
87
|
+
const updatedResult = { ...result };
|
|
88
|
+
if (!updatedResult.rawResponse) {
|
|
89
|
+
updatedResult.rawResponse = {};
|
|
90
|
+
}
|
|
91
|
+
if (!updatedResult.rawResponse.neurolink) {
|
|
92
|
+
updatedResult.rawResponse.neurolink = {};
|
|
93
|
+
}
|
|
94
|
+
updatedResult.rawResponse.neurolink.analytics = streamAnalytics;
|
|
95
|
+
return updatedResult;
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
const responseTime = Date.now() - startTime;
|
|
99
|
+
logger.error(`[AnalyticsMiddleware] Stream failed`, {
|
|
100
|
+
requestId,
|
|
101
|
+
responseTime,
|
|
102
|
+
error: error instanceof Error ? error.message : String(error),
|
|
103
|
+
});
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
// Return the NeuroLinkMiddleware with metadata
|
|
109
|
+
return {
|
|
110
|
+
...middleware,
|
|
111
|
+
metadata,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Get collected metrics from analytics middleware
|
|
116
|
+
* Note: This is a utility function for accessing metrics
|
|
117
|
+
*/
|
|
118
|
+
export function getAnalyticsMetrics() {
|
|
119
|
+
// This would need to be implemented with a global registry
|
|
120
|
+
// For now, return empty map
|
|
121
|
+
return new Map();
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Clear collected metrics from analytics middleware
|
|
125
|
+
* Note: This is a utility function for clearing metrics
|
|
126
|
+
*/
|
|
127
|
+
export function clearAnalyticsMetrics() {
|
|
128
|
+
// This would need to be implemented with a global registry
|
|
129
|
+
// For now, do nothing
|
|
130
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { LanguageModelV1 } from "ai";
|
|
2
|
+
import type { MiddlewareContext, MiddlewareConfig, MiddlewareFactoryOptions, MiddlewareChainStats } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Middleware factory for creating and applying middleware chains
|
|
5
|
+
*/
|
|
6
|
+
export declare class MiddlewareFactory {
|
|
7
|
+
/**
|
|
8
|
+
* Apply middleware to a language model
|
|
9
|
+
*/
|
|
10
|
+
static applyMiddleware(model: LanguageModelV1, context: MiddlewareContext, options?: MiddlewareFactoryOptions): LanguageModelV1;
|
|
11
|
+
/**
|
|
12
|
+
* Build middleware configuration from factory options
|
|
13
|
+
*/
|
|
14
|
+
private static buildMiddlewareConfig;
|
|
15
|
+
/**
|
|
16
|
+
* Get preset configuration
|
|
17
|
+
*/
|
|
18
|
+
private static getPresetConfig;
|
|
19
|
+
/**
|
|
20
|
+
* Get built-in preset configurations
|
|
21
|
+
*/
|
|
22
|
+
private static getBuiltInPresets;
|
|
23
|
+
/**
|
|
24
|
+
* Create middleware context from provider and options
|
|
25
|
+
*/
|
|
26
|
+
static createContext(provider: string, model: string, options?: Record<string, unknown>, session?: {
|
|
27
|
+
sessionId?: string;
|
|
28
|
+
userId?: string;
|
|
29
|
+
}): MiddlewareContext;
|
|
30
|
+
/**
|
|
31
|
+
* Validate middleware configuration
|
|
32
|
+
*/
|
|
33
|
+
static validateConfig(config: Record<string, MiddlewareConfig>): {
|
|
34
|
+
isValid: boolean;
|
|
35
|
+
errors: string[];
|
|
36
|
+
warnings: string[];
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Get available presets
|
|
40
|
+
*/
|
|
41
|
+
static getAvailablePresets(): Array<{
|
|
42
|
+
name: string;
|
|
43
|
+
description: string;
|
|
44
|
+
middleware: string[];
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Get middleware chain statistics
|
|
48
|
+
*/
|
|
49
|
+
static getChainStats(context: MiddlewareContext, config: Record<string, MiddlewareConfig>): MiddlewareChainStats;
|
|
50
|
+
/**
|
|
51
|
+
* Create a middleware-enabled model factory function
|
|
52
|
+
*/
|
|
53
|
+
static createModelFactory(baseModelFactory: () => Promise<LanguageModelV1>, defaultOptions?: MiddlewareFactoryOptions): (context: MiddlewareContext, options?: MiddlewareFactoryOptions) => Promise<LanguageModelV1>;
|
|
54
|
+
}
|