qwed-open-responses 0.1.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/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # QWED Open Responses (Node.js)
2
+
3
+ [![npm version](https://badge.fury.io/js/qwed-open-responses.svg)](https://badge.fury.io/js/qwed-open-responses)
4
+ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
5
+
6
+ **Verification guards for AI agent outputs in Node.js/Express applications.**
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install qwed-open-responses
12
+ ```
13
+
14
+ ## Quick Start
15
+
16
+ ```typescript
17
+ import express from 'express';
18
+ import { createQWEDMiddleware, ToolGuard, SafetyGuard } from 'qwed-open-responses';
19
+
20
+ const app = express();
21
+ app.use(express.json());
22
+
23
+ // Add verification middleware
24
+ app.use(createQWEDMiddleware({
25
+ guards: [new ToolGuard(), new SafetyGuard()],
26
+ blockOnFailure: true,
27
+ }));
28
+
29
+ app.post('/api/agent', (req, res) => {
30
+ // Response will be verified before sending
31
+ res.json({
32
+ tool_calls: [
33
+ { name: 'search', arguments: { query: 'weather' } }
34
+ ]
35
+ });
36
+ });
37
+ ```
38
+
39
+ ## Guards
40
+
41
+ ### ToolGuard
42
+
43
+ Blocks dangerous tool calls.
44
+
45
+ ```typescript
46
+ const guard = new ToolGuard({
47
+ blockedTools: ['execute_shell', 'delete_file'],
48
+ allowedTools: ['search', 'calculator'], // Whitelist mode
49
+ });
50
+ ```
51
+
52
+ ### SafetyGuard
53
+
54
+ Detects PII and prompt injection.
55
+
56
+ ```typescript
57
+ const guard = new SafetyGuard({
58
+ checkPii: true,
59
+ checkInjection: true,
60
+ });
61
+ ```
62
+
63
+ ### SchemaGuard
64
+
65
+ Validates JSON structure.
66
+
67
+ ```typescript
68
+ const guard = new SchemaGuard({
69
+ type: 'object',
70
+ required: ['name', 'age'],
71
+ });
72
+ ```
73
+
74
+ ### MathGuard
75
+
76
+ Verifies calculations.
77
+
78
+ ```typescript
79
+ const guard = new MathGuard({ tolerance: 0.01 });
80
+ ```
81
+
82
+ ## Middleware Options
83
+
84
+ ```typescript
85
+ createQWEDMiddleware({
86
+ guards: [], // Guards to apply
87
+ blockOnFailure: true, // Block failed responses
88
+ verbose: false, // Log verification results
89
+ skipPaths: ['/health'], // Paths to skip
90
+ onError: (result, req, res) => {
91
+ // Custom error handler
92
+ },
93
+ });
94
+ ```
95
+
96
+ ## Verify Request Bodies
97
+
98
+ ```typescript
99
+ import { verifyRequestBody, ToolGuard } from 'qwed-open-responses';
100
+
101
+ app.post('/api/execute',
102
+ verifyRequestBody({ guards: [new ToolGuard()] }),
103
+ (req, res) => {
104
+ // Request body is verified
105
+ }
106
+ );
107
+ ```
108
+
109
+ ## Direct Verification
110
+
111
+ ```typescript
112
+ import { ResponseVerifier, ToolGuard } from 'qwed-open-responses';
113
+
114
+ const verifier = new ResponseVerifier([new ToolGuard()]);
115
+
116
+ const result = verifier.verify({
117
+ tool_calls: [{ name: 'search', arguments: {} }]
118
+ });
119
+
120
+ if (result.verified) {
121
+ console.log('✅ Safe to execute');
122
+ } else {
123
+ console.log('❌ Blocked:', result.blockReason);
124
+ }
125
+ ```
126
+
127
+ ## Links
128
+
129
+ - **GitHub:** [QWED-AI/qwed-open-responses](https://github.com/QWED-AI/qwed-open-responses)
130
+ - **PyPI (Python):** [qwed-open-responses](https://pypi.org/project/qwed-open-responses/)
131
+ - **Docs:** [docs.qwedai.com](https://docs.qwedai.com/docs/open-responses/overview)
132
+
133
+ ## License
134
+
135
+ Apache 2.0
@@ -0,0 +1,73 @@
1
+ /**
2
+ * QWED Open Responses - Guards
3
+ */
4
+ import { GuardResult, ParsedResponse } from './types';
5
+ /**
6
+ * Base class for all guards.
7
+ */
8
+ export declare abstract class BaseGuard {
9
+ abstract name: string;
10
+ abstract description: string;
11
+ abstract check(response: ParsedResponse, context?: Record<string, any>): GuardResult;
12
+ protected passResult(message?: string, details?: Record<string, any>): GuardResult;
13
+ protected failResult(message: string, details?: Record<string, any>, severity?: 'error' | 'warning'): GuardResult;
14
+ }
15
+ /**
16
+ * Tool Guard - Blocks dangerous tool calls.
17
+ */
18
+ export declare class ToolGuard extends BaseGuard {
19
+ name: string;
20
+ description: string;
21
+ private blockedTools;
22
+ private allowedTools;
23
+ private dangerousPatterns;
24
+ private static DEFAULT_BLOCKED_TOOLS;
25
+ private static DEFAULT_DANGEROUS_PATTERNS;
26
+ constructor(options?: {
27
+ blockedTools?: string[];
28
+ allowedTools?: string[];
29
+ useDefaultBlocklist?: boolean;
30
+ dangerousPatterns?: RegExp[];
31
+ });
32
+ check(response: ParsedResponse, context?: Record<string, any>): GuardResult;
33
+ private extractToolCalls;
34
+ }
35
+ /**
36
+ * Schema Guard - Validates JSON schema.
37
+ */
38
+ export declare class SchemaGuard extends BaseGuard {
39
+ name: string;
40
+ description: string;
41
+ private schema;
42
+ constructor(schema: Record<string, any>);
43
+ check(response: ParsedResponse, context?: Record<string, any>): GuardResult;
44
+ }
45
+ /**
46
+ * Safety Guard - Comprehensive safety checks.
47
+ */
48
+ export declare class SafetyGuard extends BaseGuard {
49
+ name: string;
50
+ description: string;
51
+ private checkPii;
52
+ private checkInjection;
53
+ private static PII_PATTERNS;
54
+ private static INJECTION_PATTERNS;
55
+ constructor(options?: {
56
+ checkPii?: boolean;
57
+ checkInjection?: boolean;
58
+ });
59
+ check(response: ParsedResponse, context?: Record<string, any>): GuardResult;
60
+ private extractContent;
61
+ }
62
+ /**
63
+ * Math Guard - Verifies calculations.
64
+ */
65
+ export declare class MathGuard extends BaseGuard {
66
+ name: string;
67
+ description: string;
68
+ private tolerance;
69
+ constructor(options?: {
70
+ tolerance?: number;
71
+ });
72
+ check(response: ParsedResponse, context?: Record<string, any>): GuardResult;
73
+ }
package/dist/guards.js ADDED
@@ -0,0 +1,228 @@
1
+ "use strict";
2
+ /**
3
+ * QWED Open Responses - Guards
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MathGuard = exports.SafetyGuard = exports.SchemaGuard = exports.ToolGuard = exports.BaseGuard = void 0;
7
+ /**
8
+ * Base class for all guards.
9
+ */
10
+ class BaseGuard {
11
+ passResult(message, details) {
12
+ return {
13
+ guardName: this.name,
14
+ passed: true,
15
+ message: message || `${this.name} passed`,
16
+ details,
17
+ severity: 'info',
18
+ };
19
+ }
20
+ failResult(message, details, severity = 'error') {
21
+ return {
22
+ guardName: this.name,
23
+ passed: false,
24
+ message,
25
+ details,
26
+ severity,
27
+ };
28
+ }
29
+ }
30
+ exports.BaseGuard = BaseGuard;
31
+ /**
32
+ * Tool Guard - Blocks dangerous tool calls.
33
+ */
34
+ class ToolGuard extends BaseGuard {
35
+ constructor(options = {}) {
36
+ super();
37
+ this.name = 'ToolGuard';
38
+ this.description = 'Validates tool calls for safety';
39
+ const { blockedTools = [], allowedTools, useDefaultBlocklist = true, dangerousPatterns = [], } = options;
40
+ this.blockedTools = new Set(blockedTools);
41
+ if (useDefaultBlocklist) {
42
+ ToolGuard.DEFAULT_BLOCKED_TOOLS.forEach(t => this.blockedTools.add(t));
43
+ }
44
+ this.allowedTools = allowedTools ? new Set(allowedTools) : null;
45
+ this.dangerousPatterns = [
46
+ ...ToolGuard.DEFAULT_DANGEROUS_PATTERNS,
47
+ ...dangerousPatterns,
48
+ ];
49
+ }
50
+ check(response, context) {
51
+ const toolCalls = this.extractToolCalls(response);
52
+ if (toolCalls.length === 0) {
53
+ return this.passResult('No tool calls to verify');
54
+ }
55
+ for (const call of toolCalls) {
56
+ const toolName = call.toolName || call.tool_name || call.name || 'unknown';
57
+ const args = call.arguments || {};
58
+ // Check blocked list
59
+ if (this.blockedTools.has(toolName)) {
60
+ return this.failResult(`BLOCKED: Tool '${toolName}' is not allowed`, { blockedTool: toolName });
61
+ }
62
+ // Check allowed list (whitelist mode)
63
+ if (this.allowedTools && !this.allowedTools.has(toolName)) {
64
+ return this.failResult(`BLOCKED: Tool '${toolName}' is not in allowed list`, {
65
+ tool: toolName,
66
+ allowed: Array.from(this.allowedTools),
67
+ });
68
+ }
69
+ // Check dangerous patterns
70
+ const argsStr = JSON.stringify(args);
71
+ for (const pattern of this.dangerousPatterns) {
72
+ if (pattern.test(argsStr)) {
73
+ return this.failResult('BLOCKED: Dangerous pattern detected in tool arguments', {
74
+ tool: toolName,
75
+ pattern: pattern.source,
76
+ });
77
+ }
78
+ }
79
+ }
80
+ return this.passResult(`All ${toolCalls.length} tool call(s) verified`);
81
+ }
82
+ extractToolCalls(response) {
83
+ const calls = [];
84
+ if (response.type === 'tool_call') {
85
+ calls.push(response);
86
+ }
87
+ if (response.toolCalls || response.tool_calls) {
88
+ calls.push(...(response.toolCalls || response.tool_calls || []));
89
+ }
90
+ return calls;
91
+ }
92
+ }
93
+ exports.ToolGuard = ToolGuard;
94
+ ToolGuard.DEFAULT_BLOCKED_TOOLS = new Set([
95
+ 'execute_shell', 'shell', 'bash', 'cmd', 'exec', 'eval',
96
+ 'delete_file', 'remove_file', 'write_file', 'modify_file',
97
+ 'send_email', 'transfer_money', 'make_payment',
98
+ ]);
99
+ ToolGuard.DEFAULT_DANGEROUS_PATTERNS = [
100
+ /DROP\s+TABLE/i,
101
+ /DELETE\s+FROM/i,
102
+ /TRUNCATE\s+TABLE/i,
103
+ /rm\s+-rf/i,
104
+ /rmdir\s+\/s/i,
105
+ /eval\s*\(/i,
106
+ /exec\s*\(/i,
107
+ /__import__/i,
108
+ ];
109
+ /**
110
+ * Schema Guard - Validates JSON schema.
111
+ */
112
+ class SchemaGuard extends BaseGuard {
113
+ constructor(schema) {
114
+ super();
115
+ this.name = 'SchemaGuard';
116
+ this.description = 'Validates response against JSON Schema';
117
+ this.schema = schema;
118
+ }
119
+ check(response, context) {
120
+ const data = response.output || response;
121
+ // Basic type checking (full JSON Schema validation would need ajv)
122
+ if (this.schema.type === 'object' && typeof data !== 'object') {
123
+ return this.failResult('Expected object type');
124
+ }
125
+ if (this.schema.required) {
126
+ const missing = this.schema.required.filter((field) => !(field in data));
127
+ if (missing.length > 0) {
128
+ return this.failResult(`Missing required fields: ${missing.join(', ')}`, { missing });
129
+ }
130
+ }
131
+ return this.passResult('Schema validation passed');
132
+ }
133
+ }
134
+ exports.SchemaGuard = SchemaGuard;
135
+ /**
136
+ * Safety Guard - Comprehensive safety checks.
137
+ */
138
+ class SafetyGuard extends BaseGuard {
139
+ constructor(options = {}) {
140
+ super();
141
+ this.name = 'SafetyGuard';
142
+ this.description = 'Comprehensive safety checks';
143
+ this.checkPii = options.checkPii ?? true;
144
+ this.checkInjection = options.checkInjection ?? true;
145
+ }
146
+ check(response, context) {
147
+ const content = this.extractContent(response);
148
+ const issues = [];
149
+ if (this.checkPii) {
150
+ for (const [type, pattern] of Object.entries(SafetyGuard.PII_PATTERNS)) {
151
+ if (pattern.test(content)) {
152
+ issues.push(`PII detected: ${type}`);
153
+ }
154
+ }
155
+ }
156
+ if (this.checkInjection) {
157
+ for (const pattern of SafetyGuard.INJECTION_PATTERNS) {
158
+ if (pattern.test(content)) {
159
+ return this.failResult('BLOCKED: Prompt injection detected', { pattern: pattern.source });
160
+ }
161
+ }
162
+ }
163
+ if (issues.length > 0) {
164
+ return this.failResult(`Safety issues detected: ${issues.join(', ')}`, { issues }, 'warning');
165
+ }
166
+ return this.passResult('All safety checks passed');
167
+ }
168
+ extractContent(response) {
169
+ const parts = [];
170
+ if (typeof response.content === 'string')
171
+ parts.push(response.content);
172
+ if (typeof response.output === 'string')
173
+ parts.push(response.output);
174
+ if (typeof response.text === 'string')
175
+ parts.push(response.text);
176
+ if (typeof response.output === 'object')
177
+ parts.push(JSON.stringify(response.output));
178
+ if (response.arguments)
179
+ parts.push(JSON.stringify(response.arguments));
180
+ return parts.join(' ');
181
+ }
182
+ }
183
+ exports.SafetyGuard = SafetyGuard;
184
+ SafetyGuard.PII_PATTERNS = {
185
+ email: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/,
186
+ phone: /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/,
187
+ ssn: /\b\d{3}-\d{2}-\d{4}\b/,
188
+ creditCard: /\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/,
189
+ };
190
+ SafetyGuard.INJECTION_PATTERNS = [
191
+ /ignore\s+(previous|all|above)\s+(instructions?|prompts?)/i,
192
+ /disregard\s+(previous|all|above)/i,
193
+ /forget\s+(everything|all|your\s+instructions)/i,
194
+ /you\s+are\s+now\s+/i,
195
+ /pretend\s+(you|to\s+be)/i,
196
+ ];
197
+ /**
198
+ * Math Guard - Verifies calculations.
199
+ */
200
+ class MathGuard extends BaseGuard {
201
+ constructor(options = {}) {
202
+ super();
203
+ this.name = 'MathGuard';
204
+ this.description = 'Verifies mathematical calculations';
205
+ this.tolerance = options.tolerance ?? 0.01;
206
+ }
207
+ check(response, context) {
208
+ const data = response.output || response;
209
+ if (typeof data !== 'object') {
210
+ return this.passResult('No calculations to verify');
211
+ }
212
+ // Check common total patterns
213
+ if ('total' in data && 'subtotal' in data) {
214
+ const subtotal = Number(data.subtotal) || 0;
215
+ const tax = Number(data.tax) || 0;
216
+ const shipping = Number(data.shipping) || 0;
217
+ const discount = Number(data.discount) || 0;
218
+ const total = Number(data.total);
219
+ const expected = subtotal + tax + shipping - discount;
220
+ if (Math.abs(expected - total) > this.tolerance) {
221
+ return this.failResult(`Total mismatch: expected ${expected}, got ${total}`, { expected, actual: total });
222
+ }
223
+ }
224
+ return this.passResult('Math verification passed');
225
+ }
226
+ }
227
+ exports.MathGuard = MathGuard;
228
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3VhcmRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2d1YXJkcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7O0dBRUc7OztBQUlIOztHQUVHO0FBQ0gsTUFBc0IsU0FBUztJQU1qQixVQUFVLENBQUMsT0FBZ0IsRUFBRSxPQUE2QjtRQUNoRSxPQUFPO1lBQ0gsU0FBUyxFQUFFLElBQUksQ0FBQyxJQUFJO1lBQ3BCLE1BQU0sRUFBRSxJQUFJO1lBQ1osT0FBTyxFQUFFLE9BQU8sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLFNBQVM7WUFDekMsT0FBTztZQUNQLFFBQVEsRUFBRSxNQUFNO1NBQ25CLENBQUM7SUFDTixDQUFDO0lBRVMsVUFBVSxDQUFDLE9BQWUsRUFBRSxPQUE2QixFQUFFLFdBQWdDLE9BQU87UUFDeEcsT0FBTztZQUNILFNBQVMsRUFBRSxJQUFJLENBQUMsSUFBSTtZQUNwQixNQUFNLEVBQUUsS0FBSztZQUNiLE9BQU87WUFDUCxPQUFPO1lBQ1AsUUFBUTtTQUNYLENBQUM7SUFDTixDQUFDO0NBQ0o7QUF6QkQsOEJBeUJDO0FBRUQ7O0dBRUc7QUFDSCxNQUFhLFNBQVUsU0FBUSxTQUFTO0lBeUJwQyxZQUFZLFVBS1IsRUFBRTtRQUNGLEtBQUssRUFBRSxDQUFDO1FBOUJaLFNBQUksR0FBRyxXQUFXLENBQUM7UUFDbkIsZ0JBQVcsR0FBRyxpQ0FBaUMsQ0FBQztRQStCNUMsTUFBTSxFQUNGLFlBQVksR0FBRyxFQUFFLEVBQ2pCLFlBQVksRUFDWixtQkFBbUIsR0FBRyxJQUFJLEVBQzFCLGlCQUFpQixHQUFHLEVBQUUsR0FDekIsR0FBRyxPQUFPLENBQUM7UUFFWixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQzFDLElBQUksbUJBQW1CLEVBQUUsQ0FBQztZQUN0QixTQUFTLENBQUMscUJBQXFCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzRSxDQUFDO1FBRUQsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDaEUsSUFBSSxDQUFDLGlCQUFpQixHQUFHO1lBQ3JCLEdBQUcsU0FBUyxDQUFDLDBCQUEwQjtZQUN2QyxHQUFHLGlCQUFpQjtTQUN2QixDQUFDO0lBQ04sQ0FBQztJQUVELEtBQUssQ0FBQyxRQUF3QixFQUFFLE9BQTZCO1FBQ3pELE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUVsRCxJQUFJLFNBQVMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDekIsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLHlCQUF5QixDQUFDLENBQUM7UUFDdEQsQ0FBQztRQUVELEtBQUssTUFBTSxJQUFJLElBQUksU0FBUyxFQUFFLENBQUM7WUFDM0IsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsU0FBUyxJQUFJLElBQUksQ0FBQyxJQUFJLElBQUksU0FBUyxDQUFDO1lBQzNFLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxTQUFTLElBQUksRUFBRSxDQUFDO1lBRWxDLHFCQUFxQjtZQUNyQixJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7Z0JBQ2xDLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxrQkFBa0IsUUFBUSxrQkFBa0IsRUFBRSxFQUFFLFdBQVcsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO1lBQ3BHLENBQUM7WUFFRCxzQ0FBc0M7WUFDdEMsSUFBSSxJQUFJLENBQUMsWUFBWSxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztnQkFDeEQsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLGtCQUFrQixRQUFRLDBCQUEwQixFQUFFO29CQUN6RSxJQUFJLEVBQUUsUUFBUTtvQkFDZCxPQUFPLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDO2lCQUN6QyxDQUFDLENBQUM7WUFDUCxDQUFDO1lBRUQsMkJBQTJCO1lBQzNCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDckMsS0FBSyxNQUFNLE9BQU8sSUFBSSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztnQkFDM0MsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7b0JBQ3hCLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyx1REFBdUQsRUFBRTt3QkFDNUUsSUFBSSxFQUFFLFFBQVE7d0JBQ2QsT0FBTyxFQUFFLE9BQU8sQ0FBQyxNQUFNO3FCQUMxQixDQUFDLENBQUM7Z0JBQ1AsQ0FBQztZQUNMLENBQUM7UUFDTCxDQUFDO1FBRUQsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sU0FBUyxDQUFDLE1BQU0sd0JBQXdCLENBQUMsQ0FBQztJQUM1RSxDQUFDO0lBRU8sZ0JBQWdCLENBQUMsUUFBd0I7UUFDN0MsTUFBTSxLQUFLLEdBQVUsRUFBRSxDQUFDO1FBRXhCLElBQUksUUFBUSxDQUFDLElBQUksS0FBSyxXQUFXLEVBQUUsQ0FBQztZQUNoQyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3pCLENBQUM7UUFFRCxJQUFJLFFBQVEsQ0FBQyxTQUFTLElBQUksUUFBUSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQzVDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxTQUFTLElBQUksUUFBUSxDQUFDLFVBQVUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3JFLENBQUM7UUFFRCxPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDOztBQXZHTCw4QkF3R0M7QUFoR2tCLCtCQUFxQixHQUFHLElBQUksR0FBRyxDQUFDO0lBQzNDLGVBQWUsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTTtJQUN2RCxhQUFhLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBRSxhQUFhO0lBQ3pELFlBQVksRUFBRSxnQkFBZ0IsRUFBRSxjQUFjO0NBQ2pELENBQUMsQUFKa0MsQ0FJakM7QUFFWSxvQ0FBMEIsR0FBRztJQUN4QyxlQUFlO0lBQ2YsZ0JBQWdCO0lBQ2hCLG1CQUFtQjtJQUNuQixXQUFXO0lBQ1gsY0FBYztJQUNkLFlBQVk7SUFDWixZQUFZO0lBQ1osYUFBYTtDQUNoQixBQVR3QyxDQVN2QztBQW1GTjs7R0FFRztBQUNILE1BQWEsV0FBWSxTQUFRLFNBQVM7SUFNdEMsWUFBWSxNQUEyQjtRQUNuQyxLQUFLLEVBQUUsQ0FBQztRQU5aLFNBQUksR0FBRyxhQUFhLENBQUM7UUFDckIsZ0JBQVcsR0FBRyx3Q0FBd0MsQ0FBQztRQU1uRCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztJQUN6QixDQUFDO0lBRUQsS0FBSyxDQUFDLFFBQXdCLEVBQUUsT0FBNkI7UUFDekQsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLE1BQU0sSUFBSSxRQUFRLENBQUM7UUFFekMsbUVBQW1FO1FBQ25FLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEtBQUssUUFBUSxJQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQzVELE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBQ25ELENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDdkIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBYSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDakYsSUFBSSxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUNyQixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsNEJBQTRCLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFDMUYsQ0FBQztRQUNMLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsMEJBQTBCLENBQUMsQ0FBQztJQUN2RCxDQUFDO0NBQ0o7QUE1QkQsa0NBNEJDO0FBRUQ7O0dBRUc7QUFDSCxNQUFhLFdBQVksU0FBUSxTQUFTO0lBc0J0QyxZQUFZLFVBQTRELEVBQUU7UUFDdEUsS0FBSyxFQUFFLENBQUM7UUF0QlosU0FBSSxHQUFHLGFBQWEsQ0FBQztRQUNyQixnQkFBVyxHQUFHLDZCQUE2QixDQUFDO1FBc0J4QyxJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDO1FBQ3pDLElBQUksQ0FBQyxjQUFjLEdBQUcsT0FBTyxDQUFDLGNBQWMsSUFBSSxJQUFJLENBQUM7SUFDekQsQ0FBQztJQUVELEtBQUssQ0FBQyxRQUF3QixFQUFFLE9BQTZCO1FBQ3pELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDOUMsTUFBTSxNQUFNLEdBQWEsRUFBRSxDQUFDO1FBRTVCLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2hCLEtBQUssTUFBTSxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO2dCQUNyRSxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztvQkFDeEIsTUFBTSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsSUFBSSxFQUFFLENBQUMsQ0FBQztnQkFDekMsQ0FBQztZQUNMLENBQUM7UUFDTCxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDdEIsS0FBSyxNQUFNLE9BQU8sSUFBSSxXQUFXLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztnQkFDbkQsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7b0JBQ3hCLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxvQ0FBb0MsRUFBRSxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztnQkFDOUYsQ0FBQztZQUNMLENBQUM7UUFDTCxDQUFDO1FBRUQsSUFBSSxNQUFNLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3BCLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQywyQkFBMkIsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUUsTUFBTSxFQUFFLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDbEcsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO0lBQ3ZELENBQUM7SUFFTyxjQUFjLENBQUMsUUFBd0I7UUFDM0MsTUFBTSxLQUFLLEdBQWEsRUFBRSxDQUFDO1FBRTNCLElBQUksT0FBTyxRQUFRLENBQUMsT0FBTyxLQUFLLFFBQVE7WUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN2RSxJQUFJLE9BQU8sUUFBUSxDQUFDLE1BQU0sS0FBSyxRQUFRO1lBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDckUsSUFBSSxPQUFPLFFBQVEsQ0FBQyxJQUFJLEtBQUssUUFBUTtZQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRWpFLElBQUksT0FBTyxRQUFRLENBQUMsTUFBTSxLQUFLLFFBQVE7WUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDckYsSUFBSSxRQUFRLENBQUMsU0FBUztZQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztRQUV2RSxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDM0IsQ0FBQzs7QUFsRUwsa0NBbUVDO0FBNURrQix3QkFBWSxHQUFHO0lBQzFCLEtBQUssRUFBRSxnREFBZ0Q7SUFDdkQsS0FBSyxFQUFFLCtCQUErQjtJQUN0QyxHQUFHLEVBQUUsdUJBQXVCO0lBQzVCLFVBQVUsRUFBRSw0Q0FBNEM7Q0FDM0QsQUFMMEIsQ0FLekI7QUFFYSw4QkFBa0IsR0FBRztJQUNoQywyREFBMkQ7SUFDM0QsbUNBQW1DO0lBQ25DLGdEQUFnRDtJQUNoRCxxQkFBcUI7SUFDckIsMEJBQTBCO0NBQzdCLEFBTmdDLENBTS9CO0FBaUROOztHQUVHO0FBQ0gsTUFBYSxTQUFVLFNBQVEsU0FBUztJQU1wQyxZQUFZLFVBQWtDLEVBQUU7UUFDNUMsS0FBSyxFQUFFLENBQUM7UUFOWixTQUFJLEdBQUcsV0FBVyxDQUFDO1FBQ25CLGdCQUFXLEdBQUcsb0NBQW9DLENBQUM7UUFNL0MsSUFBSSxDQUFDLFNBQVMsR0FBRyxPQUFPLENBQUMsU0FBUyxJQUFJLElBQUksQ0FBQztJQUMvQyxDQUFDO0lBRUQsS0FBSyxDQUFDLFFBQXdCLEVBQUUsT0FBNkI7UUFDekQsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLE1BQU0sSUFBSSxRQUFRLENBQUM7UUFFekMsSUFBSSxPQUFPLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUMzQixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsMkJBQTJCLENBQUMsQ0FBQztRQUN4RCxDQUFDO1FBRUQsOEJBQThCO1FBQzlCLElBQUksT0FBTyxJQUFJLElBQUksSUFBSSxVQUFVLElBQUksSUFBSSxFQUFFLENBQUM7WUFDeEMsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDNUMsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbEMsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDNUMsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDNUMsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUVqQyxNQUFNLFFBQVEsR0FBRyxRQUFRLEdBQUcsR0FBRyxHQUFHLFFBQVEsR0FBRyxRQUFRLENBQUM7WUFFdEQsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQzlDLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FDbEIsNEJBQTRCLFFBQVEsU0FBUyxLQUFLLEVBQUUsRUFDcEQsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUM5QixDQUFDO1lBQ04sQ0FBQztRQUNMLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsMEJBQTBCLENBQUMsQ0FBQztJQUN2RCxDQUFDO0NBQ0o7QUF0Q0QsOEJBc0NDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBRV0VEIE9wZW4gUmVzcG9uc2VzIC0gR3VhcmRzXG4gKi9cblxuaW1wb3J0IHsgR3VhcmRSZXN1bHQsIFBhcnNlZFJlc3BvbnNlIH0gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogQmFzZSBjbGFzcyBmb3IgYWxsIGd1YXJkcy5cbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VHdWFyZCB7XG4gICAgYWJzdHJhY3QgbmFtZTogc3RyaW5nO1xuICAgIGFic3RyYWN0IGRlc2NyaXB0aW9uOiBzdHJpbmc7XG5cbiAgICBhYnN0cmFjdCBjaGVjayhyZXNwb25zZTogUGFyc2VkUmVzcG9uc2UsIGNvbnRleHQ/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogR3VhcmRSZXN1bHQ7XG5cbiAgICBwcm90ZWN0ZWQgcGFzc1Jlc3VsdChtZXNzYWdlPzogc3RyaW5nLCBkZXRhaWxzPzogUmVjb3JkPHN0cmluZywgYW55Pik6IEd1YXJkUmVzdWx0IHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGd1YXJkTmFtZTogdGhpcy5uYW1lLFxuICAgICAgICAgICAgcGFzc2VkOiB0cnVlLFxuICAgICAgICAgICAgbWVzc2FnZTogbWVzc2FnZSB8fCBgJHt0aGlzLm5hbWV9IHBhc3NlZGAsXG4gICAgICAgICAgICBkZXRhaWxzLFxuICAgICAgICAgICAgc2V2ZXJpdHk6ICdpbmZvJyxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgZmFpbFJlc3VsdChtZXNzYWdlOiBzdHJpbmcsIGRldGFpbHM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBzZXZlcml0eTogJ2Vycm9yJyB8ICd3YXJuaW5nJyA9ICdlcnJvcicpOiBHdWFyZFJlc3VsdCB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBndWFyZE5hbWU6IHRoaXMubmFtZSxcbiAgICAgICAgICAgIHBhc3NlZDogZmFsc2UsXG4gICAgICAgICAgICBtZXNzYWdlLFxuICAgICAgICAgICAgZGV0YWlscyxcbiAgICAgICAgICAgIHNldmVyaXR5LFxuICAgICAgICB9O1xuICAgIH1cbn1cblxuLyoqXG4gKiBUb29sIEd1YXJkIC0gQmxvY2tzIGRhbmdlcm91cyB0b29sIGNhbGxzLlxuICovXG5leHBvcnQgY2xhc3MgVG9vbEd1YXJkIGV4dGVuZHMgQmFzZUd1YXJkIHtcbiAgICBuYW1lID0gJ1Rvb2xHdWFyZCc7XG4gICAgZGVzY3JpcHRpb24gPSAnVmFsaWRhdGVzIHRvb2wgY2FsbHMgZm9yIHNhZmV0eSc7XG5cbiAgICBwcml2YXRlIGJsb2NrZWRUb29sczogU2V0PHN0cmluZz47XG4gICAgcHJpdmF0ZSBhbGxvd2VkVG9vbHM6IFNldDxzdHJpbmc+IHwgbnVsbDtcbiAgICBwcml2YXRlIGRhbmdlcm91c1BhdHRlcm5zOiBSZWdFeHBbXTtcblxuICAgIHByaXZhdGUgc3RhdGljIERFRkFVTFRfQkxPQ0tFRF9UT09MUyA9IG5ldyBTZXQoW1xuICAgICAgICAnZXhlY3V0ZV9zaGVsbCcsICdzaGVsbCcsICdiYXNoJywgJ2NtZCcsICdleGVjJywgJ2V2YWwnLFxuICAgICAgICAnZGVsZXRlX2ZpbGUnLCAncmVtb3ZlX2ZpbGUnLCAnd3JpdGVfZmlsZScsICdtb2RpZnlfZmlsZScsXG4gICAgICAgICdzZW5kX2VtYWlsJywgJ3RyYW5zZmVyX21vbmV5JywgJ21ha2VfcGF5bWVudCcsXG4gICAgXSk7XG5cbiAgICBwcml2YXRlIHN0YXRpYyBERUZBVUxUX0RBTkdFUk9VU19QQVRURVJOUyA9IFtcbiAgICAgICAgL0RST1BcXHMrVEFCTEUvaSxcbiAgICAgICAgL0RFTEVURVxccytGUk9NL2ksXG4gICAgICAgIC9UUlVOQ0FURVxccytUQUJMRS9pLFxuICAgICAgICAvcm1cXHMrLXJmL2ksXG4gICAgICAgIC9ybWRpclxccytcXC9zL2ksXG4gICAgICAgIC9ldmFsXFxzKlxcKC9pLFxuICAgICAgICAvZXhlY1xccypcXCgvaSxcbiAgICAgICAgL19faW1wb3J0X18vaSxcbiAgICBdO1xuXG4gICAgY29uc3RydWN0b3Iob3B0aW9uczoge1xuICAgICAgICBibG9ja2VkVG9vbHM/OiBzdHJpbmdbXTtcbiAgICAgICAgYWxsb3dlZFRvb2xzPzogc3RyaW5nW107XG4gICAgICAgIHVzZURlZmF1bHRCbG9ja2xpc3Q/OiBib29sZWFuO1xuICAgICAgICBkYW5nZXJvdXNQYXR0ZXJucz86IFJlZ0V4cFtdO1xuICAgIH0gPSB7fSkge1xuICAgICAgICBzdXBlcigpO1xuXG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAgIGJsb2NrZWRUb29scyA9IFtdLFxuICAgICAgICAgICAgYWxsb3dlZFRvb2xzLFxuICAgICAgICAgICAgdXNlRGVmYXVsdEJsb2NrbGlzdCA9IHRydWUsXG4gICAgICAgICAgICBkYW5nZXJvdXNQYXR0ZXJucyA9IFtdLFxuICAgICAgICB9ID0gb3B0aW9ucztcblxuICAgICAgICB0aGlzLmJsb2NrZWRUb29scyA9IG5ldyBTZXQoYmxvY2tlZFRvb2xzKTtcbiAgICAgICAgaWYgKHVzZURlZmF1bHRCbG9ja2xpc3QpIHtcbiAgICAgICAgICAgIFRvb2xHdWFyZC5ERUZBVUxUX0JMT0NLRURfVE9PTFMuZm9yRWFjaCh0ID0+IHRoaXMuYmxvY2tlZFRvb2xzLmFkZCh0KSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmFsbG93ZWRUb29scyA9IGFsbG93ZWRUb29scyA/IG5ldyBTZXQoYWxsb3dlZFRvb2xzKSA6IG51bGw7XG4gICAgICAgIHRoaXMuZGFuZ2Vyb3VzUGF0dGVybnMgPSBbXG4gICAgICAgICAgICAuLi5Ub29sR3VhcmQuREVGQVVMVF9EQU5HRVJPVVNfUEFUVEVSTlMsXG4gICAgICAgICAgICAuLi5kYW5nZXJvdXNQYXR0ZXJucyxcbiAgICAgICAgXTtcbiAgICB9XG5cbiAgICBjaGVjayhyZXNwb25zZTogUGFyc2VkUmVzcG9uc2UsIGNvbnRleHQ/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogR3VhcmRSZXN1bHQge1xuICAgICAgICBjb25zdCB0b29sQ2FsbHMgPSB0aGlzLmV4dHJhY3RUb29sQ2FsbHMocmVzcG9uc2UpO1xuXG4gICAgICAgIGlmICh0b29sQ2FsbHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wYXNzUmVzdWx0KCdObyB0b29sIGNhbGxzIHRvIHZlcmlmeScpO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChjb25zdCBjYWxsIG9mIHRvb2xDYWxscykge1xuICAgICAgICAgICAgY29uc3QgdG9vbE5hbWUgPSBjYWxsLnRvb2xOYW1lIHx8IGNhbGwudG9vbF9uYW1lIHx8IGNhbGwubmFtZSB8fCAndW5rbm93bic7XG4gICAgICAgICAgICBjb25zdCBhcmdzID0gY2FsbC5hcmd1bWVudHMgfHwge307XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGJsb2NrZWQgbGlzdFxuICAgICAgICAgICAgaWYgKHRoaXMuYmxvY2tlZFRvb2xzLmhhcyh0b29sTmFtZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5mYWlsUmVzdWx0KGBCTE9DS0VEOiBUb29sICcke3Rvb2xOYW1lfScgaXMgbm90IGFsbG93ZWRgLCB7IGJsb2NrZWRUb29sOiB0b29sTmFtZSB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ2hlY2sgYWxsb3dlZCBsaXN0ICh3aGl0ZWxpc3QgbW9kZSlcbiAgICAgICAgICAgIGlmICh0aGlzLmFsbG93ZWRUb29scyAmJiAhdGhpcy5hbGxvd2VkVG9vbHMuaGFzKHRvb2xOYW1lKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmZhaWxSZXN1bHQoYEJMT0NLRUQ6IFRvb2wgJyR7dG9vbE5hbWV9JyBpcyBub3QgaW4gYWxsb3dlZCBsaXN0YCwge1xuICAgICAgICAgICAgICAgICAgICB0b29sOiB0b29sTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgYWxsb3dlZDogQXJyYXkuZnJvbSh0aGlzLmFsbG93ZWRUb29scyksXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGRhbmdlcm91cyBwYXR0ZXJuc1xuICAgICAgICAgICAgY29uc3QgYXJnc1N0ciA9IEpTT04uc3RyaW5naWZ5KGFyZ3MpO1xuICAgICAgICAgICAgZm9yIChjb25zdCBwYXR0ZXJuIG9mIHRoaXMuZGFuZ2Vyb3VzUGF0dGVybnMpIHtcbiAgICAgICAgICAgICAgICBpZiAocGF0dGVybi50ZXN0KGFyZ3NTdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmZhaWxSZXN1bHQoJ0JMT0NLRUQ6IERhbmdlcm91cyBwYXR0ZXJuIGRldGVjdGVkIGluIHRvb2wgYXJndW1lbnRzJywge1xuICAgICAgICAgICAgICAgICAgICAgICAgdG9vbDogdG9vbE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuOiBwYXR0ZXJuLnNvdXJjZSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMucGFzc1Jlc3VsdChgQWxsICR7dG9vbENhbGxzLmxlbmd0aH0gdG9vbCBjYWxsKHMpIHZlcmlmaWVkYCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBleHRyYWN0VG9vbENhbGxzKHJlc3BvbnNlOiBQYXJzZWRSZXNwb25zZSk6IGFueVtdIHtcbiAgICAgICAgY29uc3QgY2FsbHM6IGFueVtdID0gW107XG5cbiAgICAgICAgaWYgKHJlc3BvbnNlLnR5cGUgPT09ICd0b29sX2NhbGwnKSB7XG4gICAgICAgICAgICBjYWxscy5wdXNoKHJlc3BvbnNlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyZXNwb25zZS50b29sQ2FsbHMgfHwgcmVzcG9uc2UudG9vbF9jYWxscykge1xuICAgICAgICAgICAgY2FsbHMucHVzaCguLi4ocmVzcG9uc2UudG9vbENhbGxzIHx8IHJlc3BvbnNlLnRvb2xfY2FsbHMgfHwgW10pKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjYWxscztcbiAgICB9XG59XG5cbi8qKlxuICogU2NoZW1hIEd1YXJkIC0gVmFsaWRhdGVzIEpTT04gc2NoZW1hLlxuICovXG5leHBvcnQgY2xhc3MgU2NoZW1hR3VhcmQgZXh0ZW5kcyBCYXNlR3VhcmQge1xuICAgIG5hbWUgPSAnU2NoZW1hR3VhcmQnO1xuICAgIGRlc2NyaXB0aW9uID0gJ1ZhbGlkYXRlcyByZXNwb25zZSBhZ2FpbnN0IEpTT04gU2NoZW1hJztcblxuICAgIHByaXZhdGUgc2NoZW1hOiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuXG4gICAgY29uc3RydWN0b3Ioc2NoZW1hOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMuc2NoZW1hID0gc2NoZW1hO1xuICAgIH1cblxuICAgIGNoZWNrKHJlc3BvbnNlOiBQYXJzZWRSZXNwb25zZSwgY29udGV4dD86IFJlY29yZDxzdHJpbmcsIGFueT4pOiBHdWFyZFJlc3VsdCB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSByZXNwb25zZS5vdXRwdXQgfHwgcmVzcG9uc2U7XG5cbiAgICAgICAgLy8gQmFzaWMgdHlwZSBjaGVja2luZyAoZnVsbCBKU09OIFNjaGVtYSB2YWxpZGF0aW9uIHdvdWxkIG5lZWQgYWp2KVxuICAgICAgICBpZiAodGhpcy5zY2hlbWEudHlwZSA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIGRhdGEgIT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5mYWlsUmVzdWx0KCdFeHBlY3RlZCBvYmplY3QgdHlwZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuc2NoZW1hLnJlcXVpcmVkKSB7XG4gICAgICAgICAgICBjb25zdCBtaXNzaW5nID0gdGhpcy5zY2hlbWEucmVxdWlyZWQuZmlsdGVyKChmaWVsZDogc3RyaW5nKSA9PiAhKGZpZWxkIGluIGRhdGEpKTtcbiAgICAgICAgICAgIGlmIChtaXNzaW5nLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5mYWlsUmVzdWx0KGBNaXNzaW5nIHJlcXVpcmVkIGZpZWxkczogJHttaXNzaW5nLmpvaW4oJywgJyl9YCwgeyBtaXNzaW5nIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMucGFzc1Jlc3VsdCgnU2NoZW1hIHZhbGlkYXRpb24gcGFzc2VkJyk7XG4gICAgfVxufVxuXG4vKipcbiAqIFNhZmV0eSBHdWFyZCAtIENvbXByZWhlbnNpdmUgc2FmZXR5IGNoZWNrcy5cbiAqL1xuZXhwb3J0IGNsYXNzIFNhZmV0eUd1YXJkIGV4dGVuZHMgQmFzZUd1YXJkIHtcbiAgICBuYW1lID0gJ1NhZmV0eUd1YXJkJztcbiAgICBkZXNjcmlwdGlvbiA9ICdDb21wcmVoZW5zaXZlIHNhZmV0eSBjaGVja3MnO1xuXG4gICAgcHJpdmF0ZSBjaGVja1BpaTogYm9vbGVhbjtcbiAgICBwcml2YXRlIGNoZWNrSW5qZWN0aW9uOiBib29sZWFuO1xuXG4gICAgcHJpdmF0ZSBzdGF0aWMgUElJX1BBVFRFUk5TID0ge1xuICAgICAgICBlbWFpbDogL1thLXpBLVowLTkuXyUrLV0rQFthLXpBLVowLTkuLV0rXFwuW2EtekEtWl17Mix9LyxcbiAgICAgICAgcGhvbmU6IC9cXGJcXGR7M31bLS5dP1xcZHszfVstLl0/XFxkezR9XFxiLyxcbiAgICAgICAgc3NuOiAvXFxiXFxkezN9LVxcZHsyfS1cXGR7NH1cXGIvLFxuICAgICAgICBjcmVkaXRDYXJkOiAvXFxiXFxkezR9W1xccy1dP1xcZHs0fVtcXHMtXT9cXGR7NH1bXFxzLV0/XFxkezR9XFxiLyxcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBzdGF0aWMgSU5KRUNUSU9OX1BBVFRFUk5TID0gW1xuICAgICAgICAvaWdub3JlXFxzKyhwcmV2aW91c3xhbGx8YWJvdmUpXFxzKyhpbnN0cnVjdGlvbnM/fHByb21wdHM/KS9pLFxuICAgICAgICAvZGlzcmVnYXJkXFxzKyhwcmV2aW91c3xhbGx8YWJvdmUpL2ksXG4gICAgICAgIC9mb3JnZXRcXHMrKGV2ZXJ5dGhpbmd8YWxsfHlvdXJcXHMraW5zdHJ1Y3Rpb25zKS9pLFxuICAgICAgICAveW91XFxzK2FyZVxccytub3dcXHMrL2ksXG4gICAgICAgIC9wcmV0ZW5kXFxzKyh5b3V8dG9cXHMrYmUpL2ksXG4gICAgXTtcblxuICAgIGNvbnN0cnVjdG9yKG9wdGlvbnM6IHsgY2hlY2tQaWk/OiBib29sZWFuOyBjaGVja0luamVjdGlvbj86IGJvb2xlYW4gfSA9IHt9KSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMuY2hlY2tQaWkgPSBvcHRpb25zLmNoZWNrUGlpID8/IHRydWU7XG4gICAgICAgIHRoaXMuY2hlY2tJbmplY3Rpb24gPSBvcHRpb25zLmNoZWNrSW5qZWN0aW9uID8/IHRydWU7XG4gICAgfVxuXG4gICAgY2hlY2socmVzcG9uc2U6IFBhcnNlZFJlc3BvbnNlLCBjb250ZXh0PzogUmVjb3JkPHN0cmluZywgYW55Pik6IEd1YXJkUmVzdWx0IHtcbiAgICAgICAgY29uc3QgY29udGVudCA9IHRoaXMuZXh0cmFjdENvbnRlbnQocmVzcG9uc2UpO1xuICAgICAgICBjb25zdCBpc3N1ZXM6IHN0cmluZ1tdID0gW107XG5cbiAgICAgICAgaWYgKHRoaXMuY2hlY2tQaWkpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgW3R5cGUsIHBhdHRlcm5dIG9mIE9iamVjdC5lbnRyaWVzKFNhZmV0eUd1YXJkLlBJSV9QQVRURVJOUykpIHtcbiAgICAgICAgICAgICAgICBpZiAocGF0dGVybi50ZXN0KGNvbnRlbnQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlzc3Vlcy5wdXNoKGBQSUkgZGV0ZWN0ZWQ6ICR7dHlwZX1gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5jaGVja0luamVjdGlvbikge1xuICAgICAgICAgICAgZm9yIChjb25zdCBwYXR0ZXJuIG9mIFNhZmV0eUd1YXJkLklOSkVDVElPTl9QQVRURVJOUykge1xuICAgICAgICAgICAgICAgIGlmIChwYXR0ZXJuLnRlc3QoY29udGVudCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmFpbFJlc3VsdCgnQkxPQ0tFRDogUHJvbXB0IGluamVjdGlvbiBkZXRlY3RlZCcsIHsgcGF0dGVybjogcGF0dGVybi5zb3VyY2UgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzc3Vlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5mYWlsUmVzdWx0KGBTYWZldHkgaXNzdWVzIGRldGVjdGVkOiAke2lzc3Vlcy5qb2luKCcsICcpfWAsIHsgaXNzdWVzIH0sICd3YXJuaW5nJyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5wYXNzUmVzdWx0KCdBbGwgc2FmZXR5IGNoZWNrcyBwYXNzZWQnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGV4dHJhY3RDb250ZW50KHJlc3BvbnNlOiBQYXJzZWRSZXNwb25zZSk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IHBhcnRzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgICAgIGlmICh0eXBlb2YgcmVzcG9uc2UuY29udGVudCA9PT0gJ3N0cmluZycpIHBhcnRzLnB1c2gocmVzcG9uc2UuY29udGVudCk7XG4gICAgICAgIGlmICh0eXBlb2YgcmVzcG9uc2Uub3V0cHV0ID09PSAnc3RyaW5nJykgcGFydHMucHVzaChyZXNwb25zZS5vdXRwdXQpO1xuICAgICAgICBpZiAodHlwZW9mIHJlc3BvbnNlLnRleHQgPT09ICdzdHJpbmcnKSBwYXJ0cy5wdXNoKHJlc3BvbnNlLnRleHQpO1xuXG4gICAgICAgIGlmICh0eXBlb2YgcmVzcG9uc2Uub3V0cHV0ID09PSAnb2JqZWN0JykgcGFydHMucHVzaChKU09OLnN0cmluZ2lmeShyZXNwb25zZS5vdXRwdXQpKTtcbiAgICAgICAgaWYgKHJlc3BvbnNlLmFyZ3VtZW50cykgcGFydHMucHVzaChKU09OLnN0cmluZ2lmeShyZXNwb25zZS5hcmd1bWVudHMpKTtcblxuICAgICAgICByZXR1cm4gcGFydHMuam9pbignICcpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBNYXRoIEd1YXJkIC0gVmVyaWZpZXMgY2FsY3VsYXRpb25zLlxuICovXG5leHBvcnQgY2xhc3MgTWF0aEd1YXJkIGV4dGVuZHMgQmFzZUd1YXJkIHtcbiAgICBuYW1lID0gJ01hdGhHdWFyZCc7XG4gICAgZGVzY3JpcHRpb24gPSAnVmVyaWZpZXMgbWF0aGVtYXRpY2FsIGNhbGN1bGF0aW9ucyc7XG5cbiAgICBwcml2YXRlIHRvbGVyYW5jZTogbnVtYmVyO1xuXG4gICAgY29uc3RydWN0b3Iob3B0aW9uczogeyB0b2xlcmFuY2U/OiBudW1iZXIgfSA9IHt9KSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMudG9sZXJhbmNlID0gb3B0aW9ucy50b2xlcmFuY2UgPz8gMC4wMTtcbiAgICB9XG5cbiAgICBjaGVjayhyZXNwb25zZTogUGFyc2VkUmVzcG9uc2UsIGNvbnRleHQ/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogR3VhcmRSZXN1bHQge1xuICAgICAgICBjb25zdCBkYXRhID0gcmVzcG9uc2Uub3V0cHV0IHx8IHJlc3BvbnNlO1xuXG4gICAgICAgIGlmICh0eXBlb2YgZGF0YSAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBhc3NSZXN1bHQoJ05vIGNhbGN1bGF0aW9ucyB0byB2ZXJpZnknKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENoZWNrIGNvbW1vbiB0b3RhbCBwYXR0ZXJuc1xuICAgICAgICBpZiAoJ3RvdGFsJyBpbiBkYXRhICYmICdzdWJ0b3RhbCcgaW4gZGF0YSkge1xuICAgICAgICAgICAgY29uc3Qgc3VidG90YWwgPSBOdW1iZXIoZGF0YS5zdWJ0b3RhbCkgfHwgMDtcbiAgICAgICAgICAgIGNvbnN0IHRheCA9IE51bWJlcihkYXRhLnRheCkgfHwgMDtcbiAgICAgICAgICAgIGNvbnN0IHNoaXBwaW5nID0gTnVtYmVyKGRhdGEuc2hpcHBpbmcpIHx8IDA7XG4gICAgICAgICAgICBjb25zdCBkaXNjb3VudCA9IE51bWJlcihkYXRhLmRpc2NvdW50KSB8fCAwO1xuICAgICAgICAgICAgY29uc3QgdG90YWwgPSBOdW1iZXIoZGF0YS50b3RhbCk7XG5cbiAgICAgICAgICAgIGNvbnN0IGV4cGVjdGVkID0gc3VidG90YWwgKyB0YXggKyBzaGlwcGluZyAtIGRpc2NvdW50O1xuXG4gICAgICAgICAgICBpZiAoTWF0aC5hYnMoZXhwZWN0ZWQgLSB0b3RhbCkgPiB0aGlzLnRvbGVyYW5jZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmZhaWxSZXN1bHQoXG4gICAgICAgICAgICAgICAgICAgIGBUb3RhbCBtaXNtYXRjaDogZXhwZWN0ZWQgJHtleHBlY3RlZH0sIGdvdCAke3RvdGFsfWAsXG4gICAgICAgICAgICAgICAgICAgIHsgZXhwZWN0ZWQsIGFjdHVhbDogdG90YWwgfVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5wYXNzUmVzdWx0KCdNYXRoIHZlcmlmaWNhdGlvbiBwYXNzZWQnKTtcbiAgICB9XG59XG4iXX0=
@@ -0,0 +1,58 @@
1
+ /**
2
+ * QWED Open Responses - Express Middleware
3
+ *
4
+ * Verification guards for AI agent outputs in Express.js applications.
5
+ */
6
+ import { Request, Response, RequestHandler } from 'express';
7
+ export * from './guards';
8
+ export * from './types';
9
+ export * from './verifier';
10
+ import { ResponseVerifier, VerificationResult } from './verifier';
11
+ import { BaseGuard, ToolGuard, SchemaGuard, SafetyGuard } from './guards';
12
+ export interface QWEDMiddlewareOptions {
13
+ /** Guards to apply to all requests */
14
+ guards?: BaseGuard[];
15
+ /** Block requests that fail verification */
16
+ blockOnFailure?: boolean;
17
+ /** Custom error handler */
18
+ onError?: (error: VerificationResult, req: Request, res: Response) => void;
19
+ /** Log verification results */
20
+ verbose?: boolean;
21
+ /** Paths to skip verification */
22
+ skipPaths?: string[];
23
+ }
24
+ /**
25
+ * Create QWED verification middleware for Express.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * import express from 'express';
30
+ * import { createQWEDMiddleware, ToolGuard, SafetyGuard } from 'qwed-open-responses';
31
+ *
32
+ * const app = express();
33
+ *
34
+ * app.use(createQWEDMiddleware({
35
+ * guards: [new ToolGuard(), new SafetyGuard()],
36
+ * blockOnFailure: true,
37
+ * }));
38
+ * ```
39
+ */
40
+ export declare function createQWEDMiddleware(options?: QWEDMiddlewareOptions): RequestHandler;
41
+ /**
42
+ * Middleware to verify incoming request bodies.
43
+ */
44
+ export declare function verifyRequestBody(options?: QWEDMiddlewareOptions): RequestHandler;
45
+ /**
46
+ * Middleware to verify tool calls in AI agent requests.
47
+ */
48
+ export declare function verifyToolCalls(options?: QWEDMiddlewareOptions): RequestHandler;
49
+ declare const _default: {
50
+ createQWEDMiddleware: typeof createQWEDMiddleware;
51
+ verifyRequestBody: typeof verifyRequestBody;
52
+ verifyToolCalls: typeof verifyToolCalls;
53
+ ResponseVerifier: typeof ResponseVerifier;
54
+ ToolGuard: typeof ToolGuard;
55
+ SchemaGuard: typeof SchemaGuard;
56
+ SafetyGuard: typeof SafetyGuard;
57
+ };
58
+ export default _default;
package/dist/index.js ADDED
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ /**
3
+ * QWED Open Responses - Express Middleware
4
+ *
5
+ * Verification guards for AI agent outputs in Express.js applications.
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
19
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.createQWEDMiddleware = createQWEDMiddleware;
23
+ exports.verifyRequestBody = verifyRequestBody;
24
+ exports.verifyToolCalls = verifyToolCalls;
25
+ // Re-export all guards and types
26
+ __exportStar(require("./guards"), exports);
27
+ __exportStar(require("./types"), exports);
28
+ __exportStar(require("./verifier"), exports);
29
+ const verifier_1 = require("./verifier");
30
+ const guards_1 = require("./guards");
31
+ /**
32
+ * Create QWED verification middleware for Express.
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * import express from 'express';
37
+ * import { createQWEDMiddleware, ToolGuard, SafetyGuard } from 'qwed-open-responses';
38
+ *
39
+ * const app = express();
40
+ *
41
+ * app.use(createQWEDMiddleware({
42
+ * guards: [new ToolGuard(), new SafetyGuard()],
43
+ * blockOnFailure: true,
44
+ * }));
45
+ * ```
46
+ */
47
+ function createQWEDMiddleware(options = {}) {
48
+ const { guards = [], blockOnFailure = true, onError, verbose = false, skipPaths = [], } = options;
49
+ const verifier = new verifier_1.ResponseVerifier(guards);
50
+ return (req, res, next) => {
51
+ // Skip certain paths
52
+ if (skipPaths.some(path => req.path.startsWith(path))) {
53
+ return next();
54
+ }
55
+ // Store original json method
56
+ const originalJson = res.json.bind(res);
57
+ // Override json to verify before sending
58
+ res.json = (body) => {
59
+ const result = verifier.verify(body);
60
+ if (verbose) {
61
+ console.log(`[QWED] ${req.method} ${req.path} -> ${result.verified ? 'PASS' : 'FAIL'}`);
62
+ }
63
+ // Attach verification result to response
64
+ res._qwedVerification = result;
65
+ if (!result.verified && blockOnFailure) {
66
+ if (onError) {
67
+ onError(result, req, res);
68
+ return res;
69
+ }
70
+ return originalJson({
71
+ error: 'Response verification failed',
72
+ code: 'QWED_VERIFICATION_FAILED',
73
+ details: result.guardResults.filter(g => !g.passed).map(g => ({
74
+ guard: g.guardName,
75
+ message: g.message,
76
+ })),
77
+ });
78
+ }
79
+ return originalJson(body);
80
+ };
81
+ next();
82
+ };
83
+ }
84
+ /**
85
+ * Middleware to verify incoming request bodies.
86
+ */
87
+ function verifyRequestBody(options = {}) {
88
+ const { guards = [], blockOnFailure = true, verbose = false, } = options;
89
+ const verifier = new verifier_1.ResponseVerifier(guards);
90
+ return (req, res, next) => {
91
+ if (!req.body) {
92
+ return next();
93
+ }
94
+ const result = verifier.verify(req.body);
95
+ if (verbose) {
96
+ console.log(`[QWED] Request body ${req.method} ${req.path} -> ${result.verified ? 'PASS' : 'FAIL'}`);
97
+ }
98
+ req._qwedVerification = result;
99
+ if (!result.verified && blockOnFailure) {
100
+ return res.status(422).json({
101
+ error: 'Request verification failed',
102
+ code: 'QWED_REQUEST_BLOCKED',
103
+ details: result.guardResults.filter(g => !g.passed).map(g => ({
104
+ guard: g.guardName,
105
+ message: g.message,
106
+ })),
107
+ });
108
+ }
109
+ next();
110
+ };
111
+ }
112
+ /**
113
+ * Middleware to verify tool calls in AI agent requests.
114
+ */
115
+ function verifyToolCalls(options = {}) {
116
+ const toolGuard = new guards_1.ToolGuard();
117
+ const guards = [toolGuard, ...(options.guards || [])];
118
+ return verifyRequestBody({ ...options, guards });
119
+ }
120
+ // Default export
121
+ exports.default = {
122
+ createQWEDMiddleware,
123
+ verifyRequestBody,
124
+ verifyToolCalls,
125
+ ResponseVerifier: verifier_1.ResponseVerifier,
126
+ ToolGuard: guards_1.ToolGuard,
127
+ SchemaGuard: guards_1.SchemaGuard,
128
+ SafetyGuard: guards_1.SafetyGuard,
129
+ };
130
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7O0dBSUc7Ozs7Ozs7Ozs7Ozs7Ozs7QUF5Q0gsb0RBb0RDO0FBS0QsOENBbUNDO0FBS0QsMENBS0M7QUEzSUQsaUNBQWlDO0FBQ2pDLDJDQUF5QjtBQUN6QiwwQ0FBd0I7QUFDeEIsNkNBQTJCO0FBRTNCLHlDQUFrRTtBQUNsRSxxQ0FBMEU7QUFlMUU7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBQ0gsU0FBZ0Isb0JBQW9CLENBQUMsVUFBaUMsRUFBRTtJQUNwRSxNQUFNLEVBQ0YsTUFBTSxHQUFHLEVBQUUsRUFDWCxjQUFjLEdBQUcsSUFBSSxFQUNyQixPQUFPLEVBQ1AsT0FBTyxHQUFHLEtBQUssRUFDZixTQUFTLEdBQUcsRUFBRSxHQUNqQixHQUFHLE9BQU8sQ0FBQztJQUVaLE1BQU0sUUFBUSxHQUFHLElBQUksMkJBQWdCLENBQUMsTUFBTSxDQUFDLENBQUM7SUFFOUMsT0FBTyxDQUFDLEdBQVksRUFBRSxHQUFhLEVBQUUsSUFBa0IsRUFBRSxFQUFFO1FBQ3ZELHFCQUFxQjtRQUNyQixJQUFJLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDcEQsT0FBTyxJQUFJLEVBQUUsQ0FBQztRQUNsQixDQUFDO1FBRUQsNkJBQTZCO1FBQzdCLE1BQU0sWUFBWSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRXhDLHlDQUF5QztRQUN6QyxHQUFHLENBQUMsSUFBSSxHQUFHLENBQUMsSUFBUyxFQUFFLEVBQUU7WUFDckIsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUVyQyxJQUFJLE9BQU8sRUFBRSxD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QUFDTixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixlQUFlLENBQUMsVUFBaUMsRUFBRTtJQUMvRCxNQUFNLFNBQVMsR0FBRyxJQUFJLGtCQUFTLEVBQUUsQ0FBQztJQUNsQyxNQUFNLE1BQU0sR0FBRyxDQUFDLFNBQVMsRUFBRSxHQUFHLENBQUMsT0FBTyxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBRXRELE9BQU8saUJBQWlCLENBQUMsRUFBRSxHQUFHLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO0FBQ3JELENBQUM7QUFFRCxpQkFBaUI7QUFDakIsa0JBQWU7SUFDWCxvQkFBb0I7SUFDcEIsaUJBQWlCO0lBQ2pCLGVBQWU7SUFDZixnQkFBZ0IsRUFBaEIsMkJBQWdCO0lBQ2hCLFNBQVMsRUFBVCxrQkFBUztJQUNULFdBQVcsRUFBWCxvQkFBVztJQUNYLFdBQVcsRUFBWCxvQkFBVztDQUNkLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFFXRUQgT3BlbiBSZXNwb25zZXMgLSBFeHByZXNzIE1pZGRsZXdhcmVcbiAqIFxuICogVmVyaWZpY2F0aW9uIGd1YXJkcyBmb3IgQUkgYWdlbnQgb3V0cHV0cyBpbiBFeHByZXNzLmpzIGFwcGxpY2F0aW9ucy5cbiAqL1xuXG5pbXBvcnQgeyBSZXF1ZXN0LCBSZXNwb25zZSwgTmV4dEZ1bmN0aW9uLCBSZXF1ZXN0SGFuZGxlciB9IGZyb20gJ2V4cHJlc3MnO1xuXG4vLyBSZS1leHBvcnQgYWxsIGd1YXJkcyBhbmQgdHlwZXNcbmV4cG9ydCAqIGZyb20gJy4vZ3VhcmRzJztcbmV4cG9ydCAqIGZyb20gJy4vdHlwZXMnO1xuZXhwb3J0ICogZnJvbSAnLi92ZXJpZmllcic7XG5cbmltcG9ydCB7IFJlc3BvbnNlVmVyaWZpZXIsIFZlcmlmaWNhdGlvblJlc3VsdCB9IGZyb20gJy4vdmVyaWZpZXInO1xuaW1wb3J0IHsgQmFzZUd1YXJkLCBUb29sR3VhcmQsIFNjaGVtYUd1YXJkLCBTYWZldHlHdWFyZCB9IGZyb20gJy4vZ3VhcmRzJztcblxuZXhwb3J0IGludGVyZmFjZSBRV0VETWlkZGxld2FyZU9wdGlvbnMge1xuICAgIC8qKiBHdWFyZHMgdG8gYXBwbHkgdG8gYWxsIHJlcXVlc3RzICovXG4gICAgZ3VhcmRzPzogQmFzZUd1YXJkW107XG4gICAgLyoqIEJsb2NrIHJlcXVlc3RzIHRoYXQgZmFpbCB2ZXJpZmljYXRpb24gKi9cbiAgICBibG9ja09uRmFpbHVyZT86IGJvb2xlYW47XG4gICAgLyoqIEN1c3RvbSBlcnJvciBoYW5kbGVyICovXG4gICAgb25FcnJvcj86IChlcnJvcjogVmVyaWZpY2F0aW9uUmVzdWx0LCByZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UpID0+IHZvaWQ7XG4gICAgLyoqIExvZyB2ZXJpZmljYXRpb24gcmVzdWx0cyAqL1xuICAgIHZlcmJvc2U/OiBib29sZWFuO1xuICAgIC8qKiBQYXRocyB0byBza2lwIHZlcmlmaWNhdGlvbiAqL1xuICAgIHNraXBQYXRocz86IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIENyZWF0ZSBRV0VEIHZlcmlmaWNhdGlvbiBtaWRkbGV3YXJlIGZvciBFeHByZXNzLlxuICogXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IGV4cHJlc3MgZnJvbSAnZXhwcmVzcyc7XG4gKiBpbXBvcnQgeyBjcmVhdGVRV0VETWlkZGxld2FyZSwgVG9vbEd1YXJkLCBTYWZldHlHdWFyZCB9IGZyb20gJ3F3ZWQtb3Blbi1yZXNwb25zZXMnO1xuICogXG4gKiBjb25zdCBhcHAgPSBleHByZXNzKCk7XG4gKiBcbiAqIGFwcC51c2UoY3JlYXRlUVdFRE1pZGRsZXdhcmUoe1xuICogICBndWFyZHM6IFtuZXcgVG9vbEd1YXJkKCksIG5ldyBTYWZldHlHdWFyZCgpXSxcbiAqICAgYmxvY2tPbkZhaWx1cmU6IHRydWUsXG4gKiB9KSk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVFXRURNaWRkbGV3YXJlKG9wdGlvbnM6IFFXRURNaWRkbGV3YXJlT3B0aW9ucyA9IHt9KTogUmVxdWVzdEhhbmRsZXIge1xuICAgIGNvbnN0IHtcbiAgICAgICAgZ3VhcmRzID0gW10sXG4gICAgICAgIGJsb2NrT25GYWlsdXJlID0gdHJ1ZSxcbiAgICAgICAgb25FcnJvcixcbiAgICAgICAgdmVyYm9zZSA9IGZhbHNlLFxuICAgICAgICBza2lwUGF0aHMgPSBbXSxcbiAgICB9ID0gb3B0aW9ucztcblxuICAgIGNvbnN0IHZlcmlmaWVyID0gbmV3IFJlc3BvbnNlVmVyaWZpZXIoZ3VhcmRzKTtcblxuICAgIHJldHVybiAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pID0+IHtcbiAgICAgICAgLy8gU2tpcCBjZXJ0YWluIHBhdGhzXG4gICAgICAgIGlmIChza2lwUGF0aHMuc29tZShwYXRoID0+IHJlcS5wYXRoLnN0YXJ0c1dpdGgocGF0aCkpKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV4dCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU3RvcmUgb3JpZ2luYWwganNvbiBtZXRob2RcbiAgICAgICAgY29uc3Qgb3JpZ2luYWxKc29uID0gcmVzLmpzb24uYmluZChyZXMpO1xuXG4gICAgICAgIC8vIE92ZXJyaWRlIGpzb24gdG8gdmVyaWZ5IGJlZm9yZSBzZW5kaW5nXG4gICAgICAgIHJlcy5qc29uID0gKGJvZHk6IGFueSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gdmVyaWZpZXIudmVyaWZ5KGJvZHkpO1xuXG4gICAgICAgICAgICBpZiAodmVyYm9zZSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGBbUVdFRF0gJHtyZXEubWV0aG9kfSAke3JlcS5wYXRofSAtPiAke3Jlc3VsdC52ZXJpZmllZCA/ICdQQVNTJyA6ICdGQUlMJ31gKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQXR0YWNoIHZlcmlmaWNhdGlvbiByZXN1bHQgdG8gcmVzcG9uc2VcbiAgICAgICAgICAgIChyZXMgYXMgYW55KS5fcXdlZFZlcmlmaWNhdGlvbiA9IHJlc3VsdDtcblxuICAgICAgICAgICAgaWYgKCFyZXN1bHQudmVyaWZpZWQgJiYgYmxvY2tPbkZhaWx1cmUpIHtcbiAgICAgICAgICAgICAgICBpZiAob25FcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBvbkVycm9yKHJlc3VsdCwgcmVxLCByZXMpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbEpzb24oe1xuICAgICAgICAgICAgICAgICAgICBlcnJvcjogJ1Jlc3BvbnNlIHZlcmlmaWNhdGlvbiBmYWlsZWQnLFxuICAgICAgICAgICAgICAgICAgICBjb2RlOiAnUVdFRF9WRVJJRklDQVRJT05fRkFJTEVEJyxcbiAgICAgICAgICAgICAgICAgICAgZGV0YWlsczogcmVzdWx0Lmd1YXJkUmVzdWx0cy5maWx0ZXIoZyA9PiAhZy5wYXNzZWQpLm1hcChnID0+ICh7XG4gICAgICAgICAgICAgICAgICAgICAgICBndWFyZDogZy5ndWFyZE5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBnLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIH0pKSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsSnNvbihib2R5KTtcbiAgICAgICAgfTtcblxuICAgICAgICBuZXh0KCk7XG4gICAgfTtcbn1cblxuLyoqXG4gKiBNaWRkbGV3YXJlIHRvIHZlcmlmeSBpbmNvbWluZyByZXF1ZXN0IGJvZGllcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZlcmlmeVJlcXVlc3RCb2R5KG9wdGlvbnM6IFFXRURNaWRkbGV3YXJlT3B0aW9ucyA9IHt9KTogUmVxdWVzdEhhbmRsZXIge1xuICAgIGNvbnN0IHtcbiAgICAgICAgZ3VhcmRzID0gW10sXG4gICAgICAgIGJsb2NrT25GYWlsdXJlID0gdHJ1ZSxcbiAgICAgICAgdmVyYm9zZSA9IGZhbHNlLFxuICAgIH0gPSBvcHRpb25zO1xuXG4gICAgY29uc3QgdmVyaWZpZXIgPSBuZXcgUmVzcG9uc2VWZXJpZmllcihndWFyZHMpO1xuXG4gICAgcmV0dXJuIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UsIG5leHQ6IE5leHRGdW5jdGlvbikgPT4ge1xuICAgICAgICBpZiAoIXJlcS5ib2R5KSB7XG4gICAgICAgICAgICByZXR1cm4gbmV4dCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gdmVyaWZpZXIudmVyaWZ5KHJlcS5ib2R5KTtcblxuICAgICAgICBpZiAodmVyYm9zZSkge1xuICAgICAgICAgICAgY29uc29sZS5sb2coYFtRV0VEXSBSZXF1ZXN0IGJvZHkgJHtyZXEubWV0aG9kfSAke3JlcS5wYXRofSAtPiAke3Jlc3VsdC52ZXJpZmllZCA/ICdQQVNTJyA6ICdGQUlMJ31gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIChyZXEgYXMgYW55KS5fcXdlZFZlcmlmaWNhdGlvbiA9IHJlc3VsdDtcblxuICAgICAgICBpZiAoIXJlc3VsdC52ZXJpZmllZCAmJiBibG9ja09uRmFpbHVyZSkge1xuICAgICAgICAgICAgcmV0dXJuIHJlcy5zdGF0dXMoNDIyKS5qc29uKHtcbiAgICAgICAgICAgICAgICBlcnJvcjogJ1JlcXVlc3QgdmVyaWZpY2F0aW9uIGZhaWxlZCcsXG4gICAgICAgICAgICAgICAgY29kZTogJ1FXRURfUkVRVUVTVF9CTE9DS0VEJyxcbiAgICAgICAgICAgICAgICBkZXRhaWxzOiByZXN1bHQuZ3VhcmRSZXN1bHRzLmZpbHRlcihnID0+ICFnLnBhc3NlZCkubWFwKGcgPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgZ3VhcmQ6IGcuZ3VhcmROYW1lLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBnLm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgfSkpLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBuZXh0KCk7XG4gICAgfTtcbn1cblxuLyoqXG4gKiBNaWRkbGV3YXJlIHRvIHZlcmlmeSB0b29sIGNhbGxzIGluIEFJIGFnZW50IHJlcXVlc3RzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmVyaWZ5VG9vbENhbGxzKG9wdGlvbnM6IFFXRURNaWRkbGV3YXJlT3B0aW9ucyA9IHt9KTogUmVxdWVzdEhhbmRsZXIge1xuICAgIGNvbnN0IHRvb2xHdWFyZCA9IG5ldyBUb29sR3VhcmQoKTtcbiAgICBjb25zdCBndWFyZHMgPSBbdG9vbEd1YXJkLCAuLi4ob3B0aW9ucy5ndWFyZHMgfHwgW10pXTtcblxuICAgIHJldHVybiB2ZXJpZnlSZXF1ZXN0Qm9keSh7IC4uLm9wdGlvbnMsIGd1YXJkcyB9KTtcbn1cblxuLy8gRGVmYXVsdCBleHBvcnRcbmV4cG9ydCBkZWZhdWx0IHtcbiAgICBjcmVhdGVRV0VETWlkZGxld2FyZSxcbiAgICB2ZXJpZnlSZXF1ZXN0Qm9keSxcbiAgICB2ZXJpZnlUb29sQ2FsbHMsXG4gICAgUmVzcG9uc2VWZXJpZmllcixcbiAgICBUb29sR3VhcmQsXG4gICAgU2NoZW1hR3VhcmQsXG4gICAgU2FmZXR5R3VhcmQsXG59O1xuIl19
@@ -0,0 +1,35 @@
1
+ /**
2
+ * QWED Open Responses - Types
3
+ */
4
+ export interface GuardResult {
5
+ guardName: string;
6
+ passed: boolean;
7
+ message?: string;
8
+ details?: Record<string, any>;
9
+ severity: 'error' | 'warning' | 'info';
10
+ }
11
+ export interface VerificationResult {
12
+ verified: boolean;
13
+ response: any;
14
+ guardsPassed: number;
15
+ guardsFailed: number;
16
+ guardResults: GuardResult[];
17
+ blocked: boolean;
18
+ blockReason?: string;
19
+ timestamp: string;
20
+ }
21
+ export interface ToolCall {
22
+ type?: string;
23
+ toolName?: string;
24
+ tool_name?: string;
25
+ name?: string;
26
+ arguments?: Record<string, any>;
27
+ }
28
+ export interface ParsedResponse {
29
+ type?: string;
30
+ content?: string;
31
+ output?: any;
32
+ toolCalls?: ToolCall[];
33
+ tool_calls?: ToolCall[];
34
+ [key: string]: any;
35
+ }
package/dist/types.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * QWED Open Responses - Types
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOztHQUVHIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBRV0VEIE9wZW4gUmVzcG9uc2VzIC0gVHlwZXNcbiAqL1xuXG5leHBvcnQgaW50ZXJmYWNlIEd1YXJkUmVzdWx0IHtcbiAgICBndWFyZE5hbWU6IHN0cmluZztcbiAgICBwYXNzZWQ6IGJvb2xlYW47XG4gICAgbWVzc2FnZT86IHN0cmluZztcbiAgICBkZXRhaWxzPzogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgICBzZXZlcml0eTogJ2Vycm9yJyB8ICd3YXJuaW5nJyB8ICdpbmZvJztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBWZXJpZmljYXRpb25SZXN1bHQge1xuICAgIHZlcmlmaWVkOiBib29sZWFuO1xuICAgIHJlc3BvbnNlOiBhbnk7XG4gICAgZ3VhcmRzUGFzc2VkOiBudW1iZXI7XG4gICAgZ3VhcmRzRmFpbGVkOiBudW1iZXI7XG4gICAgZ3VhcmRSZXN1bHRzOiBHdWFyZFJlc3VsdFtdO1xuICAgIGJsb2NrZWQ6IGJvb2xlYW47XG4gICAgYmxvY2tSZWFzb24/OiBzdHJpbmc7XG4gICAgdGltZXN0YW1wOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVG9vbENhbGwge1xuICAgIHR5cGU/OiBzdHJpbmc7XG4gICAgdG9vbE5hbWU/OiBzdHJpbmc7XG4gICAgdG9vbF9uYW1lPzogc3RyaW5nO1xuICAgIG5hbWU/OiBzdHJpbmc7XG4gICAgYXJndW1lbnRzPzogUmVjb3JkPHN0cmluZywgYW55Pjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQYXJzZWRSZXNwb25zZSB7XG4gICAgdHlwZT86IHN0cmluZztcbiAgICBjb250ZW50Pzogc3RyaW5nO1xuICAgIG91dHB1dD86IGFueTtcbiAgICB0b29sQ2FsbHM/OiBUb29sQ2FsbFtdO1xuICAgIHRvb2xfY2FsbHM/OiBUb29sQ2FsbFtdO1xuICAgIFtrZXk6IHN0cmluZ106IGFueTtcbn1cbiJdfQ==
@@ -0,0 +1,25 @@
1
+ /**
2
+ * QWED Open Responses - Response Verifier
3
+ */
4
+ import { BaseGuard } from './guards';
5
+ import { VerificationResult, GuardResult } from './types';
6
+ export { VerificationResult, GuardResult };
7
+ /**
8
+ * Main verifier for AI responses.
9
+ */
10
+ export declare class ResponseVerifier {
11
+ private defaultGuards;
12
+ private strictMode;
13
+ constructor(guards?: BaseGuard[], options?: {
14
+ strictMode?: boolean;
15
+ });
16
+ /**
17
+ * Verify a response against guards.
18
+ */
19
+ verify(response: any, guards?: BaseGuard[], context?: Record<string, any>): VerificationResult;
20
+ /**
21
+ * Verify a tool call.
22
+ */
23
+ verifyToolCall(toolName: string, args: Record<string, any>, guards?: BaseGuard[]): VerificationResult;
24
+ private parseResponse;
25
+ }
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ /**
3
+ * QWED Open Responses - Response Verifier
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ResponseVerifier = void 0;
7
+ /**
8
+ * Main verifier for AI responses.
9
+ */
10
+ class ResponseVerifier {
11
+ constructor(guards = [], options = {}) {
12
+ this.defaultGuards = guards;
13
+ this.strictMode = options.strictMode ?? true;
14
+ }
15
+ /**
16
+ * Verify a response against guards.
17
+ */
18
+ verify(response, guards, context) {
19
+ const guardsToUse = guards ?? this.defaultGuards;
20
+ const parsedResponse = this.parseResponse(response);
21
+ const guardResults = [];
22
+ let guardsPassed = 0;
23
+ let guardsFailed = 0;
24
+ let blocked = false;
25
+ let blockReason;
26
+ for (const guard of guardsToUse) {
27
+ try {
28
+ const result = guard.check(parsedResponse, context);
29
+ guardResults.push(result);
30
+ if (result.passed) {
31
+ guardsPassed++;
32
+ }
33
+ else {
34
+ guardsFailed++;
35
+ if (result.severity === 'error' && this.strictMode) {
36
+ blocked = true;
37
+ blockReason = result.message;
38
+ }
39
+ }
40
+ }
41
+ catch (error) {
42
+ guardResults.push({
43
+ guardName: guard.name,
44
+ passed: false,
45
+ message: `Guard error: ${error instanceof Error ? error.message : String(error)}`,
46
+ severity: 'error',
47
+ });
48
+ guardsFailed++;
49
+ }
50
+ }
51
+ return {
52
+ verified: guardsFailed === 0,
53
+ response: parsedResponse,
54
+ guardsPassed,
55
+ guardsFailed,
56
+ guardResults,
57
+ blocked,
58
+ blockReason,
59
+ timestamp: new Date().toISOString(),
60
+ };
61
+ }
62
+ /**
63
+ * Verify a tool call.
64
+ */
65
+ verifyToolCall(toolName, args, guards) {
66
+ const toolCall = {
67
+ type: 'tool_call',
68
+ toolName,
69
+ arguments: args,
70
+ };
71
+ return this.verify(toolCall, guards);
72
+ }
73
+ parseResponse(response) {
74
+ if (typeof response === 'object' && response !== null) {
75
+ return response;
76
+ }
77
+ if (typeof response === 'string') {
78
+ try {
79
+ return JSON.parse(response);
80
+ }
81
+ catch {
82
+ return { type: 'text', content: response };
83
+ }
84
+ }
85
+ return { type: 'unknown', raw: String(response) };
86
+ }
87
+ }
88
+ exports.ResponseVerifier = ResponseVerifier;
89
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyaWZpZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdmVyaWZpZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOztHQUVHOzs7QUFRSDs7R0FFRztBQUNILE1BQWEsZ0JBQWdCO0lBSXpCLFlBQVksU0FBc0IsRUFBRSxFQUFFLFVBQW9DLEVBQUU7UUFDeEUsSUFBSSxDQUFDLGFBQWEsR0FBRyxNQUFNLENBQUM7UUFDNUIsSUFBSSxDQUFDLFVBQVUsR0FBRyxPQUFPLENBQUMsVUFBVSxJQUFJLElBQUksQ0FBQztJQUNqRCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxNQUFNLENBQ0YsUUFBYSxFQUNiLE1BQW9CLEVBQ3BCLE9BQTZCO1FBRTdCLE1BQU0sV0FBVyxHQUFHLE1BQU0sSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDO1FBQ2pELE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFcEQsTUFBTSxZQUFZLEdBQWtCLEVBQUUsQ0FBQztRQUN2QyxJQUFJLFlBQVksR0FBRyxDQUFDLENBQUM7UUFDckIsSUFBSSxZQUFZLEdBQUcsQ0FBQyxDQUFDO1FBQ3JCLElBQUksT0FBTyxHQUFHLEtBQUssQ0FBQztRQUNwQixJQUFJLFdBQStCLENBQUM7UUFFcEMsS0FBSyxNQUFNLEtBQUssSUFBSSxXQUFXLEVBQUUsQ0FBQztZQUM5QixJQUFJLENBQUM7Z0JBQ0QsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLENBQUM7Z0JBQ3BELFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBRTFCLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO29CQUNoQixZQUFZLEVBQUUsQ0FBQztnQkFDbkIsQ0FBQztxQkFBTSxDQUFDO29CQUNKLFlBQVksRUFBRSxDQUFDO29CQUNmLElBQUksTUFBTSxDQUFDLFFBQVEsS0FBSyxPQUFPLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO3dCQUNqRCxPQUFPLEdBQUcsSUFBSSxDQUFDO3dCQUNmLFdBQVcsR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDO29CQUNqQyxDQUFDO2dCQUNMLENBQUM7WUFDTCxDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFDYixZQUFZLENBQUMsSUFBSSxDQUFDO29CQUNkLFNBQVMsRUFBRSxLQUFLLENBQUMsSUFBSTtvQkFDckIsTUFBTSxFQUFFLEtBQUs7b0JBQ2IsT0FBTyxFQUFFLGdCQUFnQixLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUU7b0JBQ2pGLFFBQVEsRUFBRSxPQUFPO2lCQUNwQixDQUFDLENBQUM7Z0JBQ0gsWUFBWSxFQUFFLENBQUM7WUFDbkIsQ0FBQztRQUNMLENBQUM7UUFFRCxPQUFPO1lBQ0gsUUFBUSxFQUFFLFlBQVksS0FBSyxDQUFDO1lBQzVCLFFBQVEsRUFBRSxjQUFjO1lBQ3hCLFlBQVk7WUFDWixZQUFZO1lBQ1osWUFBWTtZQUNaLE9BQU87WUFDUCxXQUFXO1lBQ1gsU0FBUyxFQUFFLElBQUksSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFO1NBQ3RDLENBQUM7SUFDTixDQUFDO0lBRUQ7O09BRUc7SUFDSCxjQUFjLENBQ1YsUUFBZ0IsRUFDaEIsSUFBeUIsRUFDekIsTUFBb0I7UUFFcEIsTUFBTSxRQUFRLEdBQUc7WUFDYixJQUFJLEVBQUUsV0FBVztZQUNqQixRQUFRO1lBQ1IsU0FBUyxFQUFFLElBQUk7U0FDbEIsQ0FBQztRQUNGLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVPLGFBQWEsQ0FBQyxRQUFhO1FBQy9CLElBQUksT0FBTyxRQUFRLEtBQUssUUFBUSxJQUFJLFFBQVEsS0FBSyxJQUFJLEVBQUUsQ0FBQztZQUNwRCxPQUFPLFFBQVEsQ0FBQztRQUNwQixDQUFDO1FBRUQsSUFBSSxPQUFPLFFBQVEsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUMvQixJQUFJLENBQUM7Z0JBQ0QsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ2hDLENBQUM7WUFBQyxNQUFNLENBQUM7Z0JBQ0wsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxDQUFDO1lBQy9DLENBQUM7UUFDTCxDQUFDO1FBRUQsT0FBTyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO0lBQ3RELENBQUM7Q0FDSjtBQTlGRCw0Q0E4RkMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFFXRUQgT3BlbiBSZXNwb25zZXMgLSBSZXNwb25zZSBWZXJpZmllclxuICovXG5cbmltcG9ydCB7IEJhc2VHdWFyZCB9IGZyb20gJy4vZ3VhcmRzJztcbmltcG9ydCB7IFZlcmlmaWNhdGlvblJlc3VsdCwgR3VhcmRSZXN1bHQsIFBhcnNlZFJlc3BvbnNlIH0gZnJvbSAnLi90eXBlcyc7XG5cbi8vIFJlLWV4cG9ydCB0eXBlc1xuZXhwb3J0IHsgVmVyaWZpY2F0aW9uUmVzdWx0LCBHdWFyZFJlc3VsdCB9O1xuXG4vKipcbiAqIE1haW4gdmVyaWZpZXIgZm9yIEFJIHJlc3BvbnNlcy5cbiAqL1xuZXhwb3J0IGNsYXNzIFJlc3BvbnNlVmVyaWZpZXIge1xuICAgIHByaXZhdGUgZGVmYXVsdEd1YXJkczogQmFzZUd1YXJkW107XG4gICAgcHJpdmF0ZSBzdHJpY3RNb2RlOiBib29sZWFuO1xuXG4gICAgY29uc3RydWN0b3IoZ3VhcmRzOiBCYXNlR3VhcmRbXSA9IFtdLCBvcHRpb25zOiB7IHN0cmljdE1vZGU/OiBib29sZWFuIH0gPSB7fSkge1xuICAgICAgICB0aGlzLmRlZmF1bHRHdWFyZHMgPSBndWFyZHM7XG4gICAgICAgIHRoaXMuc3RyaWN0TW9kZSA9IG9wdGlvbnMuc3RyaWN0TW9kZSA/PyB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFZlcmlmeSBhIHJlc3BvbnNlIGFnYWluc3QgZ3VhcmRzLlxuICAgICAqL1xuICAgIHZlcmlmeShcbiAgICAgICAgcmVzcG9uc2U6IGFueSxcbiAgICAgICAgZ3VhcmRzPzogQmFzZUd1YXJkW10sXG4gICAgICAgIGNvbnRleHQ/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+XG4gICAgKTogVmVyaWZpY2F0aW9uUmVzdWx0IHtcbiAgICAgICAgY29uc3QgZ3VhcmRzVG9Vc2UgPSBndWFyZHMgPz8gdGhpcy5kZWZhdWx0R3VhcmRzO1xuICAgICAgICBjb25zdCBwYXJzZWRSZXNwb25zZSA9IHRoaXMucGFyc2VSZXNwb25zZShyZXNwb25zZSk7XG5cbiAgICAgICAgY29uc3QgZ3VhcmRSZXN1bHRzOiBHdWFyZFJlc3VsdFtdID0gW107XG4gICAgICAgIGxldCBndWFyZHNQYXNzZWQgPSAwO1xuICAgICAgICBsZXQgZ3VhcmRzRmFpbGVkID0gMDtcbiAgICAgICAgbGV0IGJsb2NrZWQgPSBmYWxzZTtcbiAgICAgICAgbGV0IGJsb2NrUmVhc29uOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgICAgICAgZm9yIChjb25zdCBndWFyZCBvZiBndWFyZHNUb1VzZSkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBndWFyZC5jaGVjayhwYXJzZWRSZXNwb25zZSwgY29udGV4dCk7XG4gICAgICAgICAgICAgICAgZ3VhcmRSZXN1bHRzLnB1c2gocmVzdWx0KTtcblxuICAgICAgICAgICAgICAgIGlmIChyZXN1bHQucGFzc2VkKSB7XG4gICAgICAgICAgICAgICAgICAgIGd1YXJkc1Bhc3NlZCsrO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGd1YXJkc0ZhaWxlZCsrO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0LnNldmVyaXR5ID09PSAnZXJyb3InICYmIHRoaXMuc3RyaWN0TW9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYmxvY2tlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBibG9ja1JlYXNvbiA9IHJlc3VsdC5tZXNzYWdlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBndWFyZFJlc3VsdHMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGd1YXJkTmFtZTogZ3VhcmQubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgcGFzc2VkOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogYEd1YXJkIGVycm9yOiAke2Vycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKX1gLFxuICAgICAgICAgICAgICAgICAgICBzZXZlcml0eTogJ2Vycm9yJyxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBndWFyZHNGYWlsZWQrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB2ZXJpZmllZDogZ3VhcmRzRmFpbGVkID09PSAwLFxuICAgICAgICAgICAgcmVzcG9uc2U6IHBhcnNlZFJlc3BvbnNlLFxuICAgICAgICAgICAgZ3VhcmRzUGFzc2VkLFxuICAgICAgICAgICAgZ3VhcmRzRmFpbGVkLFxuICAgICAgICAgICAgZ3VhcmRSZXN1bHRzLFxuICAgICAgICAgICAgYmxvY2tlZCxcbiAgICAgICAgICAgIGJsb2NrUmVhc29uLFxuICAgICAgICAgICAgdGltZXN0YW1wOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVmVyaWZ5IGEgdG9vbCBjYWxsLlxuICAgICAqL1xuICAgIHZlcmlmeVRvb2xDYWxsKFxuICAgICAgICB0b29sTmFtZTogc3RyaW5nLFxuICAgICAgICBhcmdzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgICAgICBndWFyZHM/OiBCYXNlR3VhcmRbXVxuICAgICk6IFZlcmlmaWNhdGlvblJlc3VsdCB7XG4gICAgICAgIGNvbnN0IHRvb2xDYWxsID0ge1xuICAgICAgICAgICAgdHlwZTogJ3Rvb2xfY2FsbCcsXG4gICAgICAgICAgICB0b29sTmFtZSxcbiAgICAgICAgICAgIGFyZ3VtZW50czogYXJncyxcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHRoaXMudmVyaWZ5KHRvb2xDYWxsLCBndWFyZHMpO1xuICAgIH1cblxuICAgIHByaXZhdGUgcGFyc2VSZXNwb25zZShyZXNwb25zZTogYW55KTogUGFyc2VkUmVzcG9uc2Uge1xuICAgICAgICBpZiAodHlwZW9mIHJlc3BvbnNlID09PSAnb2JqZWN0JyAmJiByZXNwb25zZSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiByZXNwb25zZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UocmVzcG9uc2UpO1xuICAgICAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgdHlwZTogJ3RleHQnLCBjb250ZW50OiByZXNwb25zZSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHsgdHlwZTogJ3Vua25vd24nLCByYXc6IFN0cmluZyhyZXNwb25zZSkgfTtcbiAgICB9XG59XG4iXX0=
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "qwed-open-responses",
3
+ "version": "0.1.0",
4
+ "description": "Verification guards for AI agent outputs - Works with OpenAI, LangChain, Express.js",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "README.md",
10
+ "LICENSE"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "test": "jest",
15
+ "prepublishOnly": "npm run build"
16
+ },
17
+ "keywords": [
18
+ "ai",
19
+ "verification",
20
+ "openai",
21
+ "responses-api",
22
+ "agents",
23
+ "tool-calling",
24
+ "structured-outputs",
25
+ "llm",
26
+ "safety",
27
+ "express",
28
+ "middleware",
29
+ "qwed"
30
+ ],
31
+ "author": "QWED-AI <team@qwedai.com>",
32
+ "license": "Apache-2.0",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/QWED-AI/qwed-open-responses.git"
36
+ },
37
+ "bugs": {
38
+ "url": "https://github.com/QWED-AI/qwed-open-responses/issues"
39
+ },
40
+ "homepage": "https://github.com/QWED-AI/qwed-open-responses#readme",
41
+ "devDependencies": {
42
+ "@types/express": "^4.17.21",
43
+ "@types/node": "^20.10.0",
44
+ "typescript": "^5.3.0",
45
+ "jest": "^29.7.0",
46
+ "@types/jest": "^29.5.11"
47
+ },
48
+ "peerDependencies": {
49
+ "express": "^4.18.0 || ^5.0.0"
50
+ },
51
+ "engines": {
52
+ "node": ">=16.0.0"
53
+ }
54
+ }