@juspay/neurolink 7.24.0 → 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 +8 -0
- package/dist/cli/index.js +8 -66
- 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/lib/providers/anthropic.js +25 -33
- package/dist/lib/providers/googleAiStudio.js +10 -11
- package/dist/lib/providers/openAI.js +15 -6
- package/dist/lib/types/errors.d.ts +44 -0
- package/dist/lib/types/errors.js +60 -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/dist/providers/anthropic.js +25 -33
- package/dist/providers/googleAiStudio.js +10 -11
- package/dist/providers/openAI.js +15 -6
- package/dist/types/errors.d.ts +44 -0
- package/dist/types/errors.js +60 -0
- package/package.json +1 -1
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error class for all NeuroLink-specific errors.
|
|
3
|
+
* This allows for easy identification of errors thrown by the SDK.
|
|
4
|
+
*/
|
|
5
|
+
export class BaseError extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = this.constructor.name;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Thrown when a provider encounters a generic error.
|
|
13
|
+
*/
|
|
14
|
+
export class ProviderError extends BaseError {
|
|
15
|
+
provider;
|
|
16
|
+
constructor(message, provider) {
|
|
17
|
+
super(provider ? `[${provider}] ${message}` : message);
|
|
18
|
+
this.provider = provider;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Thrown for authentication-related errors, such as invalid or missing API keys.
|
|
23
|
+
*/
|
|
24
|
+
export class AuthenticationError extends ProviderError {
|
|
25
|
+
constructor(message, provider) {
|
|
26
|
+
super(message, provider);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Thrown for authorization errors, where the user does not have permission.
|
|
31
|
+
*/
|
|
32
|
+
export class AuthorizationError extends ProviderError {
|
|
33
|
+
constructor(message, provider) {
|
|
34
|
+
super(message, provider);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Thrown for network-related issues, such as connectivity problems or timeouts.
|
|
39
|
+
*/
|
|
40
|
+
export class NetworkError extends ProviderError {
|
|
41
|
+
constructor(message, provider) {
|
|
42
|
+
super(message, provider);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Thrown when an API rate limit has been exceeded.
|
|
47
|
+
*/
|
|
48
|
+
export class RateLimitError extends ProviderError {
|
|
49
|
+
constructor(message, provider) {
|
|
50
|
+
super(message, provider);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Thrown when a specified model is not found or is invalid for the provider.
|
|
55
|
+
*/
|
|
56
|
+
export class InvalidModelError extends ProviderError {
|
|
57
|
+
constructor(message, provider) {
|
|
58
|
+
super(message, provider);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { wrapLanguageModel } from "ai";
|
|
2
|
+
import { middlewareRegistry } from "./registry.js";
|
|
3
|
+
import { logger } from "../utils/logger.js";
|
|
4
|
+
/**
|
|
5
|
+
* Middleware factory for creating and applying middleware chains
|
|
6
|
+
*/
|
|
7
|
+
export class MiddlewareFactory {
|
|
8
|
+
/**
|
|
9
|
+
* Apply middleware to a language model
|
|
10
|
+
*/
|
|
11
|
+
static applyMiddleware(model, context, options = {}) {
|
|
12
|
+
const startTime = Date.now();
|
|
13
|
+
try {
|
|
14
|
+
// Build middleware configuration
|
|
15
|
+
const middlewareConfig = this.buildMiddlewareConfig(options);
|
|
16
|
+
// Build middleware chain
|
|
17
|
+
const middlewareChain = middlewareRegistry.buildChain(context, middlewareConfig);
|
|
18
|
+
if (middlewareChain.length === 0) {
|
|
19
|
+
logger.debug("No middleware to apply", { provider: context.provider });
|
|
20
|
+
return model;
|
|
21
|
+
}
|
|
22
|
+
logger.debug(`Applying ${middlewareChain.length} middleware to model`, {
|
|
23
|
+
provider: context.provider,
|
|
24
|
+
model: context.model,
|
|
25
|
+
middlewareCount: middlewareChain.length,
|
|
26
|
+
});
|
|
27
|
+
// Apply middleware using AI SDK's wrapLanguageModel
|
|
28
|
+
// Cast to the expected AI SDK middleware type
|
|
29
|
+
const wrappedModel = wrapLanguageModel({
|
|
30
|
+
model,
|
|
31
|
+
middleware: middlewareChain,
|
|
32
|
+
});
|
|
33
|
+
const processingTime = Date.now() - startTime;
|
|
34
|
+
logger.debug("Middleware applied successfully", {
|
|
35
|
+
provider: context.provider,
|
|
36
|
+
middlewareCount: middlewareChain.length,
|
|
37
|
+
processingTime,
|
|
38
|
+
});
|
|
39
|
+
return wrappedModel;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
logger.error("Failed to apply middleware", {
|
|
43
|
+
provider: context.provider,
|
|
44
|
+
error: error instanceof Error ? error.message : String(error),
|
|
45
|
+
});
|
|
46
|
+
// Return original model on error to maintain functionality
|
|
47
|
+
return model;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Build middleware configuration from factory options
|
|
52
|
+
*/
|
|
53
|
+
static buildMiddlewareConfig(options) {
|
|
54
|
+
const config = {};
|
|
55
|
+
// Start with all registered middleware
|
|
56
|
+
const allMiddleware = middlewareRegistry.list();
|
|
57
|
+
for (const middleware of allMiddleware) {
|
|
58
|
+
// Default configuration
|
|
59
|
+
config[middleware.metadata.id] = {
|
|
60
|
+
enabled: middleware.metadata.defaultEnabled || false,
|
|
61
|
+
config: {},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
// Apply preset configuration if specified
|
|
65
|
+
if (options.preset) {
|
|
66
|
+
const presetConfig = this.getPresetConfig(options.preset);
|
|
67
|
+
if (presetConfig) {
|
|
68
|
+
Object.assign(config, presetConfig);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Apply explicit middleware configurations
|
|
72
|
+
if (options.middlewareConfig) {
|
|
73
|
+
for (const [middlewareId, middlewareConfig] of Object.entries(options.middlewareConfig)) {
|
|
74
|
+
config[middlewareId] = {
|
|
75
|
+
...config[middlewareId],
|
|
76
|
+
...middlewareConfig,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Apply enabled middleware list
|
|
81
|
+
if (options.enabledMiddleware) {
|
|
82
|
+
for (const middlewareId of options.enabledMiddleware) {
|
|
83
|
+
if (config[middlewareId]) {
|
|
84
|
+
config[middlewareId].enabled = true;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Apply disabled middleware list
|
|
89
|
+
if (options.disabledMiddleware) {
|
|
90
|
+
for (const middlewareId of options.disabledMiddleware) {
|
|
91
|
+
if (config[middlewareId]) {
|
|
92
|
+
config[middlewareId].enabled = false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return config;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get preset configuration
|
|
100
|
+
*/
|
|
101
|
+
static getPresetConfig(presetName) {
|
|
102
|
+
const presets = this.getBuiltInPresets();
|
|
103
|
+
return presets[presetName] || null;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get built-in preset configurations
|
|
107
|
+
*/
|
|
108
|
+
static getBuiltInPresets() {
|
|
109
|
+
return {
|
|
110
|
+
// Development preset - logging and basic analytics
|
|
111
|
+
development: {
|
|
112
|
+
logging: { enabled: true },
|
|
113
|
+
analytics: { enabled: true },
|
|
114
|
+
},
|
|
115
|
+
// Production preset - analytics, caching, rate limiting
|
|
116
|
+
production: {
|
|
117
|
+
analytics: { enabled: true },
|
|
118
|
+
caching: { enabled: true },
|
|
119
|
+
rateLimit: { enabled: true },
|
|
120
|
+
retry: { enabled: true },
|
|
121
|
+
},
|
|
122
|
+
// Security preset - guardrails and content filtering
|
|
123
|
+
security: {
|
|
124
|
+
guardrails: { enabled: true },
|
|
125
|
+
logging: { enabled: true },
|
|
126
|
+
rateLimit: { enabled: true },
|
|
127
|
+
},
|
|
128
|
+
// Performance preset - caching and optimization
|
|
129
|
+
performance: {
|
|
130
|
+
caching: { enabled: true },
|
|
131
|
+
retry: { enabled: true },
|
|
132
|
+
timeout: { enabled: true },
|
|
133
|
+
},
|
|
134
|
+
// Enterprise preset - all middleware enabled
|
|
135
|
+
enterprise: {
|
|
136
|
+
analytics: { enabled: true },
|
|
137
|
+
guardrails: { enabled: true },
|
|
138
|
+
logging: { enabled: true },
|
|
139
|
+
caching: { enabled: true },
|
|
140
|
+
rateLimit: { enabled: true },
|
|
141
|
+
retry: { enabled: true },
|
|
142
|
+
timeout: { enabled: true },
|
|
143
|
+
},
|
|
144
|
+
// Minimal preset - only essential middleware
|
|
145
|
+
minimal: {
|
|
146
|
+
analytics: { enabled: true },
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Create middleware context from provider and options
|
|
152
|
+
*/
|
|
153
|
+
static createContext(provider, model, options = {}, session) {
|
|
154
|
+
return {
|
|
155
|
+
provider,
|
|
156
|
+
model,
|
|
157
|
+
options,
|
|
158
|
+
session,
|
|
159
|
+
metadata: {
|
|
160
|
+
timestamp: Date.now(),
|
|
161
|
+
requestId: `${provider}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Validate middleware configuration
|
|
167
|
+
*/
|
|
168
|
+
static validateConfig(config) {
|
|
169
|
+
const errors = [];
|
|
170
|
+
const warnings = [];
|
|
171
|
+
for (const [middlewareId, middlewareConfig] of Object.entries(config)) {
|
|
172
|
+
// Check if middleware is registered
|
|
173
|
+
if (!middlewareRegistry.has(middlewareId)) {
|
|
174
|
+
errors.push(`Middleware '${middlewareId}' is not registered`);
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
// Validate configuration structure
|
|
178
|
+
if (middlewareConfig.enabled !== undefined &&
|
|
179
|
+
typeof middlewareConfig.enabled !== "boolean") {
|
|
180
|
+
errors.push(`Middleware '${middlewareId}' enabled property must be boolean`);
|
|
181
|
+
}
|
|
182
|
+
if (middlewareConfig.config &&
|
|
183
|
+
typeof middlewareConfig.config !== "object") {
|
|
184
|
+
errors.push(`Middleware '${middlewareId}' config property must be an object`);
|
|
185
|
+
}
|
|
186
|
+
// Check for potential conflicts
|
|
187
|
+
if (middlewareConfig.conditions?.providers &&
|
|
188
|
+
middlewareConfig.conditions.providers.length === 0) {
|
|
189
|
+
warnings.push(`Middleware '${middlewareId}' has empty providers condition`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
isValid: errors.length === 0,
|
|
194
|
+
errors,
|
|
195
|
+
warnings,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Get available presets
|
|
200
|
+
*/
|
|
201
|
+
static getAvailablePresets() {
|
|
202
|
+
return [
|
|
203
|
+
{
|
|
204
|
+
name: "development",
|
|
205
|
+
description: "Logging and basic analytics for development",
|
|
206
|
+
middleware: ["logging", "analytics"],
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
name: "production",
|
|
210
|
+
description: "Optimized for production with caching and rate limiting",
|
|
211
|
+
middleware: ["analytics", "caching", "rateLimit", "retry"],
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
name: "security",
|
|
215
|
+
description: "Enhanced security with guardrails and monitoring",
|
|
216
|
+
middleware: ["guardrails", "logging", "rateLimit"],
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
name: "performance",
|
|
220
|
+
description: "Optimized for performance with caching and retries",
|
|
221
|
+
middleware: ["caching", "retry", "timeout"],
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
name: "enterprise",
|
|
225
|
+
description: "Full enterprise feature set with all middleware",
|
|
226
|
+
middleware: [
|
|
227
|
+
"analytics",
|
|
228
|
+
"guardrails",
|
|
229
|
+
"logging",
|
|
230
|
+
"caching",
|
|
231
|
+
"rateLimit",
|
|
232
|
+
"retry",
|
|
233
|
+
"timeout",
|
|
234
|
+
],
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
name: "minimal",
|
|
238
|
+
description: "Minimal overhead with only essential features",
|
|
239
|
+
middleware: ["analytics"],
|
|
240
|
+
},
|
|
241
|
+
];
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Get middleware chain statistics
|
|
245
|
+
*/
|
|
246
|
+
static getChainStats(context, config) {
|
|
247
|
+
const chain = middlewareRegistry.buildChain(context, config);
|
|
248
|
+
const stats = middlewareRegistry.getAggregatedStats();
|
|
249
|
+
const results = {};
|
|
250
|
+
let totalExecutionTime = 0;
|
|
251
|
+
let appliedMiddleware = 0;
|
|
252
|
+
for (const [middlewareId, middlewareStats] of Object.entries(stats)) {
|
|
253
|
+
if (config[middlewareId]?.enabled) {
|
|
254
|
+
results[middlewareId] = {
|
|
255
|
+
applied: true,
|
|
256
|
+
executionTime: middlewareStats.averageExecutionTime,
|
|
257
|
+
};
|
|
258
|
+
totalExecutionTime += middlewareStats.averageExecutionTime;
|
|
259
|
+
appliedMiddleware++;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return {
|
|
263
|
+
totalMiddleware: chain.length,
|
|
264
|
+
appliedMiddleware,
|
|
265
|
+
totalExecutionTime,
|
|
266
|
+
results,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Create a middleware-enabled model factory function
|
|
271
|
+
*/
|
|
272
|
+
static createModelFactory(baseModelFactory, defaultOptions = {}) {
|
|
273
|
+
return async (context, options = {}) => {
|
|
274
|
+
// Get base model
|
|
275
|
+
const baseModel = await baseModelFactory();
|
|
276
|
+
// Merge options
|
|
277
|
+
const _mergedOptions = {
|
|
278
|
+
...defaultOptions,
|
|
279
|
+
...options,
|
|
280
|
+
middlewareConfig: {
|
|
281
|
+
...defaultOptions.middlewareConfig,
|
|
282
|
+
...options.middlewareConfig,
|
|
283
|
+
},
|
|
284
|
+
};
|
|
285
|
+
// Apply middleware
|
|
286
|
+
return this.applyMiddleware(baseModel, context, _mergedOptions);
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NeuroLink Middleware System
|
|
3
|
+
*
|
|
4
|
+
* This module provides a comprehensive middleware system for NeuroLink that integrates
|
|
5
|
+
* with the AI SDK's wrapLanguageModel functionality. It allows for modular enhancement
|
|
6
|
+
* of language models with features like analytics, guardrails, caching, and more.
|
|
7
|
+
*/
|
|
8
|
+
import type { NeuroLinkMiddleware, MiddlewareRegistrationOptions, MiddlewareConfig } from "./types.js";
|
|
9
|
+
export type { NeuroLinkMiddleware, MiddlewareConfig, MiddlewareContext, MiddlewareConditions, MiddlewareRegistrationOptions, MiddlewareExecutionResult, MiddlewareChainStats, MiddlewarePreset, MiddlewareFactoryOptions, BuiltInMiddlewareType, } from "./types.js";
|
|
10
|
+
export type { LanguageModelV1Middleware } from "ai";
|
|
11
|
+
export { MiddlewareRegistry, middlewareRegistry } from "./registry.js";
|
|
12
|
+
export { MiddlewareFactory } from "./factory.js";
|
|
13
|
+
/**
|
|
14
|
+
* Convenience function to register a middleware
|
|
15
|
+
*/
|
|
16
|
+
export declare function registerMiddleware(middleware: NeuroLinkMiddleware, options?: MiddlewareRegistrationOptions): void;
|
|
17
|
+
/**
|
|
18
|
+
* Convenience function to unregister a middleware
|
|
19
|
+
*/
|
|
20
|
+
export declare function unregisterMiddleware(middlewareId: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Convenience function to get all registered middleware
|
|
23
|
+
*/
|
|
24
|
+
export declare function listMiddleware(): NeuroLinkMiddleware[];
|
|
25
|
+
/**
|
|
26
|
+
* Convenience function to check if a middleware is registered
|
|
27
|
+
*/
|
|
28
|
+
export declare function hasMiddleware(middlewareId: string): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Convenience function to get middleware execution statistics
|
|
31
|
+
*/
|
|
32
|
+
export declare function getMiddlewareStats(): Record<string, {
|
|
33
|
+
totalExecutions: number;
|
|
34
|
+
successfulExecutions: number;
|
|
35
|
+
failedExecutions: number;
|
|
36
|
+
averageExecutionTime: number;
|
|
37
|
+
lastExecutionTime: number;
|
|
38
|
+
}>;
|
|
39
|
+
/**
|
|
40
|
+
* Convenience function to clear middleware execution statistics
|
|
41
|
+
*/
|
|
42
|
+
export declare function clearMiddlewareStats(middlewareId?: string): void;
|
|
43
|
+
/**
|
|
44
|
+
* Convenience function to get available middleware presets
|
|
45
|
+
*/
|
|
46
|
+
export declare function getAvailablePresets(): Array<{
|
|
47
|
+
name: string;
|
|
48
|
+
description: string;
|
|
49
|
+
middleware: string[];
|
|
50
|
+
}>;
|
|
51
|
+
/**
|
|
52
|
+
* Convenience function to validate middleware configuration
|
|
53
|
+
*/
|
|
54
|
+
export declare function validateMiddlewareConfig(config: Record<string, MiddlewareConfig>): {
|
|
55
|
+
isValid: boolean;
|
|
56
|
+
errors: string[];
|
|
57
|
+
warnings: string[];
|
|
58
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NeuroLink Middleware System
|
|
3
|
+
*
|
|
4
|
+
* This module provides a comprehensive middleware system for NeuroLink that integrates
|
|
5
|
+
* with the AI SDK's wrapLanguageModel functionality. It allows for modular enhancement
|
|
6
|
+
* of language models with features like analytics, guardrails, caching, and more.
|
|
7
|
+
*/
|
|
8
|
+
import { middlewareRegistry } from "./registry.js";
|
|
9
|
+
import { MiddlewareFactory } from "./factory.js";
|
|
10
|
+
// Registry for managing middleware
|
|
11
|
+
export { MiddlewareRegistry, middlewareRegistry } from "./registry.js";
|
|
12
|
+
// Factory for creating and applying middleware chains
|
|
13
|
+
export { MiddlewareFactory } from "./factory.js";
|
|
14
|
+
// Re-export built-in middleware when they're implemented
|
|
15
|
+
// export { analyticsMiddleware } from './built-in/analytics.js';
|
|
16
|
+
// export { guardrailsMiddleware } from './built-in/guardrails.js';
|
|
17
|
+
// export { loggingMiddleware } from './built-in/logging.js';
|
|
18
|
+
// export { cachingMiddleware } from './built-in/caching.js';
|
|
19
|
+
// export { rateLimitMiddleware } from './built-in/rateLimit.js';
|
|
20
|
+
/**
|
|
21
|
+
* Convenience function to register a middleware
|
|
22
|
+
*/
|
|
23
|
+
export function registerMiddleware(middleware, options) {
|
|
24
|
+
middlewareRegistry.register(middleware, options);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Convenience function to unregister a middleware
|
|
28
|
+
*/
|
|
29
|
+
export function unregisterMiddleware(middlewareId) {
|
|
30
|
+
return middlewareRegistry.unregister(middlewareId);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Convenience function to get all registered middleware
|
|
34
|
+
*/
|
|
35
|
+
export function listMiddleware() {
|
|
36
|
+
return middlewareRegistry.list();
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Convenience function to check if a middleware is registered
|
|
40
|
+
*/
|
|
41
|
+
export function hasMiddleware(middlewareId) {
|
|
42
|
+
return middlewareRegistry.has(middlewareId);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Convenience function to get middleware execution statistics
|
|
46
|
+
*/
|
|
47
|
+
export function getMiddlewareStats() {
|
|
48
|
+
return middlewareRegistry.getAggregatedStats();
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Convenience function to clear middleware execution statistics
|
|
52
|
+
*/
|
|
53
|
+
export function clearMiddlewareStats(middlewareId) {
|
|
54
|
+
middlewareRegistry.clearStats(middlewareId);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Convenience function to get available middleware presets
|
|
58
|
+
*/
|
|
59
|
+
export function getAvailablePresets() {
|
|
60
|
+
return MiddlewareFactory.getAvailablePresets();
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Convenience function to validate middleware configuration
|
|
64
|
+
*/
|
|
65
|
+
export function validateMiddlewareConfig(config) {
|
|
66
|
+
return MiddlewareFactory.validateConfig(config);
|
|
67
|
+
}
|