ai.matey.middleware 0.2.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/LICENSE +21 -0
- package/dist/cjs/caching.js +226 -0
- package/dist/cjs/caching.js.map +1 -0
- package/dist/cjs/conversation-history.js +213 -0
- package/dist/cjs/conversation-history.js.map +1 -0
- package/dist/cjs/cost-tracking.js +355 -0
- package/dist/cjs/cost-tracking.js.map +1 -0
- package/dist/cjs/index.js +37 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/logging.js +174 -0
- package/dist/cjs/logging.js.map +1 -0
- package/dist/cjs/opentelemetry.js +499 -0
- package/dist/cjs/opentelemetry.js.map +1 -0
- package/dist/cjs/retry.js +205 -0
- package/dist/cjs/retry.js.map +1 -0
- package/dist/cjs/security.js +175 -0
- package/dist/cjs/security.js.map +1 -0
- package/dist/cjs/telemetry.js +216 -0
- package/dist/cjs/telemetry.js.map +1 -0
- package/dist/cjs/transform.js +284 -0
- package/dist/cjs/transform.js.map +1 -0
- package/dist/cjs/validation.js +506 -0
- package/dist/cjs/validation.js.map +1 -0
- package/dist/esm/caching.js +221 -0
- package/dist/esm/caching.js.map +1 -0
- package/dist/esm/conversation-history.js +207 -0
- package/dist/esm/conversation-history.js.map +1 -0
- package/dist/esm/cost-tracking.js +347 -0
- package/dist/esm/cost-tracking.js.map +1 -0
- package/dist/esm/index.js +21 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/logging.js +171 -0
- package/dist/esm/logging.js.map +1 -0
- package/dist/esm/opentelemetry.js +458 -0
- package/dist/esm/opentelemetry.js.map +1 -0
- package/dist/esm/retry.js +198 -0
- package/dist/esm/retry.js.map +1 -0
- package/dist/esm/security.js +169 -0
- package/dist/esm/security.js.map +1 -0
- package/dist/esm/telemetry.js +210 -0
- package/dist/esm/telemetry.js.map +1 -0
- package/dist/esm/transform.js +272 -0
- package/dist/esm/transform.js.map +1 -0
- package/dist/esm/validation.js +494 -0
- package/dist/esm/validation.js.map +1 -0
- package/dist/types/caching.d.ts +98 -0
- package/dist/types/caching.d.ts.map +1 -0
- package/dist/types/conversation-history.d.ts +188 -0
- package/dist/types/conversation-history.d.ts.map +1 -0
- package/dist/types/cost-tracking.d.ts +262 -0
- package/dist/types/cost-tracking.d.ts.map +1 -0
- package/dist/types/index.d.ts +20 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/logging.d.ts +82 -0
- package/dist/types/logging.d.ts.map +1 -0
- package/dist/types/opentelemetry.d.ts +219 -0
- package/dist/types/opentelemetry.d.ts.map +1 -0
- package/dist/types/retry.d.ts +86 -0
- package/dist/types/retry.d.ts.map +1 -0
- package/dist/types/security.d.ts +120 -0
- package/dist/types/security.d.ts.map +1 -0
- package/dist/types/telemetry.d.ts +120 -0
- package/dist/types/telemetry.d.ts.map +1 -0
- package/dist/types/transform.d.ts +184 -0
- package/dist/types/transform.d.ts.map +1 -0
- package/dist/types/validation.d.ts +356 -0
- package/dist/types/validation.d.ts.map +1 -0
- package/package.json +203 -0
- package/readme.md +103 -0
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Input Validation & Sanitization Middleware
|
|
4
|
+
*
|
|
5
|
+
* Validates and sanitizes requests to prevent security issues and ensure data quality.
|
|
6
|
+
*
|
|
7
|
+
* ## Separation of Concerns
|
|
8
|
+
*
|
|
9
|
+
* This middleware focuses on **SECURITY validation**:
|
|
10
|
+
* - PII detection and redaction
|
|
11
|
+
* - Prompt injection prevention
|
|
12
|
+
* - Content moderation
|
|
13
|
+
* - Message length/token limits
|
|
14
|
+
* - Sanitization
|
|
15
|
+
*
|
|
16
|
+
* For **IR format validation** (structural correctness), use ai.matey.utils/validation.ts:
|
|
17
|
+
* - Message structure and content validation
|
|
18
|
+
* - Parameter type and range validation
|
|
19
|
+
* - Request format validation
|
|
20
|
+
*
|
|
21
|
+
* @module
|
|
22
|
+
*/
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.DEFAULT_INJECTION_PATTERNS = exports.DEFAULT_PII_PATTERNS = void 0;
|
|
25
|
+
exports.detectPII = detectPII;
|
|
26
|
+
exports.redactPII = redactPII;
|
|
27
|
+
exports.detectPromptInjection = detectPromptInjection;
|
|
28
|
+
exports.sanitizeText = sanitizeText;
|
|
29
|
+
exports.validateRequest = validateRequest;
|
|
30
|
+
exports.sanitizeRequest = sanitizeRequest;
|
|
31
|
+
exports.createValidationMiddleware = createValidationMiddleware;
|
|
32
|
+
exports.createProductionValidationMiddleware = createProductionValidationMiddleware;
|
|
33
|
+
exports.createDevelopmentValidationMiddleware = createDevelopmentValidationMiddleware;
|
|
34
|
+
const ai_matey_errors_1 = require("ai.matey.errors");
|
|
35
|
+
const ai_matey_utils_1 = require("ai.matey.utils");
|
|
36
|
+
/**
|
|
37
|
+
* Helper to create a structured validation error from simple field/value/message
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
40
|
+
function createValidationError(message, field, value, provenance) {
|
|
41
|
+
return new ai_matey_errors_1.ValidationError({
|
|
42
|
+
code: ai_matey_errors_1.ErrorCode.INVALID_REQUEST,
|
|
43
|
+
message,
|
|
44
|
+
validationDetails: [
|
|
45
|
+
{
|
|
46
|
+
field,
|
|
47
|
+
value,
|
|
48
|
+
reason: message,
|
|
49
|
+
expected: 'Valid value',
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
provenance,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Default PII patterns
|
|
57
|
+
*/
|
|
58
|
+
exports.DEFAULT_PII_PATTERNS = {
|
|
59
|
+
// Email addresses
|
|
60
|
+
email: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,
|
|
61
|
+
// US Social Security Numbers
|
|
62
|
+
ssn: /\b\d{3}-\d{2}-\d{4}\b/g,
|
|
63
|
+
// Credit card numbers (basic pattern)
|
|
64
|
+
creditCard: /\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/g,
|
|
65
|
+
// US Phone numbers
|
|
66
|
+
phone: /\b(\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g,
|
|
67
|
+
// IP addresses
|
|
68
|
+
ipAddress: /\b(?:\d{1,3}\.){3}\d{1,3}\b/g,
|
|
69
|
+
// API keys (common patterns)
|
|
70
|
+
apiKey: /\b[A-Za-z0-9]{32,}\b/g,
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Default prompt injection patterns
|
|
74
|
+
*/
|
|
75
|
+
exports.DEFAULT_INJECTION_PATTERNS = [
|
|
76
|
+
// Ignore previous instructions
|
|
77
|
+
/ignore\s+(previous|above|all)\s+(instructions|prompts?|commands?)/i,
|
|
78
|
+
// System prompt manipulation
|
|
79
|
+
/system\s*:\s*new\s+(instruction|prompt|role)/i,
|
|
80
|
+
// Jailbreak attempts
|
|
81
|
+
/\b(jailbreak|DAN|developer\s+mode)\b/i,
|
|
82
|
+
// Role manipulation
|
|
83
|
+
/(you\s+are\s+now|act\s+as\s+if\s+you\s+are)\s+a\s+/i,
|
|
84
|
+
// Instruction override
|
|
85
|
+
/disregard\s+(all|any|previous|above)/i,
|
|
86
|
+
];
|
|
87
|
+
/**
|
|
88
|
+
* Detect PII in text
|
|
89
|
+
*/
|
|
90
|
+
function detectPII(text, patterns = exports.DEFAULT_PII_PATTERNS) {
|
|
91
|
+
const matches = [];
|
|
92
|
+
const types = [];
|
|
93
|
+
for (const [type, pattern] of Object.entries(patterns)) {
|
|
94
|
+
const found = text.match(pattern);
|
|
95
|
+
if (found && found.length > 0) {
|
|
96
|
+
types.push(type);
|
|
97
|
+
for (const value of found) {
|
|
98
|
+
matches.push({ type, value });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
detected: matches.length > 0,
|
|
104
|
+
types: Array.from(new Set(types)),
|
|
105
|
+
matches,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Redact PII from text
|
|
110
|
+
*/
|
|
111
|
+
function redactPII(text, patterns = exports.DEFAULT_PII_PATTERNS) {
|
|
112
|
+
let redacted = text;
|
|
113
|
+
for (const [type, pattern] of Object.entries(patterns)) {
|
|
114
|
+
redacted = redacted.replace(pattern, `[REDACTED_${type.toUpperCase()}]`);
|
|
115
|
+
}
|
|
116
|
+
return redacted;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Detect prompt injection attempts
|
|
120
|
+
*/
|
|
121
|
+
function detectPromptInjection(text, patterns = exports.DEFAULT_INJECTION_PATTERNS) {
|
|
122
|
+
return patterns.some((pattern) => pattern.test(text));
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Sanitize text content
|
|
126
|
+
*/
|
|
127
|
+
function sanitizeText(text) {
|
|
128
|
+
// Remove null bytes
|
|
129
|
+
let sanitized = text.replace(/\0/g, '');
|
|
130
|
+
// Normalize whitespace (but preserve intentional formatting)
|
|
131
|
+
sanitized = sanitized.replace(/\r\n/g, '\n');
|
|
132
|
+
// Remove invisible characters (zero-width, etc.)
|
|
133
|
+
sanitized = sanitized.replace(/[\u200B-\u200D\uFEFF]/g, '');
|
|
134
|
+
return sanitized;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Estimate token count (rough approximation)
|
|
138
|
+
*/
|
|
139
|
+
function estimateTokens(text) {
|
|
140
|
+
// Rough estimate: ~4 characters per token
|
|
141
|
+
return Math.ceil(text.length / 4);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Extract text from message content
|
|
145
|
+
*/
|
|
146
|
+
function extractText(content) {
|
|
147
|
+
if (typeof content === 'string') {
|
|
148
|
+
return content;
|
|
149
|
+
}
|
|
150
|
+
return content
|
|
151
|
+
.filter((c) => c.type === 'text')
|
|
152
|
+
.map((c) => c.text)
|
|
153
|
+
.join('\n');
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Validate request
|
|
157
|
+
*/
|
|
158
|
+
async function validateRequest(request, config) {
|
|
159
|
+
const errors = [];
|
|
160
|
+
const warnings = [];
|
|
161
|
+
// Perform IR format validation first if enabled
|
|
162
|
+
if (config.validateIRFormat) {
|
|
163
|
+
try {
|
|
164
|
+
(0, ai_matey_utils_1.validateIRChatRequest)(request);
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
if (error instanceof ai_matey_errors_1.ValidationError) {
|
|
168
|
+
errors.push(error);
|
|
169
|
+
// If format validation fails, return early as security checks may not make sense
|
|
170
|
+
return { valid: false, errors, warnings };
|
|
171
|
+
}
|
|
172
|
+
throw error;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// Validate message count
|
|
176
|
+
if (config.maxMessages && request.messages.length > config.maxMessages) {
|
|
177
|
+
errors.push(createValidationError(`Too many messages: ${request.messages.length} > ${config.maxMessages}`, 'messages', request.messages.length));
|
|
178
|
+
}
|
|
179
|
+
// Validate messages
|
|
180
|
+
let totalTokens = 0;
|
|
181
|
+
const messagesArray = Array.from(request.messages);
|
|
182
|
+
for (let i = 0; i < messagesArray.length; i++) {
|
|
183
|
+
const message = messagesArray[i];
|
|
184
|
+
if (!message) {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
// Check allowed roles
|
|
188
|
+
if (config.allowedRoles &&
|
|
189
|
+
!config.allowedRoles.includes(message.role)) {
|
|
190
|
+
errors.push(createValidationError(`Invalid message role: ${message.role}`, `messages[${i}].role`, message.role));
|
|
191
|
+
}
|
|
192
|
+
// Extract text
|
|
193
|
+
const text = extractText(message.content);
|
|
194
|
+
// Check empty messages
|
|
195
|
+
if (config.blockEmptyMessages !== false && text.trim().length === 0) {
|
|
196
|
+
errors.push(createValidationError(`Empty message at index ${i}`, `messages[${i}].content`, text));
|
|
197
|
+
}
|
|
198
|
+
// Check message length
|
|
199
|
+
if (config.maxMessageLength && text.length > config.maxMessageLength) {
|
|
200
|
+
errors.push(createValidationError(`Message too long: ${text.length} > ${config.maxMessageLength}`, `messages[${i}].content`, text.length));
|
|
201
|
+
}
|
|
202
|
+
// Estimate tokens
|
|
203
|
+
const tokens = estimateTokens(text);
|
|
204
|
+
totalTokens += tokens;
|
|
205
|
+
// Check tokens per message
|
|
206
|
+
if (config.maxTokensPerMessage && tokens > config.maxTokensPerMessage) {
|
|
207
|
+
errors.push(createValidationError(`Message tokens exceed limit: ${tokens} > ${config.maxTokensPerMessage}`, `messages[${i}].content`, tokens));
|
|
208
|
+
}
|
|
209
|
+
// Detect PII
|
|
210
|
+
if (config.detectPII) {
|
|
211
|
+
const piiResult = config.piiDetector
|
|
212
|
+
? await config.piiDetector(text)
|
|
213
|
+
: detectPII(text, config.piiPatterns);
|
|
214
|
+
if (piiResult.detected) {
|
|
215
|
+
const message = `PII detected in message ${i}: ${piiResult.types.join(', ')}`;
|
|
216
|
+
if (config.piiAction === 'block') {
|
|
217
|
+
errors.push(createValidationError(message, `messages[${i}].content`, piiResult));
|
|
218
|
+
}
|
|
219
|
+
else if (config.piiAction === 'warn' || config.piiAction === 'log') {
|
|
220
|
+
warnings.push(message);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// Detect prompt injection
|
|
225
|
+
if (config.preventPromptInjection !== false) {
|
|
226
|
+
const hasInjection = detectPromptInjection(text, config.injectionPatterns);
|
|
227
|
+
if (hasInjection) {
|
|
228
|
+
errors.push(createValidationError(`Potential prompt injection detected in message ${i}`, `messages[${i}].content`, text));
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// Content moderation
|
|
232
|
+
if (config.moderationCallback) {
|
|
233
|
+
const modResult = await config.moderationCallback(text);
|
|
234
|
+
if (modResult.flagged) {
|
|
235
|
+
const message = `Content flagged by moderation in message ${i}: ${modResult.categories.join(', ')}`;
|
|
236
|
+
if (config.blockFlaggedContent) {
|
|
237
|
+
errors.push(createValidationError(message, `messages[${i}].content`, modResult));
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
warnings.push(message);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// Check total tokens
|
|
246
|
+
if (config.maxTotalTokens && totalTokens > config.maxTotalTokens) {
|
|
247
|
+
errors.push(createValidationError(`Total tokens exceed limit: ${totalTokens} > ${config.maxTotalTokens}`, 'messages', totalTokens));
|
|
248
|
+
}
|
|
249
|
+
// Validate model
|
|
250
|
+
if (config.validateModel && request.parameters?.model) {
|
|
251
|
+
if (config.allowedModels && !config.allowedModels.includes(request.parameters.model)) {
|
|
252
|
+
errors.push(createValidationError(`Model not allowed: ${request.parameters.model}`, 'parameters.model', request.parameters.model));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// Validate temperature (deprecated - use validateIRFormat instead)
|
|
256
|
+
if (config.validateTemperature && request.parameters?.temperature !== undefined) {
|
|
257
|
+
try {
|
|
258
|
+
(0, ai_matey_utils_1.validateTemperature)(request.parameters.temperature);
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
if (error instanceof ai_matey_errors_1.ValidationError) {
|
|
262
|
+
errors.push(error);
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
throw error;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// Custom validation
|
|
270
|
+
if (config.customValidator) {
|
|
271
|
+
const customErrors = await config.customValidator(request);
|
|
272
|
+
errors.push(...customErrors);
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
valid: errors.length === 0,
|
|
276
|
+
errors,
|
|
277
|
+
warnings,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Sanitize request
|
|
282
|
+
*/
|
|
283
|
+
function sanitizeRequest(request, config) {
|
|
284
|
+
if (config.sanitizeMessages === false) {
|
|
285
|
+
return request;
|
|
286
|
+
}
|
|
287
|
+
const sanitizer = config.sanitizer || sanitizeText;
|
|
288
|
+
// Sanitize messages
|
|
289
|
+
const sanitizedMessages = request.messages.map((message) => {
|
|
290
|
+
if (typeof message.content === 'string') {
|
|
291
|
+
return {
|
|
292
|
+
...message,
|
|
293
|
+
content: sanitizer(message.content),
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
return {
|
|
297
|
+
...message,
|
|
298
|
+
content: message.content.map((content) => {
|
|
299
|
+
if (content.type === 'text') {
|
|
300
|
+
return {
|
|
301
|
+
...content,
|
|
302
|
+
text: sanitizer(content.text),
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
return content;
|
|
306
|
+
}),
|
|
307
|
+
};
|
|
308
|
+
});
|
|
309
|
+
// Redact PII if configured
|
|
310
|
+
if (config.detectPII && config.piiAction === 'redact') {
|
|
311
|
+
const patterns = config.piiPatterns || exports.DEFAULT_PII_PATTERNS;
|
|
312
|
+
return {
|
|
313
|
+
...request,
|
|
314
|
+
messages: sanitizedMessages.map((message) => {
|
|
315
|
+
if (typeof message.content === 'string') {
|
|
316
|
+
return {
|
|
317
|
+
...message,
|
|
318
|
+
content: redactPII(message.content, patterns),
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
return {
|
|
322
|
+
...message,
|
|
323
|
+
content: message.content.map((content) => {
|
|
324
|
+
if (content.type === 'text') {
|
|
325
|
+
return {
|
|
326
|
+
...content,
|
|
327
|
+
text: redactPII(content.text, patterns),
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
return content;
|
|
331
|
+
}),
|
|
332
|
+
};
|
|
333
|
+
}),
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
return {
|
|
337
|
+
...request,
|
|
338
|
+
messages: sanitizedMessages,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Create input validation middleware
|
|
343
|
+
*
|
|
344
|
+
* Validates and sanitizes requests to prevent security issues and ensure data quality.
|
|
345
|
+
*
|
|
346
|
+
* @param config - Validation configuration
|
|
347
|
+
* @returns Middleware function
|
|
348
|
+
*
|
|
349
|
+
* @example Basic Usage
|
|
350
|
+
* ```typescript
|
|
351
|
+
* import { createValidationMiddleware } from 'ai.matey';
|
|
352
|
+
*
|
|
353
|
+
* const validation = createValidationMiddleware({
|
|
354
|
+
* maxMessages: 100,
|
|
355
|
+
* maxTotalTokens: 128000,
|
|
356
|
+
* preventPromptInjection: true,
|
|
357
|
+
* });
|
|
358
|
+
*
|
|
359
|
+
* bridge.use(validation);
|
|
360
|
+
* ```
|
|
361
|
+
*
|
|
362
|
+
* @example PII Detection & Redaction
|
|
363
|
+
* ```typescript
|
|
364
|
+
* const validation = createValidationMiddleware({
|
|
365
|
+
* detectPII: true,
|
|
366
|
+
* piiAction: 'redact', // or 'block', 'warn', 'log'
|
|
367
|
+
* piiPatterns: {
|
|
368
|
+
* email: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,
|
|
369
|
+
* ssn: /\b\d{3}-\d{2}-\d{4}\b/g,
|
|
370
|
+
* },
|
|
371
|
+
* });
|
|
372
|
+
* ```
|
|
373
|
+
*
|
|
374
|
+
* @example Content Moderation
|
|
375
|
+
* ```typescript
|
|
376
|
+
* const validation = createValidationMiddleware({
|
|
377
|
+
* moderationCallback: async (content) => {
|
|
378
|
+
* // Call external moderation API
|
|
379
|
+
* const result = await moderationAPI.check(content);
|
|
380
|
+
* return {
|
|
381
|
+
* flagged: result.flagged,
|
|
382
|
+
* categories: result.categories,
|
|
383
|
+
* scores: result.scores,
|
|
384
|
+
* };
|
|
385
|
+
* },
|
|
386
|
+
* blockFlaggedContent: true,
|
|
387
|
+
* });
|
|
388
|
+
* ```
|
|
389
|
+
*
|
|
390
|
+
* @example Custom Validation
|
|
391
|
+
* ```typescript
|
|
392
|
+
* const validation = createValidationMiddleware({
|
|
393
|
+
* customValidator: async (request) => {
|
|
394
|
+
* const errors: ValidationError[] = [];
|
|
395
|
+
*
|
|
396
|
+
* // Custom business logic
|
|
397
|
+
* if (request.messages.some(m => m.content.includes('forbidden'))) {
|
|
398
|
+
* errors.push(new ValidationError(
|
|
399
|
+
* 'Forbidden content detected',
|
|
400
|
+
* 'messages',
|
|
401
|
+
* 'forbidden'
|
|
402
|
+
* ));
|
|
403
|
+
* }
|
|
404
|
+
*
|
|
405
|
+
* return errors;
|
|
406
|
+
* },
|
|
407
|
+
* });
|
|
408
|
+
* ```
|
|
409
|
+
*
|
|
410
|
+
* @example Production Configuration
|
|
411
|
+
* ```typescript
|
|
412
|
+
* const validation = createValidationMiddleware({
|
|
413
|
+
* maxMessages: 100,
|
|
414
|
+
* maxTotalTokens: 128000,
|
|
415
|
+
* maxTokensPerMessage: 32000,
|
|
416
|
+
* maxMessageLength: 100000,
|
|
417
|
+
* blockEmptyMessages: true,
|
|
418
|
+
* detectPII: true,
|
|
419
|
+
* piiAction: 'redact',
|
|
420
|
+
* preventPromptInjection: true,
|
|
421
|
+
* sanitizeMessages: true,
|
|
422
|
+
* validateModel: true,
|
|
423
|
+
* allowedModels: ['gpt-4', 'claude-3-sonnet', 'gemini-pro'],
|
|
424
|
+
* validateTemperature: true,
|
|
425
|
+
* temperatureRange: [0, 2],
|
|
426
|
+
* throwOnError: true,
|
|
427
|
+
* logWarnings: true,
|
|
428
|
+
* });
|
|
429
|
+
* ```
|
|
430
|
+
*/
|
|
431
|
+
function createValidationMiddleware(config = {}) {
|
|
432
|
+
return async (context, next) => {
|
|
433
|
+
// Validate request
|
|
434
|
+
const validationResult = await validateRequest(context.request, config);
|
|
435
|
+
// Log warnings
|
|
436
|
+
if (config.logWarnings !== false && validationResult.warnings.length > 0) {
|
|
437
|
+
for (const warning of validationResult.warnings) {
|
|
438
|
+
console.warn(`[Validation] ${warning}`);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
// Handle validation errors
|
|
442
|
+
if (!validationResult.valid) {
|
|
443
|
+
const errorMessage = validationResult.errors.map((e) => e.message).join('; ');
|
|
444
|
+
if (config.throwOnError !== false) {
|
|
445
|
+
throw createValidationError(`Validation failed: ${errorMessage}`, 'request', validationResult.errors);
|
|
446
|
+
}
|
|
447
|
+
// Log errors but continue
|
|
448
|
+
console.error(`[Validation] Errors: ${errorMessage}`);
|
|
449
|
+
}
|
|
450
|
+
// Sanitize request
|
|
451
|
+
context.request = sanitizeRequest(context.request, config);
|
|
452
|
+
// Continue to next middleware
|
|
453
|
+
return await next();
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Create production-ready validation middleware with strict settings
|
|
458
|
+
*
|
|
459
|
+
* @returns Middleware with production validation settings
|
|
460
|
+
*
|
|
461
|
+
* @example
|
|
462
|
+
* ```typescript
|
|
463
|
+
* import { createProductionValidationMiddleware } from 'ai.matey';
|
|
464
|
+
*
|
|
465
|
+
* bridge.use(createProductionValidationMiddleware());
|
|
466
|
+
* ```
|
|
467
|
+
*/
|
|
468
|
+
function createProductionValidationMiddleware() {
|
|
469
|
+
return createValidationMiddleware({
|
|
470
|
+
maxMessages: 100,
|
|
471
|
+
maxTotalTokens: 128000,
|
|
472
|
+
maxTokensPerMessage: 32000,
|
|
473
|
+
maxMessageLength: 100000,
|
|
474
|
+
blockEmptyMessages: true,
|
|
475
|
+
detectPII: true,
|
|
476
|
+
piiAction: 'redact',
|
|
477
|
+
preventPromptInjection: true,
|
|
478
|
+
sanitizeMessages: true,
|
|
479
|
+
throwOnError: true,
|
|
480
|
+
logWarnings: true,
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Create development-friendly validation middleware with relaxed settings
|
|
485
|
+
*
|
|
486
|
+
* @returns Middleware with development validation settings
|
|
487
|
+
*
|
|
488
|
+
* @example
|
|
489
|
+
* ```typescript
|
|
490
|
+
* import { createDevelopmentValidationMiddleware } from 'ai.matey';
|
|
491
|
+
*
|
|
492
|
+
* bridge.use(createDevelopmentValidationMiddleware());
|
|
493
|
+
* ```
|
|
494
|
+
*/
|
|
495
|
+
function createDevelopmentValidationMiddleware() {
|
|
496
|
+
return createValidationMiddleware({
|
|
497
|
+
maxMessages: 1000,
|
|
498
|
+
blockEmptyMessages: false,
|
|
499
|
+
detectPII: false,
|
|
500
|
+
preventPromptInjection: false,
|
|
501
|
+
sanitizeMessages: true,
|
|
502
|
+
throwOnError: false,
|
|
503
|
+
logWarnings: true,
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/validation.ts"],"names":[],"mappings":"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"}
|