@juspay/neurolink 7.28.1 → 7.29.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/core/baseProvider.js +4 -2
- package/dist/index.d.ts +2 -3
- package/dist/index.js +1 -2
- package/dist/lib/core/baseProvider.js +4 -2
- package/dist/lib/core/dynamicModels.d.ts +6 -6
- package/dist/lib/index.d.ts +2 -3
- package/dist/lib/index.js +1 -2
- package/dist/lib/middleware/builtin/analytics.js +13 -14
- package/dist/lib/middleware/builtin/guardrails.d.ts +20 -0
- package/dist/lib/middleware/builtin/guardrails.js +87 -0
- package/dist/lib/middleware/factory.d.ts +29 -14
- package/dist/lib/middleware/factory.js +136 -110
- package/dist/lib/middleware/index.d.ts +3 -49
- package/dist/lib/middleware/index.js +4 -58
- package/dist/lib/middleware/registry.d.ts +1 -3
- package/dist/lib/middleware/registry.js +4 -5
- package/dist/lib/middleware/types.d.ts +3 -1
- package/dist/lib/neurolink.d.ts +297 -4
- package/dist/lib/neurolink.js +297 -4
- package/dist/lib/providers/googleVertex.js +13 -4
- package/dist/middleware/builtin/analytics.js +13 -14
- package/dist/middleware/builtin/guardrails.d.ts +20 -0
- package/dist/middleware/builtin/guardrails.js +87 -0
- package/dist/middleware/factory.d.ts +29 -14
- package/dist/middleware/factory.js +136 -110
- package/dist/middleware/index.d.ts +3 -49
- package/dist/middleware/index.js +4 -58
- package/dist/middleware/registry.d.ts +1 -3
- package/dist/middleware/registry.js +4 -5
- package/dist/middleware/types.d.ts +3 -1
- package/dist/neurolink.d.ts +297 -4
- package/dist/neurolink.js +297 -4
- package/dist/providers/googleVertex.js +13 -4
- package/package.json +1 -1
|
@@ -105,10 +105,10 @@ const createVertexSettings = async () => {
|
|
|
105
105
|
// Silent error handling for runtime credentials file creation
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
|
-
// 🎯 OPTION 1: Check for principal account authentication (
|
|
108
|
+
// 🎯 OPTION 1: Check for principal account authentication (Accept any valid GOOGLE_APPLICATION_CREDENTIALS file (service account OR ADC))
|
|
109
109
|
if (process.env.GOOGLE_APPLICATION_CREDENTIALS) {
|
|
110
110
|
const credentialsPath = process.env.GOOGLE_APPLICATION_CREDENTIALS;
|
|
111
|
-
//
|
|
111
|
+
// Check if the credentials file exists
|
|
112
112
|
let fileExists = false;
|
|
113
113
|
try {
|
|
114
114
|
fileExists = fs.existsSync(credentialsPath);
|
|
@@ -1115,8 +1115,9 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
1115
1115
|
method: authValidation.method,
|
|
1116
1116
|
issues: authValidation.issues,
|
|
1117
1117
|
solutions: [
|
|
1118
|
-
"Option 1: Set GOOGLE_APPLICATION_CREDENTIALS to valid service account file",
|
|
1118
|
+
"Option 1: Set GOOGLE_APPLICATION_CREDENTIALS to valid service account OR ADC file",
|
|
1119
1119
|
"Option 2: Set individual env vars: GOOGLE_AUTH_CLIENT_EMAIL, GOOGLE_AUTH_PRIVATE_KEY",
|
|
1120
|
+
"Option 3: Use gcloud auth application-default login for ADC",
|
|
1120
1121
|
"Documentation: https://cloud.google.com/docs/authentication/provide-credentials-adc",
|
|
1121
1122
|
],
|
|
1122
1123
|
});
|
|
@@ -1268,8 +1269,16 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
1268
1269
|
result.method = "service_account_file";
|
|
1269
1270
|
return result;
|
|
1270
1271
|
}
|
|
1272
|
+
else if (credentials.client_id &&
|
|
1273
|
+
credentials.client_secret &&
|
|
1274
|
+
credentials.refresh_token &&
|
|
1275
|
+
credentials.type !== "service_account") {
|
|
1276
|
+
result.isValid = true;
|
|
1277
|
+
result.method = "application_default_credentials";
|
|
1278
|
+
return result;
|
|
1279
|
+
}
|
|
1271
1280
|
else {
|
|
1272
|
-
result.issues.push("
|
|
1281
|
+
result.issues.push("Credentials file missing required fields (not service account or ADC format)");
|
|
1273
1282
|
}
|
|
1274
1283
|
}
|
|
1275
1284
|
else {
|
|
@@ -78,20 +78,19 @@ export function createAnalyticsMiddleware() {
|
|
|
78
78
|
streamingMode: true,
|
|
79
79
|
};
|
|
80
80
|
requestMetrics.set(requestId, streamAnalytics);
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
updatedResult.rawResponse.neurolink.analytics = streamAnalytics;
|
|
81
|
+
// Ensure the result includes all required properties
|
|
82
|
+
const updatedResult = {
|
|
83
|
+
...result,
|
|
84
|
+
stream: result.stream || new ReadableStream(),
|
|
85
|
+
rawCall: result.rawCall || { rawPrompt: null, rawSettings: {} },
|
|
86
|
+
rawResponse: {
|
|
87
|
+
...(result.rawResponse || {}),
|
|
88
|
+
neurolink: {
|
|
89
|
+
...(result.rawResponse?.neurolink ?? {}),
|
|
90
|
+
analytics: streamAnalytics,
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
};
|
|
95
94
|
return updatedResult;
|
|
96
95
|
}
|
|
97
96
|
catch (error) {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { LanguageModelV1 } from "ai";
|
|
2
|
+
import type { NeuroLinkMiddleware } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for the Guardrails middleware.
|
|
5
|
+
*/
|
|
6
|
+
export interface GuardrailsMiddlewareConfig {
|
|
7
|
+
badWords?: {
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
list?: string[];
|
|
10
|
+
};
|
|
11
|
+
modelFilter?: {
|
|
12
|
+
enabled?: boolean;
|
|
13
|
+
filterModel?: LanguageModelV1;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Create Guardrails AI middleware for content filtering and policy enforcement.
|
|
18
|
+
* @param config - Configuration for the guardrails middleware.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createGuardrailsMiddleware(config?: GuardrailsMiddlewareConfig): NeuroLinkMiddleware;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { generateText } from "ai";
|
|
2
|
+
import { logger } from "../../utils/logger.js";
|
|
3
|
+
/**
|
|
4
|
+
* Create Guardrails AI middleware for content filtering and policy enforcement.
|
|
5
|
+
* @param config - Configuration for the guardrails middleware.
|
|
6
|
+
*/
|
|
7
|
+
export function createGuardrailsMiddleware(config = {}) {
|
|
8
|
+
const metadata = {
|
|
9
|
+
id: "guardrails",
|
|
10
|
+
name: "Guardrails AI",
|
|
11
|
+
description: "Provides content filtering and policy enforcement using custom rules and AI models.",
|
|
12
|
+
priority: 90,
|
|
13
|
+
defaultEnabled: true,
|
|
14
|
+
};
|
|
15
|
+
const middleware = {
|
|
16
|
+
wrapGenerate: async ({ doGenerate, params }) => {
|
|
17
|
+
logger.debug(`[GuardrailsMiddleware] Applying to generate call.`, {
|
|
18
|
+
badWordsEnabled: !!config.badWords?.enabled,
|
|
19
|
+
modelFilterEnabled: !!config.modelFilter?.enabled,
|
|
20
|
+
});
|
|
21
|
+
let result = await doGenerate();
|
|
22
|
+
// 1. Bad Word Filtering
|
|
23
|
+
if (config.badWords?.enabled && config.badWords.list) {
|
|
24
|
+
let filteredText = result.text;
|
|
25
|
+
for (const term of config.badWords.list) {
|
|
26
|
+
const regex = new RegExp(term, "gi");
|
|
27
|
+
filteredText = filteredText?.replace(regex, "*".repeat(term.length));
|
|
28
|
+
}
|
|
29
|
+
if (result.text !== filteredText) {
|
|
30
|
+
logger.debug(`[GuardrailsMiddleware] Redacted bad words from text.`);
|
|
31
|
+
result = { ...result, text: filteredText ?? "" };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// 2. Model-based Filtering
|
|
35
|
+
if (config.modelFilter?.enabled && config.modelFilter.filterModel) {
|
|
36
|
+
logger.debug(`[GuardrailsMiddleware] Invoking model-based filter.`);
|
|
37
|
+
try {
|
|
38
|
+
const filterPrompt = `Is the following text safe? Respond with only "safe" or "unsafe".\n\nText: "${result.text}"`;
|
|
39
|
+
const { text: filterResponse } = await generateText({
|
|
40
|
+
model: config.modelFilter.filterModel, // Cast as any to satisfy type, will be resolved in integration
|
|
41
|
+
prompt: filterPrompt,
|
|
42
|
+
});
|
|
43
|
+
if (filterResponse.toLowerCase().trim() === "unsafe") {
|
|
44
|
+
logger.warn(`[GuardrailsMiddleware] Model-based filter flagged content as unsafe.`);
|
|
45
|
+
result = { ...result, text: "<REDACTED BY AI GUARDRAIL>" };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
logger.error(`[GuardrailsMiddleware] Model-based filter failed.`, {
|
|
50
|
+
error,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
},
|
|
56
|
+
wrapStream: async ({ doStream, params }) => {
|
|
57
|
+
logger.debug(`[GuardrailsMiddleware] Applying to stream call.`, {
|
|
58
|
+
badWordsEnabled: !!config.badWords?.enabled,
|
|
59
|
+
});
|
|
60
|
+
const { stream, ...rest } = await doStream();
|
|
61
|
+
// Note: Model-based filtering is not applied to streams in this version
|
|
62
|
+
// as it requires the full text for analysis.
|
|
63
|
+
const transformStream = new TransformStream({
|
|
64
|
+
transform(chunk, controller) {
|
|
65
|
+
let filteredChunk = chunk;
|
|
66
|
+
if (config.badWords?.enabled && config.badWords.list) {
|
|
67
|
+
for (const term of config.badWords.list) {
|
|
68
|
+
const regex = new RegExp(term, "gi");
|
|
69
|
+
if (typeof filteredChunk === "string") {
|
|
70
|
+
filteredChunk = filteredChunk.replace(regex, "*".repeat(term.length));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
controller.enqueue(filteredChunk);
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
return {
|
|
78
|
+
stream: stream.pipeThrough(transformStream),
|
|
79
|
+
...rest,
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
return {
|
|
84
|
+
...middleware,
|
|
85
|
+
metadata,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -1,36 +1,51 @@
|
|
|
1
1
|
import type { LanguageModelV1 } from "ai";
|
|
2
|
-
import type { MiddlewareContext, MiddlewareConfig, MiddlewareFactoryOptions, MiddlewareChainStats } from "./types.js";
|
|
2
|
+
import type { MiddlewareContext, MiddlewareConfig, MiddlewareFactoryOptions, MiddlewareChainStats, MiddlewarePreset, NeuroLinkMiddleware, MiddlewareRegistrationOptions } from "./types.js";
|
|
3
|
+
import { MiddlewareRegistry } from "./registry.js";
|
|
3
4
|
/**
|
|
4
|
-
* Middleware factory for creating and applying middleware chains
|
|
5
|
+
* Middleware factory for creating and applying middleware chains.
|
|
6
|
+
* Each factory instance manages its own registry and configuration.
|
|
5
7
|
*/
|
|
6
8
|
export declare class MiddlewareFactory {
|
|
9
|
+
registry: MiddlewareRegistry;
|
|
10
|
+
presets: Map<string, MiddlewarePreset>;
|
|
11
|
+
private options;
|
|
12
|
+
constructor(options?: MiddlewareFactoryOptions);
|
|
13
|
+
/**
|
|
14
|
+
* Initialize the factory with built-in middleware and presets
|
|
15
|
+
*/
|
|
16
|
+
private initialize;
|
|
17
|
+
/**
|
|
18
|
+
* Register a custom preset
|
|
19
|
+
*/
|
|
20
|
+
registerPreset(preset: MiddlewarePreset, replace?: boolean): void;
|
|
21
|
+
/**
|
|
22
|
+
* Register a custom middleware
|
|
23
|
+
*/
|
|
24
|
+
register(middleware: NeuroLinkMiddleware, options?: MiddlewareRegistrationOptions): void;
|
|
7
25
|
/**
|
|
8
26
|
* Apply middleware to a language model
|
|
9
27
|
*/
|
|
10
|
-
|
|
28
|
+
applyMiddleware(model: LanguageModelV1, context: MiddlewareContext, options?: MiddlewareFactoryOptions): LanguageModelV1;
|
|
29
|
+
private getCreator;
|
|
11
30
|
/**
|
|
12
31
|
* Build middleware configuration from factory options
|
|
13
32
|
*/
|
|
14
|
-
private
|
|
33
|
+
private buildMiddlewareConfig;
|
|
15
34
|
/**
|
|
16
35
|
* Get preset configuration
|
|
17
36
|
*/
|
|
18
|
-
private
|
|
19
|
-
/**
|
|
20
|
-
* Get built-in preset configurations
|
|
21
|
-
*/
|
|
22
|
-
private static getBuiltInPresets;
|
|
37
|
+
private getPresetConfig;
|
|
23
38
|
/**
|
|
24
39
|
* Create middleware context from provider and options
|
|
25
40
|
*/
|
|
26
|
-
|
|
41
|
+
createContext(provider: string, model: string, options?: Record<string, unknown>, session?: {
|
|
27
42
|
sessionId?: string;
|
|
28
43
|
userId?: string;
|
|
29
44
|
}): MiddlewareContext;
|
|
30
45
|
/**
|
|
31
46
|
* Validate middleware configuration
|
|
32
47
|
*/
|
|
33
|
-
|
|
48
|
+
validateConfig(config: Record<string, MiddlewareConfig>): {
|
|
34
49
|
isValid: boolean;
|
|
35
50
|
errors: string[];
|
|
36
51
|
warnings: string[];
|
|
@@ -38,7 +53,7 @@ export declare class MiddlewareFactory {
|
|
|
38
53
|
/**
|
|
39
54
|
* Get available presets
|
|
40
55
|
*/
|
|
41
|
-
|
|
56
|
+
getAvailablePresets(): Array<{
|
|
42
57
|
name: string;
|
|
43
58
|
description: string;
|
|
44
59
|
middleware: string[];
|
|
@@ -46,9 +61,9 @@ export declare class MiddlewareFactory {
|
|
|
46
61
|
/**
|
|
47
62
|
* Get middleware chain statistics
|
|
48
63
|
*/
|
|
49
|
-
|
|
64
|
+
getChainStats(context: MiddlewareContext, config: Record<string, MiddlewareConfig>): MiddlewareChainStats;
|
|
50
65
|
/**
|
|
51
66
|
* Create a middleware-enabled model factory function
|
|
52
67
|
*/
|
|
53
|
-
|
|
68
|
+
createModelFactory(baseModelFactory: () => Promise<LanguageModelV1>, defaultOptions?: MiddlewareFactoryOptions): (context: MiddlewareContext, options?: MiddlewareFactoryOptions) => Promise<LanguageModelV1>;
|
|
54
69
|
}
|
|
@@ -1,20 +1,104 @@
|
|
|
1
1
|
import { wrapLanguageModel } from "ai";
|
|
2
|
-
import {
|
|
2
|
+
import { MiddlewareRegistry } from "./registry.js";
|
|
3
|
+
import { createAnalyticsMiddleware } from "./builtin/analytics.js";
|
|
4
|
+
import { createGuardrailsMiddleware } from "./builtin/guardrails.js";
|
|
3
5
|
import { logger } from "../utils/logger.js";
|
|
4
6
|
/**
|
|
5
|
-
* Middleware factory for creating and applying middleware chains
|
|
7
|
+
* Middleware factory for creating and applying middleware chains.
|
|
8
|
+
* Each factory instance manages its own registry and configuration.
|
|
6
9
|
*/
|
|
7
10
|
export class MiddlewareFactory {
|
|
11
|
+
registry;
|
|
12
|
+
presets = new Map();
|
|
13
|
+
options;
|
|
14
|
+
constructor(options = {}) {
|
|
15
|
+
this.options = options;
|
|
16
|
+
this.registry = new MiddlewareRegistry();
|
|
17
|
+
this.initialize(options);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Initialize the factory with built-in middleware and presets
|
|
21
|
+
*/
|
|
22
|
+
initialize(options) {
|
|
23
|
+
// Register built-in middleware creators
|
|
24
|
+
const builtInMiddlewareCreators = {
|
|
25
|
+
analytics: createAnalyticsMiddleware,
|
|
26
|
+
guardrails: createGuardrailsMiddleware,
|
|
27
|
+
};
|
|
28
|
+
// Register built-in presets
|
|
29
|
+
this.registerPreset({
|
|
30
|
+
name: "default",
|
|
31
|
+
description: "Default preset with analytics enabled.",
|
|
32
|
+
config: { analytics: { enabled: true } },
|
|
33
|
+
});
|
|
34
|
+
this.registerPreset({
|
|
35
|
+
name: "all",
|
|
36
|
+
description: "Enables all available middleware.",
|
|
37
|
+
config: { analytics: { enabled: true }, guardrails: { enabled: true } },
|
|
38
|
+
});
|
|
39
|
+
this.registerPreset({
|
|
40
|
+
name: "security",
|
|
41
|
+
description: "Focuses on security with guardrails.",
|
|
42
|
+
config: { guardrails: { enabled: true } },
|
|
43
|
+
});
|
|
44
|
+
// Register custom middleware if provided
|
|
45
|
+
if (options.middleware) {
|
|
46
|
+
for (const customMiddleware of options.middleware) {
|
|
47
|
+
this.register(customMiddleware);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Register all built-in middleware so they are available to be configured
|
|
51
|
+
for (const middlewareId in builtInMiddlewareCreators) {
|
|
52
|
+
if (!this.registry.has(middlewareId)) {
|
|
53
|
+
const creator = builtInMiddlewareCreators[middlewareId];
|
|
54
|
+
const config = options.middlewareConfig?.[middlewareId]?.config;
|
|
55
|
+
this.registry.register(creator(config));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Register a custom preset
|
|
61
|
+
*/
|
|
62
|
+
registerPreset(preset, replace = false) {
|
|
63
|
+
if (this.presets.has(preset.name) && !replace) {
|
|
64
|
+
throw new Error(`Preset with name '${preset.name}' already exists. Use replace: true to override.`);
|
|
65
|
+
}
|
|
66
|
+
this.presets.set(preset.name, preset);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Register a custom middleware
|
|
70
|
+
*/
|
|
71
|
+
register(middleware, options) {
|
|
72
|
+
this.registry.register(middleware, options);
|
|
73
|
+
}
|
|
8
74
|
/**
|
|
9
75
|
* Apply middleware to a language model
|
|
10
76
|
*/
|
|
11
|
-
|
|
77
|
+
applyMiddleware(model, context, options = {}) {
|
|
12
78
|
const startTime = Date.now();
|
|
13
79
|
try {
|
|
80
|
+
// Merge constructor options with call-time options
|
|
81
|
+
const mergedOptions = {
|
|
82
|
+
...this.options,
|
|
83
|
+
...options,
|
|
84
|
+
middlewareConfig: {
|
|
85
|
+
...this.options.middlewareConfig,
|
|
86
|
+
...options.middlewareConfig,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
14
89
|
// Build middleware configuration
|
|
15
|
-
const middlewareConfig = this.buildMiddlewareConfig(
|
|
90
|
+
const middlewareConfig = this.buildMiddlewareConfig(mergedOptions);
|
|
91
|
+
// Re-register middleware with the correct configuration for this call
|
|
92
|
+
for (const [id, config] of Object.entries(middlewareConfig)) {
|
|
93
|
+
if (config.enabled && this.registry.has(id)) {
|
|
94
|
+
const creator = this.getCreator(id);
|
|
95
|
+
if (creator) {
|
|
96
|
+
this.registry.register(creator(config.config), { replace: true });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
16
100
|
// Build middleware chain
|
|
17
|
-
const middlewareChain =
|
|
101
|
+
const middlewareChain = this.registry.buildChain(context, middlewareConfig);
|
|
18
102
|
if (middlewareChain.length === 0) {
|
|
19
103
|
logger.debug("No middleware to apply", { provider: context.provider });
|
|
20
104
|
return model;
|
|
@@ -47,25 +131,47 @@ export class MiddlewareFactory {
|
|
|
47
131
|
return model;
|
|
48
132
|
}
|
|
49
133
|
}
|
|
134
|
+
getCreator(id) {
|
|
135
|
+
const builtInMiddlewareCreators = {
|
|
136
|
+
analytics: createAnalyticsMiddleware,
|
|
137
|
+
guardrails: createGuardrailsMiddleware,
|
|
138
|
+
};
|
|
139
|
+
return builtInMiddlewareCreators[id];
|
|
140
|
+
}
|
|
50
141
|
/**
|
|
51
142
|
* Build middleware configuration from factory options
|
|
52
143
|
*/
|
|
53
|
-
|
|
144
|
+
buildMiddlewareConfig(options) {
|
|
54
145
|
const config = {};
|
|
55
|
-
|
|
56
|
-
|
|
146
|
+
const allMiddleware = this.registry.list();
|
|
147
|
+
// Initialize all middleware as disabled. Configuration will enable them.
|
|
57
148
|
for (const middleware of allMiddleware) {
|
|
58
|
-
// Default configuration
|
|
59
149
|
config[middleware.metadata.id] = {
|
|
60
|
-
enabled:
|
|
150
|
+
enabled: false,
|
|
61
151
|
config: {},
|
|
62
152
|
};
|
|
63
153
|
}
|
|
64
|
-
//
|
|
65
|
-
|
|
66
|
-
|
|
154
|
+
// Determine which preset to use.
|
|
155
|
+
let presetName = options.preset;
|
|
156
|
+
// If no preset is given, and no other specific middleware config is provided, use the default.
|
|
157
|
+
if (!presetName &&
|
|
158
|
+
(!options.middlewareConfig ||
|
|
159
|
+
Object.keys(options.middlewareConfig).length === 0) &&
|
|
160
|
+
(!options.enabledMiddleware || options.enabledMiddleware.length === 0)) {
|
|
161
|
+
presetName = "default";
|
|
162
|
+
}
|
|
163
|
+
// Apply preset configuration
|
|
164
|
+
if (presetName) {
|
|
165
|
+
const presetConfig = this.getPresetConfig(presetName);
|
|
67
166
|
if (presetConfig) {
|
|
68
|
-
Object.
|
|
167
|
+
for (const [middlewareId, middlewareConfig] of Object.entries(presetConfig)) {
|
|
168
|
+
if (config[middlewareId]) {
|
|
169
|
+
config[middlewareId] = {
|
|
170
|
+
...config[middlewareId],
|
|
171
|
+
...middlewareConfig,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
69
175
|
}
|
|
70
176
|
}
|
|
71
177
|
// Apply explicit middleware configurations
|
|
@@ -98,59 +204,14 @@ export class MiddlewareFactory {
|
|
|
98
204
|
/**
|
|
99
205
|
* Get preset configuration
|
|
100
206
|
*/
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
return
|
|
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
|
-
};
|
|
207
|
+
getPresetConfig(presetName) {
|
|
208
|
+
const preset = this.presets.get(presetName);
|
|
209
|
+
return preset ? preset.config : null;
|
|
149
210
|
}
|
|
150
211
|
/**
|
|
151
212
|
* Create middleware context from provider and options
|
|
152
213
|
*/
|
|
153
|
-
|
|
214
|
+
createContext(provider, model, options = {}, session) {
|
|
154
215
|
return {
|
|
155
216
|
provider,
|
|
156
217
|
model,
|
|
@@ -165,12 +226,12 @@ export class MiddlewareFactory {
|
|
|
165
226
|
/**
|
|
166
227
|
* Validate middleware configuration
|
|
167
228
|
*/
|
|
168
|
-
|
|
229
|
+
validateConfig(config) {
|
|
169
230
|
const errors = [];
|
|
170
231
|
const warnings = [];
|
|
171
232
|
for (const [middlewareId, middlewareConfig] of Object.entries(config)) {
|
|
172
233
|
// Check if middleware is registered
|
|
173
|
-
if (!
|
|
234
|
+
if (!this.registry.has(middlewareId)) {
|
|
174
235
|
errors.push(`Middleware '${middlewareId}' is not registered`);
|
|
175
236
|
continue;
|
|
176
237
|
}
|
|
@@ -198,54 +259,19 @@ export class MiddlewareFactory {
|
|
|
198
259
|
/**
|
|
199
260
|
* Get available presets
|
|
200
261
|
*/
|
|
201
|
-
|
|
202
|
-
return
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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
|
-
];
|
|
262
|
+
getAvailablePresets() {
|
|
263
|
+
return Array.from(this.presets.values()).map((preset) => ({
|
|
264
|
+
name: preset.name,
|
|
265
|
+
description: preset.description,
|
|
266
|
+
middleware: Object.keys(preset.config),
|
|
267
|
+
}));
|
|
242
268
|
}
|
|
243
269
|
/**
|
|
244
270
|
* Get middleware chain statistics
|
|
245
271
|
*/
|
|
246
|
-
|
|
247
|
-
const chain =
|
|
248
|
-
const stats =
|
|
272
|
+
getChainStats(context, config) {
|
|
273
|
+
const chain = this.registry.buildChain(context, config);
|
|
274
|
+
const stats = this.registry.getAggregatedStats();
|
|
249
275
|
const results = {};
|
|
250
276
|
let totalExecutionTime = 0;
|
|
251
277
|
let appliedMiddleware = 0;
|
|
@@ -269,7 +295,7 @@ export class MiddlewareFactory {
|
|
|
269
295
|
/**
|
|
270
296
|
* Create a middleware-enabled model factory function
|
|
271
297
|
*/
|
|
272
|
-
|
|
298
|
+
createModelFactory(baseModelFactory, defaultOptions = {}) {
|
|
273
299
|
return async (context, options = {}) => {
|
|
274
300
|
// Get base model
|
|
275
301
|
const baseModel = await baseModelFactory();
|
|
@@ -5,54 +5,8 @@
|
|
|
5
5
|
* with the AI SDK's wrapLanguageModel functionality. It allows for modular enhancement
|
|
6
6
|
* of language models with features like analytics, guardrails, caching, and more.
|
|
7
7
|
*/
|
|
8
|
-
import
|
|
8
|
+
import { MiddlewareFactory } from "./factory.js";
|
|
9
9
|
export type { NeuroLinkMiddleware, MiddlewareConfig, MiddlewareContext, MiddlewareConditions, MiddlewareRegistrationOptions, MiddlewareExecutionResult, MiddlewareChainStats, MiddlewarePreset, MiddlewareFactoryOptions, BuiltInMiddlewareType, } from "./types.js";
|
|
10
10
|
export type { LanguageModelV1Middleware } from "ai";
|
|
11
|
-
export {
|
|
12
|
-
export
|
|
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
|
-
};
|
|
11
|
+
export { MiddlewareFactory };
|
|
12
|
+
export default MiddlewareFactory;
|