ai-sdk-guardrails 1.0.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.
@@ -0,0 +1,36 @@
1
+ import { I as InputGuardrailContext, a as InputGuardrail } from '../index-CWIb12lh.cjs';
2
+ import 'ai';
3
+
4
+ declare function extractTextContent(context: InputGuardrailContext): {
5
+ prompt: string;
6
+ messages: Array<{
7
+ content?: unknown;
8
+ }>;
9
+ system: string;
10
+ };
11
+ declare function extractMetadata(context: InputGuardrailContext): {
12
+ model?: unknown;
13
+ temperature?: number;
14
+ maxTokens?: number;
15
+ };
16
+ declare const lengthLimit: (maxLength: number) => InputGuardrail;
17
+ declare const blockedWords: (words: string[]) => InputGuardrail;
18
+ declare const contentLengthLimit: (maxLength: number) => InputGuardrail;
19
+ declare const blockedKeywords: (keywords: string[]) => InputGuardrail;
20
+ declare const rateLimiting: (maxRequestsPerMinute: number) => InputGuardrail;
21
+ declare const profanityFilter: (customWords?: string[]) => InputGuardrail;
22
+ declare const customValidation: (name: string, description: string, validator: (input: {
23
+ prompt?: string;
24
+ messages?: unknown[];
25
+ system?: string;
26
+ model?: unknown;
27
+ temperature?: number;
28
+ maxTokens?: number;
29
+ }) => boolean, message: string) => InputGuardrail;
30
+ declare const promptInjectionDetector: () => InputGuardrail;
31
+ declare const piiDetector: () => InputGuardrail;
32
+ declare const toxicityDetector: (threshold?: number) => InputGuardrail;
33
+ declare const mathHomeworkDetector: () => InputGuardrail;
34
+ declare const codeGenerationLimiter: (allowedLanguages?: string[]) => InputGuardrail;
35
+
36
+ export { blockedKeywords, blockedWords, codeGenerationLimiter, contentLengthLimit, customValidation, extractMetadata, extractTextContent, lengthLimit, mathHomeworkDetector, piiDetector, profanityFilter, promptInjectionDetector, rateLimiting, toxicityDetector };
@@ -0,0 +1,36 @@
1
+ import { I as InputGuardrailContext, a as InputGuardrail } from '../index-CWIb12lh.js';
2
+ import 'ai';
3
+
4
+ declare function extractTextContent(context: InputGuardrailContext): {
5
+ prompt: string;
6
+ messages: Array<{
7
+ content?: unknown;
8
+ }>;
9
+ system: string;
10
+ };
11
+ declare function extractMetadata(context: InputGuardrailContext): {
12
+ model?: unknown;
13
+ temperature?: number;
14
+ maxTokens?: number;
15
+ };
16
+ declare const lengthLimit: (maxLength: number) => InputGuardrail;
17
+ declare const blockedWords: (words: string[]) => InputGuardrail;
18
+ declare const contentLengthLimit: (maxLength: number) => InputGuardrail;
19
+ declare const blockedKeywords: (keywords: string[]) => InputGuardrail;
20
+ declare const rateLimiting: (maxRequestsPerMinute: number) => InputGuardrail;
21
+ declare const profanityFilter: (customWords?: string[]) => InputGuardrail;
22
+ declare const customValidation: (name: string, description: string, validator: (input: {
23
+ prompt?: string;
24
+ messages?: unknown[];
25
+ system?: string;
26
+ model?: unknown;
27
+ temperature?: number;
28
+ maxTokens?: number;
29
+ }) => boolean, message: string) => InputGuardrail;
30
+ declare const promptInjectionDetector: () => InputGuardrail;
31
+ declare const piiDetector: () => InputGuardrail;
32
+ declare const toxicityDetector: (threshold?: number) => InputGuardrail;
33
+ declare const mathHomeworkDetector: () => InputGuardrail;
34
+ declare const codeGenerationLimiter: (allowedLanguages?: string[]) => InputGuardrail;
35
+
36
+ export { blockedKeywords, blockedWords, codeGenerationLimiter, contentLengthLimit, customValidation, extractMetadata, extractTextContent, lengthLimit, mathHomeworkDetector, piiDetector, profanityFilter, promptInjectionDetector, rateLimiting, toxicityDetector };
@@ -0,0 +1,445 @@
1
+ import {
2
+ createInputGuardrail
3
+ } from "../chunk-BNGJDZMX.js";
4
+
5
+ // src/guardrails/input.ts
6
+ function isEmbedParams(context) {
7
+ return "value" in context && !("prompt" in context);
8
+ }
9
+ function hasContextProperty(context) {
10
+ return "context" in context;
11
+ }
12
+ function extractTextContent(context) {
13
+ if (isEmbedParams(context)) {
14
+ const embedContext = context;
15
+ return {
16
+ prompt: String(embedContext.value || ""),
17
+ messages: [],
18
+ system: ""
19
+ };
20
+ }
21
+ const textContext = context;
22
+ return {
23
+ prompt: textContext.prompt || "",
24
+ messages: textContext.messages || [],
25
+ system: textContext.system || ""
26
+ };
27
+ }
28
+ function extractMetadata(context) {
29
+ const contextWithMetadata = context;
30
+ return {
31
+ model: contextWithMetadata.model,
32
+ temperature: contextWithMetadata.temperature,
33
+ maxTokens: contextWithMetadata.maxTokens
34
+ };
35
+ }
36
+ var lengthLimit = (maxLength) => createInputGuardrail(
37
+ "length-limit",
38
+ "Enforces maximum input length limit",
39
+ (context) => {
40
+ const { prompt, messages, system } = extractTextContent(context);
41
+ const { model, temperature, maxTokens } = extractMetadata(context);
42
+ const totalLength = prompt.length + messages.reduce(
43
+ (sum, msg) => sum + String(msg?.content || "").length,
44
+ 0
45
+ ) + system.length;
46
+ return {
47
+ tripwireTriggered: totalLength > maxLength,
48
+ message: `Input length ${totalLength} exceeds limit of ${maxLength}`,
49
+ severity: "medium",
50
+ metadata: {
51
+ totalLength,
52
+ maxLength,
53
+ model: model ? String(model) : void 0,
54
+ temperature,
55
+ maxTokens,
56
+ messageCount: messages.length
57
+ }
58
+ };
59
+ }
60
+ );
61
+ var blockedWords = (words) => createInputGuardrail(
62
+ "blocked-words",
63
+ "Blocks input containing specified words",
64
+ (context) => {
65
+ const { prompt, messages, system } = extractTextContent(context);
66
+ const allText = [
67
+ prompt,
68
+ ...messages.map((msg) => String(msg?.content || "")),
69
+ system
70
+ ].join(" ").toLowerCase();
71
+ const blockedWord = words.find(
72
+ (word) => allText.includes(word.toLowerCase())
73
+ );
74
+ return {
75
+ tripwireTriggered: !!blockedWord,
76
+ message: blockedWord ? `Blocked word detected: ${blockedWord}` : void 0,
77
+ severity: "high",
78
+ metadata: {
79
+ blockedWord,
80
+ allWords: words
81
+ }
82
+ };
83
+ }
84
+ );
85
+ var contentLengthLimit = (maxLength) => createInputGuardrail(
86
+ "content-length-limit",
87
+ "Enforces maximum content length limit",
88
+ (context) => {
89
+ const { prompt, messages, system } = extractTextContent(context);
90
+ const totalLength = prompt.length + messages.reduce(
91
+ (sum, msg) => sum + String(msg?.content || "").length,
92
+ 0
93
+ ) + system.length;
94
+ return {
95
+ tripwireTriggered: totalLength > maxLength,
96
+ message: `Content length ${totalLength} exceeds limit of ${maxLength}`,
97
+ severity: "medium",
98
+ metadata: {
99
+ totalLength,
100
+ maxLength
101
+ }
102
+ };
103
+ }
104
+ );
105
+ var blockedKeywords = (keywords) => createInputGuardrail(
106
+ "blocked-keywords",
107
+ "Blocks input containing specified keywords",
108
+ (context) => {
109
+ const { prompt, messages, system } = extractTextContent(context);
110
+ const allText = [
111
+ prompt,
112
+ ...messages.map((msg) => String(msg?.content || "")),
113
+ system
114
+ ].join(" ").toLowerCase();
115
+ const blockedWord = keywords.find(
116
+ (word) => allText.includes(word.toLowerCase())
117
+ );
118
+ return {
119
+ tripwireTriggered: !!blockedWord,
120
+ message: blockedWord ? `Blocked keyword detected: ${blockedWord}` : void 0,
121
+ severity: "high",
122
+ metadata: {
123
+ blockedWord,
124
+ allKeywords: keywords,
125
+ textLength: allText.length
126
+ }
127
+ };
128
+ }
129
+ );
130
+ var rateLimiting = (maxRequestsPerMinute) => {
131
+ const requestCounts = /* @__PURE__ */ new Map();
132
+ return createInputGuardrail(
133
+ "rate-limiting",
134
+ "Enforces rate limiting per minute",
135
+ (inputContext) => {
136
+ const { prompt } = extractTextContent(inputContext);
137
+ const { model, temperature, maxTokens } = extractMetadata(inputContext);
138
+ let contextData;
139
+ if (hasContextProperty(inputContext)) {
140
+ contextData = inputContext.context;
141
+ }
142
+ const key = contextData?.user?.id || contextData?.request?.ip || "default";
143
+ const now = Date.now();
144
+ const windowMs = 6e4;
145
+ const current = requestCounts.get(key) || {
146
+ count: 0,
147
+ resetTime: now + windowMs
148
+ };
149
+ if (now > current.resetTime) {
150
+ current.count = 0;
151
+ current.resetTime = now + windowMs;
152
+ }
153
+ current.count++;
154
+ requestCounts.set(key, current);
155
+ return {
156
+ tripwireTriggered: current.count > maxRequestsPerMinute,
157
+ message: `Rate limit exceeded: ${current.count}/${maxRequestsPerMinute} requests per minute`,
158
+ severity: "medium",
159
+ metadata: {
160
+ currentCount: current.count,
161
+ maxRequests: maxRequestsPerMinute,
162
+ resetTime: current.resetTime,
163
+ userId: contextData?.user?.id,
164
+ userIp: contextData?.request?.ip,
165
+ model: model ? String(model) : void 0,
166
+ temperature,
167
+ maxTokens,
168
+ promptLength: prompt.length
169
+ }
170
+ };
171
+ }
172
+ );
173
+ };
174
+ var profanityFilter = (customWords = []) => {
175
+ const defaultProfanity = ["profanity1", "profanity2"];
176
+ const allWords = [...defaultProfanity, ...customWords];
177
+ return createInputGuardrail(
178
+ "profanity-filter",
179
+ "Filters profanity and inappropriate language",
180
+ (context) => {
181
+ const { prompt, messages, system } = extractTextContent(context);
182
+ const allText = [
183
+ prompt,
184
+ ...messages.map((msg) => String(msg?.content || "")),
185
+ system
186
+ ].join(" ").toLowerCase();
187
+ const profaneWord = allWords.find(
188
+ (word) => allText.includes(word.toLowerCase())
189
+ );
190
+ return {
191
+ tripwireTriggered: !!profaneWord,
192
+ message: profaneWord ? `Profanity detected: ${profaneWord}` : void 0,
193
+ severity: "high",
194
+ metadata: {
195
+ profaneWord,
196
+ allWords,
197
+ textLength: allText.length
198
+ }
199
+ };
200
+ }
201
+ );
202
+ };
203
+ var customValidation = (name, description, validator, message) => createInputGuardrail(name, description, (context) => {
204
+ const { prompt, messages, system } = extractTextContent(context);
205
+ const { model, temperature, maxTokens } = extractMetadata(context);
206
+ const input = { prompt, messages, system, model, temperature, maxTokens };
207
+ const blocked = validator(input);
208
+ return {
209
+ tripwireTriggered: blocked,
210
+ message: blocked ? message : void 0,
211
+ severity: "medium",
212
+ metadata: {
213
+ validatorName: name,
214
+ inputKeys: Object.keys(input),
215
+ model: model ? String(model) : void 0,
216
+ temperature,
217
+ maxTokens
218
+ }
219
+ };
220
+ });
221
+ var promptInjectionDetector = () => createInputGuardrail(
222
+ "prompt-injection-detector",
223
+ "Detects potential prompt injection attempts",
224
+ (context) => {
225
+ const { prompt, messages, system } = extractTextContent(context);
226
+ const allText = [
227
+ prompt,
228
+ ...messages.map((msg) => String(msg?.content || "")),
229
+ system
230
+ ].join(" ");
231
+ const injectionPatterns = [
232
+ /ignore\s+previous\s+instructions/i,
233
+ /system\s*:\s*you\s+are\s+now/i,
234
+ /forget\s+everything\s+above/i,
235
+ /\bDAN\b.*mode/i,
236
+ /jailbreak/i,
237
+ /act\s+as\s+if\s+you\s+are/i,
238
+ /pretend\s+to\s+be/i,
239
+ /role\s*:\s*system/i
240
+ ];
241
+ const detectedPatterns = injectionPatterns.filter(
242
+ (pattern) => pattern.test(allText)
243
+ );
244
+ return {
245
+ tripwireTriggered: detectedPatterns.length > 0,
246
+ message: detectedPatterns.length > 0 ? `Potential prompt injection detected: ${detectedPatterns.length} suspicious patterns found` : void 0,
247
+ severity: "critical",
248
+ metadata: {
249
+ patternsDetected: detectedPatterns.length,
250
+ textLength: allText.length,
251
+ suspiciousPatterns: detectedPatterns.map((p) => p.source)
252
+ },
253
+ suggestion: "Please rephrase your request without system instructions or role-playing elements"
254
+ };
255
+ }
256
+ );
257
+ var piiDetector = () => createInputGuardrail(
258
+ "pii-detector",
259
+ "Detects personally identifiable information in input",
260
+ (context) => {
261
+ const { prompt, messages, system } = extractTextContent(context);
262
+ const allText = [
263
+ prompt,
264
+ ...messages.map((msg) => String(msg?.content || "")),
265
+ system
266
+ ].join(" ");
267
+ const piiPatterns = {
268
+ email: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,
269
+ phone: /\b(?:\+?1[-.\s]?)?\(?([0-9]{3})\)?[-.\s]?([0-9]{3})[-.\s]?([0-9]{4})\b/g,
270
+ ssn: /\b\d{3}-\d{2}-\d{4}\b/g,
271
+ creditCard: /\b(?:\d{4}[\s-]?){3}\d{4}\b/g,
272
+ ipAddress: /\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/g
273
+ };
274
+ const detectedPII = [];
275
+ const matches = [];
276
+ for (const [type, pattern] of Object.entries(piiPatterns)) {
277
+ const found = allText.match(pattern);
278
+ if (found) {
279
+ detectedPII.push(type);
280
+ matches.push(...found);
281
+ }
282
+ }
283
+ return {
284
+ tripwireTriggered: detectedPII.length > 0,
285
+ message: detectedPII.length > 0 ? `PII detected: ${detectedPII.join(", ")}` : void 0,
286
+ severity: "critical",
287
+ metadata: {
288
+ piiTypes: detectedPII,
289
+ matchCount: matches.length,
290
+ textLength: allText.length
291
+ },
292
+ suggestion: "Please remove any personal information (emails, phone numbers, SSNs, etc.) from your input"
293
+ };
294
+ }
295
+ );
296
+ var toxicityDetector = (threshold = 0.7) => createInputGuardrail(
297
+ "toxicity-detector",
298
+ "Detects toxic and harmful content in input",
299
+ (context) => {
300
+ const { prompt, messages, system } = extractTextContent(context);
301
+ const allText = [
302
+ prompt,
303
+ ...messages.map((msg) => String(msg?.content || "")),
304
+ system
305
+ ].join(" ").toLowerCase();
306
+ const toxicWords = [
307
+ "hate",
308
+ "kill",
309
+ "die",
310
+ "stupid",
311
+ "idiot",
312
+ "moron",
313
+ "toxic",
314
+ "harmful"
315
+ ];
316
+ const detectedWords = toxicWords.filter((word) => allText.includes(word));
317
+ const toxicityScore = detectedWords.length * 0.3;
318
+ return {
319
+ tripwireTriggered: toxicityScore > threshold,
320
+ message: toxicityScore > threshold ? `Toxic content detected (score: ${toxicityScore})` : void 0,
321
+ severity: toxicityScore > 0.8 ? "critical" : "high",
322
+ metadata: {
323
+ toxicityScore,
324
+ threshold,
325
+ detectedWords,
326
+ textLength: allText.length
327
+ },
328
+ suggestion: "Please use respectful and constructive language"
329
+ };
330
+ }
331
+ );
332
+ var mathHomeworkDetector = () => createInputGuardrail(
333
+ "math-homework-detector",
334
+ "Detects potential math homework requests",
335
+ (context) => {
336
+ const { prompt, messages, system } = extractTextContent(context);
337
+ const allText = [
338
+ prompt,
339
+ ...messages.map((msg) => String(msg?.content || "")),
340
+ system
341
+ ].join(" ");
342
+ const mathKeywords = [
343
+ "solve",
344
+ "calculate",
345
+ "equation",
346
+ "homework",
347
+ "assignment",
348
+ "problem set"
349
+ ];
350
+ const mathPatterns = [
351
+ /\b\d+\s*[+\-*/]\s*\d+/g,
352
+ /\b[xy]\s*[+\-*/=]\s*\d+/g,
353
+ /\b(derivative|integral|limit|theorem|proof)/gi,
354
+ /find\s+the\s+(value|solution|answer)/i
355
+ ];
356
+ const keywordMatches = mathKeywords.filter(
357
+ (keyword) => allText.toLowerCase().includes(keyword)
358
+ );
359
+ const patternMatches = mathPatterns.filter(
360
+ (pattern) => pattern.test(allText)
361
+ );
362
+ const isMathHomework = keywordMatches.length >= 2 || patternMatches.length > 0;
363
+ return {
364
+ tripwireTriggered: isMathHomework,
365
+ message: isMathHomework ? "Math homework request detected" : void 0,
366
+ severity: "high",
367
+ metadata: {
368
+ keywordMatches,
369
+ patternMatches: patternMatches.length,
370
+ textLength: allText.length,
371
+ confidence: isMathHomework ? 0.85 : 0.15
372
+ },
373
+ suggestion: "Try asking about learning concepts instead of solving specific problems"
374
+ };
375
+ }
376
+ );
377
+ var codeGenerationLimiter = (allowedLanguages = []) => createInputGuardrail(
378
+ "code-generation-limiter",
379
+ "Limits code generation to specified languages",
380
+ (context) => {
381
+ const { prompt, messages, system } = extractTextContent(context);
382
+ const allText = [
383
+ prompt,
384
+ ...messages.map((msg) => String(msg?.content || "")),
385
+ system
386
+ ].join(" ").toLowerCase();
387
+ const codeKeywords = [
388
+ "write code",
389
+ "generate code",
390
+ "create function",
391
+ "implement",
392
+ "script"
393
+ ];
394
+ const languagePatterns = {
395
+ javascript: /\b(javascript|js|node|react|angular|vue)\b/gi,
396
+ python: /\b(python|py|django|flask|pandas)\b/gi,
397
+ java: /\b(java|spring|hibernate)\b/gi,
398
+ cpp: /\b(c\+\+|cpp|c plus plus)\b/gi,
399
+ csharp: /\b(c#|csharp|dotnet|asp\.net)\b/gi,
400
+ php: /\b(php|laravel|symfony)\b/gi,
401
+ ruby: /\b(ruby|rails|gem)\b/gi,
402
+ go: /\b(golang|go)\b/gi,
403
+ rust: /\b(rust|cargo)\b/gi,
404
+ sql: /\b(sql|mysql|postgresql|oracle)\b/gi
405
+ };
406
+ const hasCodeRequest = codeKeywords.some(
407
+ (keyword) => allText.includes(keyword)
408
+ );
409
+ const detectedLanguages = [];
410
+ for (const [lang, pattern] of Object.entries(languagePatterns)) {
411
+ if (pattern.test(allText)) {
412
+ detectedLanguages.push(lang);
413
+ }
414
+ }
415
+ const hasRestrictedLanguage = hasCodeRequest && detectedLanguages.length > 0 && !detectedLanguages.some((lang) => allowedLanguages.includes(lang));
416
+ return {
417
+ tripwireTriggered: hasRestrictedLanguage,
418
+ message: hasRestrictedLanguage ? `Code generation requested for restricted language(s): ${detectedLanguages.join(", ")}` : void 0,
419
+ severity: "medium",
420
+ metadata: {
421
+ hasCodeRequest,
422
+ detectedLanguages,
423
+ allowedLanguages,
424
+ textLength: allText.length
425
+ },
426
+ suggestion: allowedLanguages.length > 0 ? `Please request code only in allowed languages: ${allowedLanguages.join(", ")}` : "Code generation is not allowed"
427
+ };
428
+ }
429
+ );
430
+ export {
431
+ blockedKeywords,
432
+ blockedWords,
433
+ codeGenerationLimiter,
434
+ contentLengthLimit,
435
+ customValidation,
436
+ extractMetadata,
437
+ extractTextContent,
438
+ lengthLimit,
439
+ mathHomeworkDetector,
440
+ piiDetector,
441
+ profanityFilter,
442
+ promptInjectionDetector,
443
+ rateLimiting,
444
+ toxicityDetector
445
+ };