@complyedge/sdk 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 +216 -0
- package/README.md +139 -0
- package/dist/chunk-KZYIMMVM.mjs +54 -0
- package/dist/chunk-KZYIMMVM.mjs.map +1 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +228 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +145 -0
- package/dist/index.mjs.map +1 -0
- package/dist/openai-middleware.d.mts +159 -0
- package/dist/openai-middleware.d.ts +159 -0
- package/dist/openai-middleware.js +79 -0
- package/dist/openai-middleware.js.map +1 -0
- package/dist/openai-middleware.mjs +9 -0
- package/dist/openai-middleware.mjs.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/client.ts","../src/openai-middleware.ts"],"sourcesContent":["/**\n * ComplyEdge TypeScript SDK\n *\n * Runtime EU AI Act enforcement for AI agents.\n *\n * @example\n * ```typescript\n * import { ComplyEdgeClient } from \"@complyedge/sdk\";\n *\n * const ce = new ComplyEdgeClient({ apiKey: process.env.COMPLYEDGE_API_KEY! });\n * const result = await ce.check(\"Your AI prompt here\");\n *\n * if (result.status === \"violation\") {\n * console.log(\"Blocked:\", result.violations);\n * }\n * ```\n */\n\nexport { ComplyEdgeClient } from \"./client\";\nexport { withCompliance, ComplianceError } from \"./openai-middleware\";\nexport type {\n ComplyEdgeConfig,\n ComplianceContext,\n ComplianceResult,\n ComplianceViolation,\n SeverityLevel,\n SensitivityResult,\n SensitivityDetection,\n PreDeploymentInput,\n PreDeploymentResult,\n} from \"./types\";\n","/**\n * ComplyEdge TypeScript SDK — Client\n */\n\nimport axios, { AxiosInstance } from \"axios\";\nimport type {\n ComplyEdgeConfig,\n ComplianceContext,\n ComplianceResult,\n ComplianceViolation,\n SensitivityDetection,\n SensitivityResult,\n PreDeploymentInput,\n PreDeploymentResult,\n} from \"./types\";\n\nconst DEFAULT_BASE_URL = \"https://api.complyedge.io\";\nconst SDK_VERSION = \"0.2.0\";\n\nexport class ComplyEdgeClient {\n private http: AxiosInstance;\n private agentId: string;\n private jurisdiction?: string;\n\n constructor(config: ComplyEdgeConfig) {\n const baseUrl = config.baseUrl || process.env.COMPLYEDGE_API_URL || DEFAULT_BASE_URL;\n\n this.agentId = config.agentId || \"default\";\n this.jurisdiction = config.jurisdiction;\n\n this.http = axios.create({\n baseURL: baseUrl.replace(/\\/+$/, \"\"),\n timeout: config.timeout || 30_000,\n headers: {\n Authorization: `Bearer ${config.apiKey}`,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": `complyedge-typescript-sdk/${SDK_VERSION}`,\n },\n });\n }\n\n /**\n * Run a compliance check on text input.\n *\n * Calls POST /v1/check: the deterministic OPA hot path. A decision here is\n * evaluated against the Rego rule bundle, returns article-cited violations,\n * and is written to the Article 12 audit trail (`auditLogged`).\n */\n async check(text: string, context?: ComplianceContext): Promise<ComplianceResult> {\n const start = Date.now();\n const jurisdiction = context?.jurisdiction || this.jurisdiction || \"EU\";\n\n const response = await this.http.post(\"/v1/check\", {\n text,\n agent_id: context?.agentId || this.agentId,\n jurisdiction,\n direction: context?.direction === \"prompt\" ? \"input\" : \"output\",\n use_semantic_fallback: false,\n context: context?.userRole ? { user_role: context.userRole } : undefined,\n });\n\n const data = response.data;\n const processingTimeMs = Date.now() - start;\n const allowed = data.allowed !== false;\n\n return {\n eventId: data.event_id || \"\",\n allowed,\n status: allowed ? \"safe\" : \"violation\",\n violations: (data.violations || []).map((v: Record<string, unknown>) => ({\n ruleId: (v.rule_id as string) || \"\",\n ruleDescription: (v.rule_description as string) || \"\",\n severity: (v.severity as ComplianceViolation[\"severity\"]) || \"medium\",\n reason: (v.reason as string) || \"\",\n confidence: (v.confidence as number) ?? 1.0,\n textExcerpt: v.text_excerpt as string | undefined,\n })),\n latencyMs: data.latency_ms || 0,\n bundleVersion: data.bundle_version || \"\",\n evaluatedRules: data.evaluated_rules || [],\n enginePath: data.engine_path || \"opa\",\n opaLatencyMs: data.opa_latency_ms,\n auditLogged: data.audit_logged !== false,\n jurisdiction,\n processingTimeMs,\n };\n }\n\n /**\n * Run proactive sensitivity detection on user input.\n *\n * Calls POST /v1/sensitivity/detect, which deliberately stays on the legacy\n * TrustLint + LLM pipeline. It does NOT run OPA and does NOT write the\n * Article 12 audit trail. Use `check()` for runtime EU AI Act enforcement.\n */\n async detectSensitivity(\n text: string,\n context?: ComplianceContext\n ): Promise<SensitivityResult> {\n const start = Date.now();\n const jurisdiction = context?.jurisdiction || this.jurisdiction || \"US\";\n\n const response = await this.http.post(\"/v1/sensitivity/detect\", {\n input_text: text,\n agent_id: context?.agentId || this.agentId,\n jurisdiction,\n direction: context?.direction || \"prompt\",\n user_role: context?.userRole,\n });\n\n const data = response.data;\n\n return {\n eventId: data.event_id || \"\",\n status: data.overall_risk_assessment === \"safe\" ? \"safe\" : \"violation\",\n detections: (data.detections || []).map((d: Record<string, unknown>) => ({\n ruleId: (d.rule_id as string) || \"\",\n severity: (d.severity as SensitivityDetection[\"severity\"]) || \"medium\",\n regulation: (d.regulation as string) || \"\",\n description: (d.description as string) || \"\",\n article: d.article as string | undefined,\n remediation: d.remediation as string | undefined,\n })),\n riskScore: data.overall_risk_score || 0,\n jurisdiction,\n processingTimeMs: Date.now() - start,\n };\n }\n\n /**\n * Run a pre-deployment assessment on an AI system configuration.\n */\n async assessPreDeployment(input: PreDeploymentInput): Promise<PreDeploymentResult> {\n const response = await this.http.post(\"/v1/assessment/pre-deployment\", {\n system_prompt: input.systemPrompt,\n model_config: input.modelConfig\n ? {\n provider: input.modelConfig.provider,\n model_id: input.modelConfig.modelId,\n temperature: input.modelConfig.temperature,\n }\n : undefined,\n agent_pipeline: input.agentPipeline\n ? {\n tools: input.agentPipeline.tools,\n memory: input.agentPipeline.memory,\n autonomy_level: input.agentPipeline.autonomyLevel,\n human_oversight: input.agentPipeline.humanOversight,\n }\n : undefined,\n jurisdiction: input.jurisdiction || \"EU\",\n });\n\n const data = response.data;\n return {\n complianceScore: data.compliance_score,\n riskTier: data.risk_tier,\n violations: (data.violations || []).map((v: Record<string, unknown>) => ({\n ruleId: v.rule_id as string,\n article: v.article as string,\n description: v.description as string,\n requiredAction: v.required_action as string,\n })),\n requiredDisclosures: data.required_disclosures || [],\n euAiActCategory: data.eu_ai_act_category || \"\",\n estimatedDeadline: data.estimated_deadline || \"\",\n };\n }\n}\n","/**\n * ComplyEdge OpenAI Middleware\n *\n * Wraps an OpenAI client to run compliance checks on messages\n * before they are sent to the model.\n *\n * Usage:\n * import OpenAI from \"openai\";\n * import { ComplyEdgeClient } from \"@complyedge/sdk\";\n * import { withCompliance } from \"@complyedge/sdk/openai-middleware\";\n *\n * const ce = new ComplyEdgeClient({ apiKey: \"...\" });\n * const openai = withCompliance(new OpenAI(), ce);\n * // Now openai.chat.completions.create() runs compliance checks automatically\n */\n\nimport type { ComplyEdgeClient } from \"./client\";\nimport type { ComplianceViolation } from \"./types\";\n\nexport class ComplianceError extends Error {\n public violations: ComplianceViolation[];\n\n constructor(message: string, violations: ComplianceViolation[]) {\n super(message);\n this.name = \"ComplianceError\";\n this.violations = violations;\n }\n}\n\n/**\n * Wrap an OpenAI client with ComplyEdge compliance checks.\n * The returned object proxies chat.completions.create() to check\n * user messages before sending to OpenAI.\n */\nexport function withCompliance<T extends Record<string, unknown>>(\n openaiClient: T,\n ceClient: ComplyEdgeClient,\n options?: {\n checkInput?: boolean;\n checkOutput?: boolean;\n jurisdiction?: string;\n blockOnViolation?: boolean;\n }\n): T {\n const opts = {\n checkInput: true,\n checkOutput: false,\n blockOnViolation: true,\n ...options,\n };\n\n const chat = openaiClient.chat as Record<string, unknown> | undefined;\n if (!chat || !chat.completions) {\n return openaiClient; // Not an OpenAI-shaped client, return as-is\n }\n\n const completions = chat.completions as Record<string, unknown>;\n const originalCreate = completions.create as (...args: unknown[]) => Promise<unknown>;\n\n if (typeof originalCreate !== \"function\") {\n return openaiClient;\n }\n\n completions.create = async function (...args: unknown[]) {\n const params = args[0] as Record<string, unknown> | undefined;\n\n if (opts.checkInput && params?.messages) {\n const messages = params.messages as Array<{ role: string; content: string }>;\n const userMessages = messages.filter((m) => m.role === \"user\");\n const lastUserMessage = userMessages[userMessages.length - 1];\n\n if (lastUserMessage?.content) {\n const result = await ceClient.check(lastUserMessage.content, {\n direction: \"prompt\",\n jurisdiction: opts.jurisdiction,\n });\n\n if (!result.allowed && opts.blockOnViolation) {\n throw new ComplianceError(\n `Compliance violation detected: ${result.violations.map((v) => v.ruleId).join(\", \")}`,\n result.violations\n );\n }\n }\n }\n\n return originalCreate.apply(this, args);\n };\n\n return openaiClient;\n}\n"],"mappings":"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","names":["axios"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ComplianceError,
|
|
3
|
+
withCompliance
|
|
4
|
+
} from "./chunk-KZYIMMVM.mjs";
|
|
5
|
+
|
|
6
|
+
// src/client.ts
|
|
7
|
+
import axios from "axios";
|
|
8
|
+
var DEFAULT_BASE_URL = "https://api.complyedge.io";
|
|
9
|
+
var SDK_VERSION = "0.2.0";
|
|
10
|
+
var ComplyEdgeClient = class {
|
|
11
|
+
http;
|
|
12
|
+
agentId;
|
|
13
|
+
jurisdiction;
|
|
14
|
+
constructor(config) {
|
|
15
|
+
const baseUrl = config.baseUrl || process.env.COMPLYEDGE_API_URL || DEFAULT_BASE_URL;
|
|
16
|
+
this.agentId = config.agentId || "default";
|
|
17
|
+
this.jurisdiction = config.jurisdiction;
|
|
18
|
+
this.http = axios.create({
|
|
19
|
+
baseURL: baseUrl.replace(/\/+$/, ""),
|
|
20
|
+
timeout: config.timeout || 3e4,
|
|
21
|
+
headers: {
|
|
22
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
23
|
+
"Content-Type": "application/json",
|
|
24
|
+
"User-Agent": `complyedge-typescript-sdk/${SDK_VERSION}`
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Run a compliance check on text input.
|
|
30
|
+
*
|
|
31
|
+
* Calls POST /v1/check: the deterministic OPA hot path. A decision here is
|
|
32
|
+
* evaluated against the Rego rule bundle, returns article-cited violations,
|
|
33
|
+
* and is written to the Article 12 audit trail (`auditLogged`).
|
|
34
|
+
*/
|
|
35
|
+
async check(text, context) {
|
|
36
|
+
const start = Date.now();
|
|
37
|
+
const jurisdiction = context?.jurisdiction || this.jurisdiction || "EU";
|
|
38
|
+
const response = await this.http.post("/v1/check", {
|
|
39
|
+
text,
|
|
40
|
+
agent_id: context?.agentId || this.agentId,
|
|
41
|
+
jurisdiction,
|
|
42
|
+
direction: context?.direction === "prompt" ? "input" : "output",
|
|
43
|
+
use_semantic_fallback: false,
|
|
44
|
+
context: context?.userRole ? { user_role: context.userRole } : void 0
|
|
45
|
+
});
|
|
46
|
+
const data = response.data;
|
|
47
|
+
const processingTimeMs = Date.now() - start;
|
|
48
|
+
const allowed = data.allowed !== false;
|
|
49
|
+
return {
|
|
50
|
+
eventId: data.event_id || "",
|
|
51
|
+
allowed,
|
|
52
|
+
status: allowed ? "safe" : "violation",
|
|
53
|
+
violations: (data.violations || []).map((v) => ({
|
|
54
|
+
ruleId: v.rule_id || "",
|
|
55
|
+
ruleDescription: v.rule_description || "",
|
|
56
|
+
severity: v.severity || "medium",
|
|
57
|
+
reason: v.reason || "",
|
|
58
|
+
confidence: v.confidence ?? 1,
|
|
59
|
+
textExcerpt: v.text_excerpt
|
|
60
|
+
})),
|
|
61
|
+
latencyMs: data.latency_ms || 0,
|
|
62
|
+
bundleVersion: data.bundle_version || "",
|
|
63
|
+
evaluatedRules: data.evaluated_rules || [],
|
|
64
|
+
enginePath: data.engine_path || "opa",
|
|
65
|
+
opaLatencyMs: data.opa_latency_ms,
|
|
66
|
+
auditLogged: data.audit_logged !== false,
|
|
67
|
+
jurisdiction,
|
|
68
|
+
processingTimeMs
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Run proactive sensitivity detection on user input.
|
|
73
|
+
*
|
|
74
|
+
* Calls POST /v1/sensitivity/detect, which deliberately stays on the legacy
|
|
75
|
+
* TrustLint + LLM pipeline. It does NOT run OPA and does NOT write the
|
|
76
|
+
* Article 12 audit trail. Use `check()` for runtime EU AI Act enforcement.
|
|
77
|
+
*/
|
|
78
|
+
async detectSensitivity(text, context) {
|
|
79
|
+
const start = Date.now();
|
|
80
|
+
const jurisdiction = context?.jurisdiction || this.jurisdiction || "US";
|
|
81
|
+
const response = await this.http.post("/v1/sensitivity/detect", {
|
|
82
|
+
input_text: text,
|
|
83
|
+
agent_id: context?.agentId || this.agentId,
|
|
84
|
+
jurisdiction,
|
|
85
|
+
direction: context?.direction || "prompt",
|
|
86
|
+
user_role: context?.userRole
|
|
87
|
+
});
|
|
88
|
+
const data = response.data;
|
|
89
|
+
return {
|
|
90
|
+
eventId: data.event_id || "",
|
|
91
|
+
status: data.overall_risk_assessment === "safe" ? "safe" : "violation",
|
|
92
|
+
detections: (data.detections || []).map((d) => ({
|
|
93
|
+
ruleId: d.rule_id || "",
|
|
94
|
+
severity: d.severity || "medium",
|
|
95
|
+
regulation: d.regulation || "",
|
|
96
|
+
description: d.description || "",
|
|
97
|
+
article: d.article,
|
|
98
|
+
remediation: d.remediation
|
|
99
|
+
})),
|
|
100
|
+
riskScore: data.overall_risk_score || 0,
|
|
101
|
+
jurisdiction,
|
|
102
|
+
processingTimeMs: Date.now() - start
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Run a pre-deployment assessment on an AI system configuration.
|
|
107
|
+
*/
|
|
108
|
+
async assessPreDeployment(input) {
|
|
109
|
+
const response = await this.http.post("/v1/assessment/pre-deployment", {
|
|
110
|
+
system_prompt: input.systemPrompt,
|
|
111
|
+
model_config: input.modelConfig ? {
|
|
112
|
+
provider: input.modelConfig.provider,
|
|
113
|
+
model_id: input.modelConfig.modelId,
|
|
114
|
+
temperature: input.modelConfig.temperature
|
|
115
|
+
} : void 0,
|
|
116
|
+
agent_pipeline: input.agentPipeline ? {
|
|
117
|
+
tools: input.agentPipeline.tools,
|
|
118
|
+
memory: input.agentPipeline.memory,
|
|
119
|
+
autonomy_level: input.agentPipeline.autonomyLevel,
|
|
120
|
+
human_oversight: input.agentPipeline.humanOversight
|
|
121
|
+
} : void 0,
|
|
122
|
+
jurisdiction: input.jurisdiction || "EU"
|
|
123
|
+
});
|
|
124
|
+
const data = response.data;
|
|
125
|
+
return {
|
|
126
|
+
complianceScore: data.compliance_score,
|
|
127
|
+
riskTier: data.risk_tier,
|
|
128
|
+
violations: (data.violations || []).map((v) => ({
|
|
129
|
+
ruleId: v.rule_id,
|
|
130
|
+
article: v.article,
|
|
131
|
+
description: v.description,
|
|
132
|
+
requiredAction: v.required_action
|
|
133
|
+
})),
|
|
134
|
+
requiredDisclosures: data.required_disclosures || [],
|
|
135
|
+
euAiActCategory: data.eu_ai_act_category || "",
|
|
136
|
+
estimatedDeadline: data.estimated_deadline || ""
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
export {
|
|
141
|
+
ComplianceError,
|
|
142
|
+
ComplyEdgeClient,
|
|
143
|
+
withCompliance
|
|
144
|
+
};
|
|
145
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client.ts"],"sourcesContent":["/**\n * ComplyEdge TypeScript SDK — Client\n */\n\nimport axios, { AxiosInstance } from \"axios\";\nimport type {\n ComplyEdgeConfig,\n ComplianceContext,\n ComplianceResult,\n ComplianceViolation,\n SensitivityDetection,\n SensitivityResult,\n PreDeploymentInput,\n PreDeploymentResult,\n} from \"./types\";\n\nconst DEFAULT_BASE_URL = \"https://api.complyedge.io\";\nconst SDK_VERSION = \"0.2.0\";\n\nexport class ComplyEdgeClient {\n private http: AxiosInstance;\n private agentId: string;\n private jurisdiction?: string;\n\n constructor(config: ComplyEdgeConfig) {\n const baseUrl = config.baseUrl || process.env.COMPLYEDGE_API_URL || DEFAULT_BASE_URL;\n\n this.agentId = config.agentId || \"default\";\n this.jurisdiction = config.jurisdiction;\n\n this.http = axios.create({\n baseURL: baseUrl.replace(/\\/+$/, \"\"),\n timeout: config.timeout || 30_000,\n headers: {\n Authorization: `Bearer ${config.apiKey}`,\n \"Content-Type\": \"application/json\",\n \"User-Agent\": `complyedge-typescript-sdk/${SDK_VERSION}`,\n },\n });\n }\n\n /**\n * Run a compliance check on text input.\n *\n * Calls POST /v1/check: the deterministic OPA hot path. A decision here is\n * evaluated against the Rego rule bundle, returns article-cited violations,\n * and is written to the Article 12 audit trail (`auditLogged`).\n */\n async check(text: string, context?: ComplianceContext): Promise<ComplianceResult> {\n const start = Date.now();\n const jurisdiction = context?.jurisdiction || this.jurisdiction || \"EU\";\n\n const response = await this.http.post(\"/v1/check\", {\n text,\n agent_id: context?.agentId || this.agentId,\n jurisdiction,\n direction: context?.direction === \"prompt\" ? \"input\" : \"output\",\n use_semantic_fallback: false,\n context: context?.userRole ? { user_role: context.userRole } : undefined,\n });\n\n const data = response.data;\n const processingTimeMs = Date.now() - start;\n const allowed = data.allowed !== false;\n\n return {\n eventId: data.event_id || \"\",\n allowed,\n status: allowed ? \"safe\" : \"violation\",\n violations: (data.violations || []).map((v: Record<string, unknown>) => ({\n ruleId: (v.rule_id as string) || \"\",\n ruleDescription: (v.rule_description as string) || \"\",\n severity: (v.severity as ComplianceViolation[\"severity\"]) || \"medium\",\n reason: (v.reason as string) || \"\",\n confidence: (v.confidence as number) ?? 1.0,\n textExcerpt: v.text_excerpt as string | undefined,\n })),\n latencyMs: data.latency_ms || 0,\n bundleVersion: data.bundle_version || \"\",\n evaluatedRules: data.evaluated_rules || [],\n enginePath: data.engine_path || \"opa\",\n opaLatencyMs: data.opa_latency_ms,\n auditLogged: data.audit_logged !== false,\n jurisdiction,\n processingTimeMs,\n };\n }\n\n /**\n * Run proactive sensitivity detection on user input.\n *\n * Calls POST /v1/sensitivity/detect, which deliberately stays on the legacy\n * TrustLint + LLM pipeline. It does NOT run OPA and does NOT write the\n * Article 12 audit trail. Use `check()` for runtime EU AI Act enforcement.\n */\n async detectSensitivity(\n text: string,\n context?: ComplianceContext\n ): Promise<SensitivityResult> {\n const start = Date.now();\n const jurisdiction = context?.jurisdiction || this.jurisdiction || \"US\";\n\n const response = await this.http.post(\"/v1/sensitivity/detect\", {\n input_text: text,\n agent_id: context?.agentId || this.agentId,\n jurisdiction,\n direction: context?.direction || \"prompt\",\n user_role: context?.userRole,\n });\n\n const data = response.data;\n\n return {\n eventId: data.event_id || \"\",\n status: data.overall_risk_assessment === \"safe\" ? \"safe\" : \"violation\",\n detections: (data.detections || []).map((d: Record<string, unknown>) => ({\n ruleId: (d.rule_id as string) || \"\",\n severity: (d.severity as SensitivityDetection[\"severity\"]) || \"medium\",\n regulation: (d.regulation as string) || \"\",\n description: (d.description as string) || \"\",\n article: d.article as string | undefined,\n remediation: d.remediation as string | undefined,\n })),\n riskScore: data.overall_risk_score || 0,\n jurisdiction,\n processingTimeMs: Date.now() - start,\n };\n }\n\n /**\n * Run a pre-deployment assessment on an AI system configuration.\n */\n async assessPreDeployment(input: PreDeploymentInput): Promise<PreDeploymentResult> {\n const response = await this.http.post(\"/v1/assessment/pre-deployment\", {\n system_prompt: input.systemPrompt,\n model_config: input.modelConfig\n ? {\n provider: input.modelConfig.provider,\n model_id: input.modelConfig.modelId,\n temperature: input.modelConfig.temperature,\n }\n : undefined,\n agent_pipeline: input.agentPipeline\n ? {\n tools: input.agentPipeline.tools,\n memory: input.agentPipeline.memory,\n autonomy_level: input.agentPipeline.autonomyLevel,\n human_oversight: input.agentPipeline.humanOversight,\n }\n : undefined,\n jurisdiction: input.jurisdiction || \"EU\",\n });\n\n const data = response.data;\n return {\n complianceScore: data.compliance_score,\n riskTier: data.risk_tier,\n violations: (data.violations || []).map((v: Record<string, unknown>) => ({\n ruleId: v.rule_id as string,\n article: v.article as string,\n description: v.description as string,\n requiredAction: v.required_action as string,\n })),\n requiredDisclosures: data.required_disclosures || [],\n euAiActCategory: data.eu_ai_act_category || \"\",\n estimatedDeadline: data.estimated_deadline || \"\",\n };\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ComplyEdge TypeScript SDK — Type definitions
|
|
3
|
+
* Matches the Python SDK interfaces for cross-language consistency.
|
|
4
|
+
*/
|
|
5
|
+
interface ComplianceContext {
|
|
6
|
+
agentId?: string;
|
|
7
|
+
jurisdiction?: string;
|
|
8
|
+
userRole?: string;
|
|
9
|
+
direction?: "prompt" | "output";
|
|
10
|
+
}
|
|
11
|
+
type SeverityLevel = "critical" | "high" | "medium" | "low" | "informational";
|
|
12
|
+
interface ComplianceViolation {
|
|
13
|
+
ruleId: string;
|
|
14
|
+
ruleDescription: string;
|
|
15
|
+
severity: SeverityLevel;
|
|
16
|
+
reason: string;
|
|
17
|
+
confidence: number;
|
|
18
|
+
textExcerpt?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Result of POST /v1/check (the deterministic OPA enforcement path).
|
|
22
|
+
* Field names mirror the Python SDK's ComplianceResult.
|
|
23
|
+
*/
|
|
24
|
+
interface ComplianceResult {
|
|
25
|
+
eventId: string;
|
|
26
|
+
allowed: boolean;
|
|
27
|
+
/** Convenience mirror of `allowed`, for branch-on-string call sites. */
|
|
28
|
+
status: "safe" | "violation";
|
|
29
|
+
violations: ComplianceViolation[];
|
|
30
|
+
latencyMs: number;
|
|
31
|
+
bundleVersion: string;
|
|
32
|
+
evaluatedRules: string[];
|
|
33
|
+
enginePath: string;
|
|
34
|
+
opaLatencyMs?: number;
|
|
35
|
+
auditLogged: boolean;
|
|
36
|
+
jurisdiction: string;
|
|
37
|
+
/** Client-measured round trip, including network. */
|
|
38
|
+
processingTimeMs: number;
|
|
39
|
+
}
|
|
40
|
+
interface SensitivityDetection {
|
|
41
|
+
ruleId: string;
|
|
42
|
+
severity: SeverityLevel;
|
|
43
|
+
regulation: string;
|
|
44
|
+
description: string;
|
|
45
|
+
article?: string;
|
|
46
|
+
remediation?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Result of POST /v1/sensitivity/detect (legacy TrustLint + LLM pipeline).
|
|
50
|
+
* This path does NOT run OPA and does NOT write the Article 12 audit trail.
|
|
51
|
+
*/
|
|
52
|
+
interface SensitivityResult {
|
|
53
|
+
eventId: string;
|
|
54
|
+
status: "safe" | "violation";
|
|
55
|
+
detections: SensitivityDetection[];
|
|
56
|
+
riskScore: number;
|
|
57
|
+
jurisdiction: string;
|
|
58
|
+
processingTimeMs: number;
|
|
59
|
+
}
|
|
60
|
+
interface PreDeploymentInput {
|
|
61
|
+
systemPrompt: string;
|
|
62
|
+
modelConfig?: {
|
|
63
|
+
provider?: string;
|
|
64
|
+
modelId?: string;
|
|
65
|
+
temperature?: number;
|
|
66
|
+
};
|
|
67
|
+
agentPipeline?: {
|
|
68
|
+
tools?: string[];
|
|
69
|
+
memory?: boolean;
|
|
70
|
+
autonomyLevel?: string;
|
|
71
|
+
humanOversight?: boolean;
|
|
72
|
+
};
|
|
73
|
+
jurisdiction?: string;
|
|
74
|
+
}
|
|
75
|
+
interface PreDeploymentResult {
|
|
76
|
+
complianceScore: number;
|
|
77
|
+
riskTier: "unacceptable" | "high" | "limited" | "minimal";
|
|
78
|
+
violations: Array<{
|
|
79
|
+
ruleId: string;
|
|
80
|
+
article: string;
|
|
81
|
+
description: string;
|
|
82
|
+
requiredAction: string;
|
|
83
|
+
}>;
|
|
84
|
+
requiredDisclosures: string[];
|
|
85
|
+
euAiActCategory: string;
|
|
86
|
+
estimatedDeadline: string;
|
|
87
|
+
}
|
|
88
|
+
interface ComplyEdgeConfig {
|
|
89
|
+
apiKey: string;
|
|
90
|
+
baseUrl?: string;
|
|
91
|
+
agentId?: string;
|
|
92
|
+
jurisdiction?: string;
|
|
93
|
+
timeout?: number;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* ComplyEdge TypeScript SDK — Client
|
|
98
|
+
*/
|
|
99
|
+
|
|
100
|
+
declare class ComplyEdgeClient {
|
|
101
|
+
private http;
|
|
102
|
+
private agentId;
|
|
103
|
+
private jurisdiction?;
|
|
104
|
+
constructor(config: ComplyEdgeConfig);
|
|
105
|
+
/**
|
|
106
|
+
* Run a compliance check on text input.
|
|
107
|
+
*
|
|
108
|
+
* Calls POST /v1/check: the deterministic OPA hot path. A decision here is
|
|
109
|
+
* evaluated against the Rego rule bundle, returns article-cited violations,
|
|
110
|
+
* and is written to the Article 12 audit trail (`auditLogged`).
|
|
111
|
+
*/
|
|
112
|
+
check(text: string, context?: ComplianceContext): Promise<ComplianceResult>;
|
|
113
|
+
/**
|
|
114
|
+
* Run proactive sensitivity detection on user input.
|
|
115
|
+
*
|
|
116
|
+
* Calls POST /v1/sensitivity/detect, which deliberately stays on the legacy
|
|
117
|
+
* TrustLint + LLM pipeline. It does NOT run OPA and does NOT write the
|
|
118
|
+
* Article 12 audit trail. Use `check()` for runtime EU AI Act enforcement.
|
|
119
|
+
*/
|
|
120
|
+
detectSensitivity(text: string, context?: ComplianceContext): Promise<SensitivityResult>;
|
|
121
|
+
/**
|
|
122
|
+
* Run a pre-deployment assessment on an AI system configuration.
|
|
123
|
+
*/
|
|
124
|
+
assessPreDeployment(input: PreDeploymentInput): Promise<PreDeploymentResult>;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* ComplyEdge OpenAI Middleware
|
|
129
|
+
*
|
|
130
|
+
* Wraps an OpenAI client to run compliance checks on messages
|
|
131
|
+
* before they are sent to the model.
|
|
132
|
+
*
|
|
133
|
+
* Usage:
|
|
134
|
+
* import OpenAI from "openai";
|
|
135
|
+
* import { ComplyEdgeClient } from "@complyedge/sdk";
|
|
136
|
+
* import { withCompliance } from "@complyedge/sdk/openai-middleware";
|
|
137
|
+
*
|
|
138
|
+
* const ce = new ComplyEdgeClient({ apiKey: "..." });
|
|
139
|
+
* const openai = withCompliance(new OpenAI(), ce);
|
|
140
|
+
* // Now openai.chat.completions.create() runs compliance checks automatically
|
|
141
|
+
*/
|
|
142
|
+
|
|
143
|
+
declare class ComplianceError extends Error {
|
|
144
|
+
violations: ComplianceViolation[];
|
|
145
|
+
constructor(message: string, violations: ComplianceViolation[]);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Wrap an OpenAI client with ComplyEdge compliance checks.
|
|
149
|
+
* The returned object proxies chat.completions.create() to check
|
|
150
|
+
* user messages before sending to OpenAI.
|
|
151
|
+
*/
|
|
152
|
+
declare function withCompliance<T extends Record<string, unknown>>(openaiClient: T, ceClient: ComplyEdgeClient, options?: {
|
|
153
|
+
checkInput?: boolean;
|
|
154
|
+
checkOutput?: boolean;
|
|
155
|
+
jurisdiction?: string;
|
|
156
|
+
blockOnViolation?: boolean;
|
|
157
|
+
}): T;
|
|
158
|
+
|
|
159
|
+
export { ComplyEdgeClient as C, ComplianceError, type PreDeploymentInput as P, type SeverityLevel as S, type ComplyEdgeConfig as a, type ComplianceContext as b, type ComplianceResult as c, type ComplianceViolation as d, type SensitivityResult as e, type SensitivityDetection as f, type PreDeploymentResult as g, withCompliance };
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ComplyEdge TypeScript SDK — Type definitions
|
|
3
|
+
* Matches the Python SDK interfaces for cross-language consistency.
|
|
4
|
+
*/
|
|
5
|
+
interface ComplianceContext {
|
|
6
|
+
agentId?: string;
|
|
7
|
+
jurisdiction?: string;
|
|
8
|
+
userRole?: string;
|
|
9
|
+
direction?: "prompt" | "output";
|
|
10
|
+
}
|
|
11
|
+
type SeverityLevel = "critical" | "high" | "medium" | "low" | "informational";
|
|
12
|
+
interface ComplianceViolation {
|
|
13
|
+
ruleId: string;
|
|
14
|
+
ruleDescription: string;
|
|
15
|
+
severity: SeverityLevel;
|
|
16
|
+
reason: string;
|
|
17
|
+
confidence: number;
|
|
18
|
+
textExcerpt?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Result of POST /v1/check (the deterministic OPA enforcement path).
|
|
22
|
+
* Field names mirror the Python SDK's ComplianceResult.
|
|
23
|
+
*/
|
|
24
|
+
interface ComplianceResult {
|
|
25
|
+
eventId: string;
|
|
26
|
+
allowed: boolean;
|
|
27
|
+
/** Convenience mirror of `allowed`, for branch-on-string call sites. */
|
|
28
|
+
status: "safe" | "violation";
|
|
29
|
+
violations: ComplianceViolation[];
|
|
30
|
+
latencyMs: number;
|
|
31
|
+
bundleVersion: string;
|
|
32
|
+
evaluatedRules: string[];
|
|
33
|
+
enginePath: string;
|
|
34
|
+
opaLatencyMs?: number;
|
|
35
|
+
auditLogged: boolean;
|
|
36
|
+
jurisdiction: string;
|
|
37
|
+
/** Client-measured round trip, including network. */
|
|
38
|
+
processingTimeMs: number;
|
|
39
|
+
}
|
|
40
|
+
interface SensitivityDetection {
|
|
41
|
+
ruleId: string;
|
|
42
|
+
severity: SeverityLevel;
|
|
43
|
+
regulation: string;
|
|
44
|
+
description: string;
|
|
45
|
+
article?: string;
|
|
46
|
+
remediation?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Result of POST /v1/sensitivity/detect (legacy TrustLint + LLM pipeline).
|
|
50
|
+
* This path does NOT run OPA and does NOT write the Article 12 audit trail.
|
|
51
|
+
*/
|
|
52
|
+
interface SensitivityResult {
|
|
53
|
+
eventId: string;
|
|
54
|
+
status: "safe" | "violation";
|
|
55
|
+
detections: SensitivityDetection[];
|
|
56
|
+
riskScore: number;
|
|
57
|
+
jurisdiction: string;
|
|
58
|
+
processingTimeMs: number;
|
|
59
|
+
}
|
|
60
|
+
interface PreDeploymentInput {
|
|
61
|
+
systemPrompt: string;
|
|
62
|
+
modelConfig?: {
|
|
63
|
+
provider?: string;
|
|
64
|
+
modelId?: string;
|
|
65
|
+
temperature?: number;
|
|
66
|
+
};
|
|
67
|
+
agentPipeline?: {
|
|
68
|
+
tools?: string[];
|
|
69
|
+
memory?: boolean;
|
|
70
|
+
autonomyLevel?: string;
|
|
71
|
+
humanOversight?: boolean;
|
|
72
|
+
};
|
|
73
|
+
jurisdiction?: string;
|
|
74
|
+
}
|
|
75
|
+
interface PreDeploymentResult {
|
|
76
|
+
complianceScore: number;
|
|
77
|
+
riskTier: "unacceptable" | "high" | "limited" | "minimal";
|
|
78
|
+
violations: Array<{
|
|
79
|
+
ruleId: string;
|
|
80
|
+
article: string;
|
|
81
|
+
description: string;
|
|
82
|
+
requiredAction: string;
|
|
83
|
+
}>;
|
|
84
|
+
requiredDisclosures: string[];
|
|
85
|
+
euAiActCategory: string;
|
|
86
|
+
estimatedDeadline: string;
|
|
87
|
+
}
|
|
88
|
+
interface ComplyEdgeConfig {
|
|
89
|
+
apiKey: string;
|
|
90
|
+
baseUrl?: string;
|
|
91
|
+
agentId?: string;
|
|
92
|
+
jurisdiction?: string;
|
|
93
|
+
timeout?: number;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* ComplyEdge TypeScript SDK — Client
|
|
98
|
+
*/
|
|
99
|
+
|
|
100
|
+
declare class ComplyEdgeClient {
|
|
101
|
+
private http;
|
|
102
|
+
private agentId;
|
|
103
|
+
private jurisdiction?;
|
|
104
|
+
constructor(config: ComplyEdgeConfig);
|
|
105
|
+
/**
|
|
106
|
+
* Run a compliance check on text input.
|
|
107
|
+
*
|
|
108
|
+
* Calls POST /v1/check: the deterministic OPA hot path. A decision here is
|
|
109
|
+
* evaluated against the Rego rule bundle, returns article-cited violations,
|
|
110
|
+
* and is written to the Article 12 audit trail (`auditLogged`).
|
|
111
|
+
*/
|
|
112
|
+
check(text: string, context?: ComplianceContext): Promise<ComplianceResult>;
|
|
113
|
+
/**
|
|
114
|
+
* Run proactive sensitivity detection on user input.
|
|
115
|
+
*
|
|
116
|
+
* Calls POST /v1/sensitivity/detect, which deliberately stays on the legacy
|
|
117
|
+
* TrustLint + LLM pipeline. It does NOT run OPA and does NOT write the
|
|
118
|
+
* Article 12 audit trail. Use `check()` for runtime EU AI Act enforcement.
|
|
119
|
+
*/
|
|
120
|
+
detectSensitivity(text: string, context?: ComplianceContext): Promise<SensitivityResult>;
|
|
121
|
+
/**
|
|
122
|
+
* Run a pre-deployment assessment on an AI system configuration.
|
|
123
|
+
*/
|
|
124
|
+
assessPreDeployment(input: PreDeploymentInput): Promise<PreDeploymentResult>;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* ComplyEdge OpenAI Middleware
|
|
129
|
+
*
|
|
130
|
+
* Wraps an OpenAI client to run compliance checks on messages
|
|
131
|
+
* before they are sent to the model.
|
|
132
|
+
*
|
|
133
|
+
* Usage:
|
|
134
|
+
* import OpenAI from "openai";
|
|
135
|
+
* import { ComplyEdgeClient } from "@complyedge/sdk";
|
|
136
|
+
* import { withCompliance } from "@complyedge/sdk/openai-middleware";
|
|
137
|
+
*
|
|
138
|
+
* const ce = new ComplyEdgeClient({ apiKey: "..." });
|
|
139
|
+
* const openai = withCompliance(new OpenAI(), ce);
|
|
140
|
+
* // Now openai.chat.completions.create() runs compliance checks automatically
|
|
141
|
+
*/
|
|
142
|
+
|
|
143
|
+
declare class ComplianceError extends Error {
|
|
144
|
+
violations: ComplianceViolation[];
|
|
145
|
+
constructor(message: string, violations: ComplianceViolation[]);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Wrap an OpenAI client with ComplyEdge compliance checks.
|
|
149
|
+
* The returned object proxies chat.completions.create() to check
|
|
150
|
+
* user messages before sending to OpenAI.
|
|
151
|
+
*/
|
|
152
|
+
declare function withCompliance<T extends Record<string, unknown>>(openaiClient: T, ceClient: ComplyEdgeClient, options?: {
|
|
153
|
+
checkInput?: boolean;
|
|
154
|
+
checkOutput?: boolean;
|
|
155
|
+
jurisdiction?: string;
|
|
156
|
+
blockOnViolation?: boolean;
|
|
157
|
+
}): T;
|
|
158
|
+
|
|
159
|
+
export { ComplyEdgeClient as C, ComplianceError, type PreDeploymentInput as P, type SeverityLevel as S, type ComplyEdgeConfig as a, type ComplianceContext as b, type ComplianceResult as c, type ComplianceViolation as d, type SensitivityResult as e, type SensitivityDetection as f, type PreDeploymentResult as g, withCompliance };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/openai-middleware.ts
|
|
21
|
+
var openai_middleware_exports = {};
|
|
22
|
+
__export(openai_middleware_exports, {
|
|
23
|
+
ComplianceError: () => ComplianceError,
|
|
24
|
+
withCompliance: () => withCompliance
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(openai_middleware_exports);
|
|
27
|
+
var ComplianceError = class extends Error {
|
|
28
|
+
violations;
|
|
29
|
+
constructor(message, violations) {
|
|
30
|
+
super(message);
|
|
31
|
+
this.name = "ComplianceError";
|
|
32
|
+
this.violations = violations;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
function withCompliance(openaiClient, ceClient, options) {
|
|
36
|
+
const opts = {
|
|
37
|
+
checkInput: true,
|
|
38
|
+
checkOutput: false,
|
|
39
|
+
blockOnViolation: true,
|
|
40
|
+
...options
|
|
41
|
+
};
|
|
42
|
+
const chat = openaiClient.chat;
|
|
43
|
+
if (!chat || !chat.completions) {
|
|
44
|
+
return openaiClient;
|
|
45
|
+
}
|
|
46
|
+
const completions = chat.completions;
|
|
47
|
+
const originalCreate = completions.create;
|
|
48
|
+
if (typeof originalCreate !== "function") {
|
|
49
|
+
return openaiClient;
|
|
50
|
+
}
|
|
51
|
+
completions.create = async function(...args) {
|
|
52
|
+
const params = args[0];
|
|
53
|
+
if (opts.checkInput && params?.messages) {
|
|
54
|
+
const messages = params.messages;
|
|
55
|
+
const userMessages = messages.filter((m) => m.role === "user");
|
|
56
|
+
const lastUserMessage = userMessages[userMessages.length - 1];
|
|
57
|
+
if (lastUserMessage?.content) {
|
|
58
|
+
const result = await ceClient.check(lastUserMessage.content, {
|
|
59
|
+
direction: "prompt",
|
|
60
|
+
jurisdiction: opts.jurisdiction
|
|
61
|
+
});
|
|
62
|
+
if (!result.allowed && opts.blockOnViolation) {
|
|
63
|
+
throw new ComplianceError(
|
|
64
|
+
`Compliance violation detected: ${result.violations.map((v) => v.ruleId).join(", ")}`,
|
|
65
|
+
result.violations
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return originalCreate.apply(this, args);
|
|
71
|
+
};
|
|
72
|
+
return openaiClient;
|
|
73
|
+
}
|
|
74
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
75
|
+
0 && (module.exports = {
|
|
76
|
+
ComplianceError,
|
|
77
|
+
withCompliance
|
|
78
|
+
});
|
|
79
|
+
//# sourceMappingURL=openai-middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/openai-middleware.ts"],"sourcesContent":["/**\n * ComplyEdge OpenAI Middleware\n *\n * Wraps an OpenAI client to run compliance checks on messages\n * before they are sent to the model.\n *\n * Usage:\n * import OpenAI from \"openai\";\n * import { ComplyEdgeClient } from \"@complyedge/sdk\";\n * import { withCompliance } from \"@complyedge/sdk/openai-middleware\";\n *\n * const ce = new ComplyEdgeClient({ apiKey: \"...\" });\n * const openai = withCompliance(new OpenAI(), ce);\n * // Now openai.chat.completions.create() runs compliance checks automatically\n */\n\nimport type { ComplyEdgeClient } from \"./client\";\nimport type { ComplianceViolation } from \"./types\";\n\nexport class ComplianceError extends Error {\n public violations: ComplianceViolation[];\n\n constructor(message: string, violations: ComplianceViolation[]) {\n super(message);\n this.name = \"ComplianceError\";\n this.violations = violations;\n }\n}\n\n/**\n * Wrap an OpenAI client with ComplyEdge compliance checks.\n * The returned object proxies chat.completions.create() to check\n * user messages before sending to OpenAI.\n */\nexport function withCompliance<T extends Record<string, unknown>>(\n openaiClient: T,\n ceClient: ComplyEdgeClient,\n options?: {\n checkInput?: boolean;\n checkOutput?: boolean;\n jurisdiction?: string;\n blockOnViolation?: boolean;\n }\n): T {\n const opts = {\n checkInput: true,\n checkOutput: false,\n blockOnViolation: true,\n ...options,\n };\n\n const chat = openaiClient.chat as Record<string, unknown> | undefined;\n if (!chat || !chat.completions) {\n return openaiClient; // Not an OpenAI-shaped client, return as-is\n }\n\n const completions = chat.completions as Record<string, unknown>;\n const originalCreate = completions.create as (...args: unknown[]) => Promise<unknown>;\n\n if (typeof originalCreate !== \"function\") {\n return openaiClient;\n }\n\n completions.create = async function (...args: unknown[]) {\n const params = args[0] as Record<string, unknown> | undefined;\n\n if (opts.checkInput && params?.messages) {\n const messages = params.messages as Array<{ role: string; content: string }>;\n const userMessages = messages.filter((m) => m.role === \"user\");\n const lastUserMessage = userMessages[userMessages.length - 1];\n\n if (lastUserMessage?.content) {\n const result = await ceClient.check(lastUserMessage.content, {\n direction: \"prompt\",\n jurisdiction: opts.jurisdiction,\n });\n\n if (!result.allowed && opts.blockOnViolation) {\n throw new ComplianceError(\n `Compliance violation detected: ${result.violations.map((v) => v.ruleId).join(\", \")}`,\n result.violations\n );\n }\n }\n }\n\n return originalCreate.apply(this, args);\n };\n\n return openaiClient;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAClC;AAAA,EAEP,YAAY,SAAiB,YAAmC;AAC9D,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAOO,SAAS,eACd,cACA,UACA,SAMG;AACH,QAAM,OAAO;AAAA,IACX,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,kBAAkB;AAAA,IAClB,GAAG;AAAA,EACL;AAEA,QAAM,OAAO,aAAa;AAC1B,MAAI,CAAC,QAAQ,CAAC,KAAK,aAAa;AAC9B,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,KAAK;AACzB,QAAM,iBAAiB,YAAY;AAEnC,MAAI,OAAO,mBAAmB,YAAY;AACxC,WAAO;AAAA,EACT;AAEA,cAAY,SAAS,kBAAmB,MAAiB;AACvD,UAAM,SAAS,KAAK,CAAC;AAErB,QAAI,KAAK,cAAc,QAAQ,UAAU;AACvC,YAAM,WAAW,OAAO;AACxB,YAAM,eAAe,SAAS,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM;AAC7D,YAAM,kBAAkB,aAAa,aAAa,SAAS,CAAC;AAE5D,UAAI,iBAAiB,SAAS;AAC5B,cAAM,SAAS,MAAM,SAAS,MAAM,gBAAgB,SAAS;AAAA,UAC3D,WAAW;AAAA,UACX,cAAc,KAAK;AAAA,QACrB,CAAC;AAED,YAAI,CAAC,OAAO,WAAW,KAAK,kBAAkB;AAC5C,gBAAM,IAAI;AAAA,YACR,kCAAkC,OAAO,WAAW,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;AAAA,YACnF,OAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO,eAAe,MAAM,MAAM,IAAI;AAAA,EACxC;AAEA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|