@complyedge/sdk 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/README.md +25 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +40 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +37 -6
- package/dist/index.mjs.map +1 -1
- package/dist/openai-middleware.d.mts +24 -1
- package/dist/openai-middleware.d.ts +24 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -14,6 +14,35 @@ numbers are deliberately not kept level between the two — they are separate
|
|
|
14
14
|
implementations with different capability surfaces, so matching numbers would
|
|
15
15
|
imply a parity that does not exist.
|
|
16
16
|
|
|
17
|
+
## [Unreleased]
|
|
18
|
+
|
|
19
|
+
## [0.2.4] - 2026-09-16
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
- `region: "us" | "eu"` config option and `COMPLYEDGE_REGION` environment
|
|
23
|
+
variable. The client now picks the API host from the key prefix
|
|
24
|
+
(`ce_eu_` -> `https://eu.api.complyedge.io`, `ce_` -> `https://api.complyedge.io`)
|
|
25
|
+
when neither `baseUrl` nor `COMPLYEDGE_API_URL` is set. Exported helpers:
|
|
26
|
+
`resolveBaseUrl`, `regionFromApiKey`, `REGION_BASE_URLS`, type `Region`.
|
|
27
|
+
Precedence: `baseUrl` > `COMPLYEDGE_API_URL` > `region` / `COMPLYEDGE_REGION`
|
|
28
|
+
> key prefix > US. Existing configurations resolve exactly as before.
|
|
29
|
+
|
|
30
|
+
## [0.2.3] - 2026-08-20
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
- Package-map capability table (CE-vs-CE only): offline vs hosted, Rego/OPA,
|
|
34
|
+
Article 12, bundled corpus, ESM/CJS, MCP. Named competitor comparisons stay
|
|
35
|
+
gated — they need an explicit messaging decision against the no-first/only
|
|
36
|
+
doctrine.
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
- Release-path fact: publishes still authenticate with a long-lived npm
|
|
40
|
+
credential. The 0.2.2 changelog entry that claimed OIDC Trusted Publishing
|
|
41
|
+
described an attempt that was reverted — `repository.url` names the public
|
|
42
|
+
repository while the release workflow runs in the private platform one, and
|
|
43
|
+
npm matches those two when authenticating. Provenance stays unavailable
|
|
44
|
+
until that layout changes.
|
|
45
|
+
|
|
17
46
|
## [0.2.2] - 2026-08-20
|
|
18
47
|
|
|
19
48
|
### Changed
|
|
@@ -51,5 +80,7 @@ imply a parity that does not exist.
|
|
|
51
80
|
|
|
52
81
|
Released before this changelog existed. See the repository history.
|
|
53
82
|
|
|
83
|
+
[0.2.4]: https://www.npmjs.com/package/@complyedge/sdk/v/0.2.4
|
|
84
|
+
[0.2.3]: https://www.npmjs.com/package/@complyedge/sdk/v/0.2.3
|
|
54
85
|
[0.2.2]: https://www.npmjs.com/package/@complyedge/sdk/v/0.2.2
|
|
55
86
|
[0.2.1]: https://www.npmjs.com/package/@complyedge/sdk/v/0.2.1
|
package/README.md
CHANGED
|
@@ -25,6 +25,18 @@ The SDK works in both ESM and CommonJS projects; no bundler-specific setup is re
|
|
|
25
25
|
- [`complyedge` on PyPI](https://pypi.org/project/complyedge/) is the Python SDK with the same enforcement API.
|
|
26
26
|
- [Documentation](https://www.complyedge.io/docs) covers the hosted API; the [trust portal](https://trust.complyedge.io) covers security and reliability information.
|
|
27
27
|
|
|
28
|
+
| | `@complyedge/sdk` | `trustlint` | `@complyedge/mcp` |
|
|
29
|
+
|---|:-:|:-:|:-:|
|
|
30
|
+
| Runs offline, no API key | ✗ | ✓ | ✓ |
|
|
31
|
+
| Rego / OPA evaluation | ✓ | ✗ | ✗ |
|
|
32
|
+
| Article 12 audit trail | ✓ | ✗ | ✗ |
|
|
33
|
+
| Bundled 64-rule corpus | ✗ | ✓ | ✓ |
|
|
34
|
+
| Temporal / effective-date rules | ✗ | ✗ | ✗ |
|
|
35
|
+
| ESM + CommonJS | ✓ | ✓ | ESM only |
|
|
36
|
+
| MCP host integration | ✗ | ✗ | ✓ |
|
|
37
|
+
|
|
38
|
+
Temporal / effective-date evaluation lives in the Python engine only. A shared version number across npm and PyPI is not a parity claim.
|
|
39
|
+
|
|
28
40
|
## Version policy
|
|
29
41
|
|
|
30
42
|
The TypeScript SDK and Python `complyedge` package have independent semantic versions. A version number does not imply feature parity across languages; each release documents and tests its own supported API surface.
|
|
@@ -61,10 +73,22 @@ const ce = new ComplyEdgeClient({
|
|
|
61
73
|
jurisdiction: "EU", // default: "EU"
|
|
62
74
|
agentId: "support-bot", // default: "default"
|
|
63
75
|
timeout: 30_000, // ms, default: 30_000
|
|
64
|
-
|
|
76
|
+
region: "eu", // "us" | "eu"; default: read from the key prefix (ce_eu_ -> eu)
|
|
77
|
+
baseUrl: "https://api.complyedge.io", // or COMPLYEDGE_API_URL; overrides region
|
|
65
78
|
});
|
|
66
79
|
```
|
|
67
80
|
|
|
81
|
+
### Regions
|
|
82
|
+
|
|
83
|
+
ComplyEdge runs one independent stack per region — US (`api.complyedge.io`)
|
|
84
|
+
and EU (`eu.api.complyedge.io`, Frankfurt). Your tenant, its audit trail and
|
|
85
|
+
its API keys live in exactly one of them. Keys issued by the EU stack start
|
|
86
|
+
with `ce_eu_`, US keys with `ce_`; the client reads the prefix and picks the
|
|
87
|
+
host, so `region` is only needed to override it. Precedence, highest first:
|
|
88
|
+
`baseUrl` / `COMPLYEDGE_API_URL`, then `region` / `COMPLYEDGE_REGION`, then
|
|
89
|
+
the key prefix, then US. A key presented to the other region's stack is
|
|
90
|
+
refused with `401 {"error":"wrong_region","use":"<host>"}` before any lookup.
|
|
91
|
+
|
|
68
92
|
## `check(text, context?)`
|
|
69
93
|
|
|
70
94
|
Calls `POST /v1/check`, the deterministic OPA hot path. Returns:
|
package/dist/index.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { d as ComplianceContext, ComplianceError, e as ComplianceResult, f as ComplianceViolation, C as ComplyEdgeClient, c as ComplyEdgeConfig, P as PreDeploymentInput, i as PreDeploymentResult, R as REGION_BASE_URLS, b as Region, h as SensitivityDetection, g as SensitivityResult, S as SeverityLevel, r as regionFromApiKey, a as resolveBaseUrl, withCompliance } from './openai-middleware.mjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { d as ComplianceContext, ComplianceError, e as ComplianceResult, f as ComplianceViolation, C as ComplyEdgeClient, c as ComplyEdgeConfig, P as PreDeploymentInput, i as PreDeploymentResult, R as REGION_BASE_URLS, b as Region, h as SensitivityDetection, g as SensitivityResult, S as SeverityLevel, r as regionFromApiKey, a as resolveBaseUrl, withCompliance } from './openai-middleware.js';
|
package/dist/index.js
CHANGED
|
@@ -32,24 +32,55 @@ var src_exports = {};
|
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
ComplianceError: () => ComplianceError,
|
|
34
34
|
ComplyEdgeClient: () => ComplyEdgeClient,
|
|
35
|
+
REGION_BASE_URLS: () => REGION_BASE_URLS,
|
|
36
|
+
regionFromApiKey: () => regionFromApiKey,
|
|
37
|
+
resolveBaseUrl: () => resolveBaseUrl,
|
|
35
38
|
withCompliance: () => withCompliance
|
|
36
39
|
});
|
|
37
40
|
module.exports = __toCommonJS(src_exports);
|
|
38
41
|
|
|
39
42
|
// src/client.ts
|
|
40
43
|
var import_axios = __toESM(require("axios"));
|
|
41
|
-
var
|
|
42
|
-
|
|
44
|
+
var REGION_BASE_URLS = {
|
|
45
|
+
us: "https://api.complyedge.io",
|
|
46
|
+
eu: "https://eu.api.complyedge.io"
|
|
47
|
+
};
|
|
48
|
+
function regionFromApiKey(apiKey) {
|
|
49
|
+
if (!apiKey) return void 0;
|
|
50
|
+
if (apiKey.startsWith("ce_eu_")) return "eu";
|
|
51
|
+
if (apiKey.startsWith("ce_")) return "us";
|
|
52
|
+
return void 0;
|
|
53
|
+
}
|
|
54
|
+
function resolveBaseUrl(opts) {
|
|
55
|
+
if (opts.baseUrl) return opts.baseUrl.replace(/\/+$/, "");
|
|
56
|
+
const envUrl = process.env.COMPLYEDGE_API_URL;
|
|
57
|
+
if (envUrl) return envUrl.replace(/\/+$/, "");
|
|
58
|
+
const chosen = (opts.region || process.env.COMPLYEDGE_REGION || "").trim().toLowerCase();
|
|
59
|
+
if (chosen) {
|
|
60
|
+
if (!(chosen in REGION_BASE_URLS)) {
|
|
61
|
+
throw new Error(
|
|
62
|
+
`Unknown ComplyEdge region "${chosen}"; expected one of ${Object.keys(REGION_BASE_URLS).join(", ")}`
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
return REGION_BASE_URLS[chosen];
|
|
66
|
+
}
|
|
67
|
+
return REGION_BASE_URLS[regionFromApiKey(opts.apiKey) || "us"];
|
|
68
|
+
}
|
|
69
|
+
var SDK_VERSION = "0.2.4";
|
|
43
70
|
var ComplyEdgeClient = class {
|
|
44
71
|
http;
|
|
45
72
|
agentId;
|
|
46
73
|
jurisdiction;
|
|
47
74
|
constructor(config) {
|
|
48
|
-
const baseUrl =
|
|
75
|
+
const baseUrl = resolveBaseUrl({
|
|
76
|
+
apiKey: config.apiKey,
|
|
77
|
+
baseUrl: config.baseUrl,
|
|
78
|
+
region: config.region
|
|
79
|
+
});
|
|
49
80
|
this.agentId = config.agentId || "default";
|
|
50
81
|
this.jurisdiction = config.jurisdiction;
|
|
51
82
|
this.http = import_axios.default.create({
|
|
52
|
-
baseURL: baseUrl
|
|
83
|
+
baseURL: baseUrl,
|
|
53
84
|
timeout: config.timeout || 3e4,
|
|
54
85
|
headers: {
|
|
55
86
|
Authorization: `Bearer ${config.apiKey}`,
|
|
@@ -83,7 +114,7 @@ var ComplyEdgeClient = class {
|
|
|
83
114
|
});
|
|
84
115
|
const data = response.data;
|
|
85
116
|
const processingTimeMs = Date.now() - start;
|
|
86
|
-
const allowed = data.allowed
|
|
117
|
+
const allowed = data.allowed === true;
|
|
87
118
|
return {
|
|
88
119
|
eventId: data.event_id || "",
|
|
89
120
|
allowed,
|
|
@@ -101,7 +132,7 @@ var ComplyEdgeClient = class {
|
|
|
101
132
|
evaluatedRules: data.evaluated_rules || [],
|
|
102
133
|
enginePath: data.engine_path || "opa",
|
|
103
134
|
opaLatencyMs: data.opa_latency_ms,
|
|
104
|
-
auditLogged: data.audit_logged
|
|
135
|
+
auditLogged: data.audit_logged === true,
|
|
105
136
|
textHash: data.text_hash || "",
|
|
106
137
|
timestamp: data.timestamp,
|
|
107
138
|
jurisdiction,
|
|
@@ -264,6 +295,9 @@ function extractCompletionText(response) {
|
|
|
264
295
|
0 && (module.exports = {
|
|
265
296
|
ComplianceError,
|
|
266
297
|
ComplyEdgeClient,
|
|
298
|
+
REGION_BASE_URLS,
|
|
299
|
+
regionFromApiKey,
|
|
300
|
+
resolveBaseUrl,
|
|
267
301
|
withCompliance
|
|
268
302
|
});
|
|
269
303
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +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\";\n// Keep in sync with package.json. Hardcoding it here meant the User-Agent\n// silently reported a stale version after every release bump, which is the\n// one field support uses to tell which client a customer is actually on.\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 // Pass the caller's direction through untouched. This previously mapped\n // \"prompt\" to \"input\", a value the API's DirectionType enum does not\n // accept (\"prompt\" | \"output\"), so every input check 422'd and the\n // wrapped call threw. The SDK's own ComplianceContext type has always\n // declared the correct union; only this line disagreed with it.\n direction: context?.direction ?? \"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 textHash: data.text_hash || \"\",\n timestamp: data.timestamp,\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 // \"EU\" matches the Python SDK and the server default. This read \"US\",\n // so the two SDKs enforced different rule sets for identical code.\n const jurisdiction = context?.jurisdiction || this.jurisdiction || \"EU\";\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: unknown }>;\n // Check EVERY user turn, not just the last one. A violation in an earlier\n // message is still sent to the model verbatim, so checking only the tail\n // left the majority of a multi-turn conversation unenforced.\n for (const message of messages) {\n if (message.role !== \"user\") continue;\n for (const text of extractText(message.content)) {\n const result = await ceClient.check(text, {\n direction: \"prompt\",\n jurisdiction: opts.jurisdiction,\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\n const response = await originalCreate.apply(this, args);\n\n if (opts.checkOutput) {\n // Previously declared in the options type and never read, so the README's\n // \"runs compliance checks automatically\" was half true: inputs were\n // checked, model output never was, silently.\n for (const text of extractCompletionText(response)) {\n const result = await ceClient.check(text, {\n direction: \"output\",\n jurisdiction: opts.jurisdiction,\n });\n if (!result.allowed && opts.blockOnViolation) {\n throw new ComplianceError(\n `Compliance violation in model output: ${result.violations.map((v) => v.ruleId).join(\", \")}`,\n result.violations\n );\n }\n }\n }\n\n return response;\n };\n\n return openaiClient;\n}\n\n/**\n * Pull checkable strings out of a message `content` field.\n *\n * OpenAI accepts either a plain string or an array of typed content parts.\n * The array form was previously passed to the API as a non-string and 422'd,\n * so multimodal callers could not use the middleware at all.\n */\nfunction extractText(content: unknown): string[] {\n if (typeof content === \"string\") {\n return content.trim() ? [content] : [];\n }\n if (Array.isArray(content)) {\n return content\n .map((part) => {\n if (typeof part === \"string\") return part;\n const p = part as Record<string, unknown> | null;\n return p && typeof p.text === \"string\" ? p.text : \"\";\n })\n .filter((t) => t.trim().length > 0);\n }\n return [];\n}\n\n/** Pull assistant message text out of a chat completion response. */\nfunction extractCompletionText(response: unknown): string[] {\n const r = response as { choices?: Array<{ message?: { content?: unknown } }> } | null;\n if (!r?.choices) return [];\n return r.choices.flatMap((choice) => extractText(choice?.message?.content));\n}\n"],"mappings":"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","names":["axios"]}
|
|
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 {\n ComplyEdgeClient,\n REGION_BASE_URLS,\n regionFromApiKey,\n resolveBaseUrl,\n} from \"./client\";\nexport type { Region } 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\n// ComplyEdge runs one independent stack per region. A tenant lives in exactly\n// one of them, and its API keys are only valid there. The key itself says\n// which: `ce_` -> US (api.complyedge.io), `ce_eu_` -> EU (eu.api.complyedge.io).\nexport type Region = \"us\" | \"eu\";\n\nexport const REGION_BASE_URLS: Record<Region, string> = {\n us: \"https://api.complyedge.io\",\n eu: \"https://eu.api.complyedge.io\",\n};\n\n/** Region an API key was issued in, read from its prefix; undefined if unknown. */\nexport function regionFromApiKey(apiKey?: string): Region | undefined {\n if (!apiKey) return undefined;\n // Longest prefix first: `ce_eu_` also starts with `ce_`.\n if (apiKey.startsWith(\"ce_eu_\")) return \"eu\";\n if (apiKey.startsWith(\"ce_\")) return \"us\";\n return undefined;\n}\n\n/**\n * Pick the API host. Precedence, highest first:\n * 1. `baseUrl` option\n * 2. `COMPLYEDGE_API_URL` environment variable\n * 3. `region` option, else `COMPLYEDGE_REGION` environment variable\n * 4. the region encoded in the API key prefix (`ce_eu_` -> EU)\n * 5. US\n */\nexport function resolveBaseUrl(opts: {\n apiKey?: string;\n baseUrl?: string;\n region?: Region;\n}): string {\n if (opts.baseUrl) return opts.baseUrl.replace(/\\/+$/, \"\");\n const envUrl = process.env.COMPLYEDGE_API_URL;\n if (envUrl) return envUrl.replace(/\\/+$/, \"\");\n const chosen = (opts.region || process.env.COMPLYEDGE_REGION || \"\").trim().toLowerCase();\n if (chosen) {\n if (!(chosen in REGION_BASE_URLS)) {\n throw new Error(\n `Unknown ComplyEdge region \"${chosen}\"; expected one of ${Object.keys(REGION_BASE_URLS).join(\", \")}`\n );\n }\n return REGION_BASE_URLS[chosen as Region];\n }\n return REGION_BASE_URLS[regionFromApiKey(opts.apiKey) || \"us\"];\n}\n// Keep in sync with package.json. Hardcoding it here meant the User-Agent\n// silently reported a stale version after every release bump, which is the\n// one field support uses to tell which client a customer is actually on.\nconst SDK_VERSION = \"0.2.4\";\n\nexport class ComplyEdgeClient {\n private http: AxiosInstance;\n private agentId: string;\n private jurisdiction?: string;\n\n constructor(config: ComplyEdgeConfig) {\n const baseUrl = resolveBaseUrl({\n apiKey: config.apiKey,\n baseUrl: config.baseUrl,\n region: config.region,\n });\n\n this.agentId = config.agentId || \"default\";\n this.jurisdiction = config.jurisdiction;\n\n this.http = axios.create({\n baseURL: baseUrl,\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 // Pass the caller's direction through untouched. This previously mapped\n // \"prompt\" to \"input\", a value the API's DirectionType enum does not\n // accept (\"prompt\" | \"output\"), so every input check 422'd and the\n // wrapped call threw. The SDK's own ComplianceContext type has always\n // declared the correct union; only this line disagreed with it.\n direction: context?.direction ?? \"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 // Missing `allowed` is a block. `!== false` treated a truncated 200 as a pass.\n const allowed = data.allowed === true;\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 === true,\n textHash: data.text_hash || \"\",\n timestamp: data.timestamp,\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 // \"EU\" matches the Python SDK and the server default. This read \"US\",\n // so the two SDKs enforced different rule sets for identical code.\n const jurisdiction = context?.jurisdiction || this.jurisdiction || \"EU\";\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: unknown }>;\n // Check EVERY user turn, not just the last one. A violation in an earlier\n // message is still sent to the model verbatim, so checking only the tail\n // left the majority of a multi-turn conversation unenforced.\n for (const message of messages) {\n if (message.role !== \"user\") continue;\n for (const text of extractText(message.content)) {\n const result = await ceClient.check(text, {\n direction: \"prompt\",\n jurisdiction: opts.jurisdiction,\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\n const response = await originalCreate.apply(this, args);\n\n if (opts.checkOutput) {\n // Previously declared in the options type and never read, so the README's\n // \"runs compliance checks automatically\" was half true: inputs were\n // checked, model output never was, silently.\n for (const text of extractCompletionText(response)) {\n const result = await ceClient.check(text, {\n direction: \"output\",\n jurisdiction: opts.jurisdiction,\n });\n if (!result.allowed && opts.blockOnViolation) {\n throw new ComplianceError(\n `Compliance violation in model output: ${result.violations.map((v) => v.ruleId).join(\", \")}`,\n result.violations\n );\n }\n }\n }\n\n return response;\n };\n\n return openaiClient;\n}\n\n/**\n * Pull checkable strings out of a message `content` field.\n *\n * OpenAI accepts either a plain string or an array of typed content parts.\n * The array form was previously passed to the API as a non-string and 422'd,\n * so multimodal callers could not use the middleware at all.\n */\nfunction extractText(content: unknown): string[] {\n if (typeof content === \"string\") {\n return content.trim() ? [content] : [];\n }\n if (Array.isArray(content)) {\n return content\n .map((part) => {\n if (typeof part === \"string\") return part;\n const p = part as Record<string, unknown> | null;\n return p && typeof p.text === \"string\" ? p.text : \"\";\n })\n .filter((t) => t.trim().length > 0);\n }\n return [];\n}\n\n/** Pull assistant message text out of a chat completion response. */\nfunction extractCompletionText(response: unknown): string[] {\n const r = response as { choices?: Array<{ message?: { content?: unknown } }> } | null;\n if (!r?.choices) return [];\n return r.choices.flatMap((choice) => extractText(choice?.message?.content));\n}\n"],"mappings":"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","names":["axios"]}
|
package/dist/index.mjs
CHANGED
|
@@ -5,18 +5,46 @@ import {
|
|
|
5
5
|
|
|
6
6
|
// src/client.ts
|
|
7
7
|
import axios from "axios";
|
|
8
|
-
var
|
|
9
|
-
|
|
8
|
+
var REGION_BASE_URLS = {
|
|
9
|
+
us: "https://api.complyedge.io",
|
|
10
|
+
eu: "https://eu.api.complyedge.io"
|
|
11
|
+
};
|
|
12
|
+
function regionFromApiKey(apiKey) {
|
|
13
|
+
if (!apiKey) return void 0;
|
|
14
|
+
if (apiKey.startsWith("ce_eu_")) return "eu";
|
|
15
|
+
if (apiKey.startsWith("ce_")) return "us";
|
|
16
|
+
return void 0;
|
|
17
|
+
}
|
|
18
|
+
function resolveBaseUrl(opts) {
|
|
19
|
+
if (opts.baseUrl) return opts.baseUrl.replace(/\/+$/, "");
|
|
20
|
+
const envUrl = process.env.COMPLYEDGE_API_URL;
|
|
21
|
+
if (envUrl) return envUrl.replace(/\/+$/, "");
|
|
22
|
+
const chosen = (opts.region || process.env.COMPLYEDGE_REGION || "").trim().toLowerCase();
|
|
23
|
+
if (chosen) {
|
|
24
|
+
if (!(chosen in REGION_BASE_URLS)) {
|
|
25
|
+
throw new Error(
|
|
26
|
+
`Unknown ComplyEdge region "${chosen}"; expected one of ${Object.keys(REGION_BASE_URLS).join(", ")}`
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
return REGION_BASE_URLS[chosen];
|
|
30
|
+
}
|
|
31
|
+
return REGION_BASE_URLS[regionFromApiKey(opts.apiKey) || "us"];
|
|
32
|
+
}
|
|
33
|
+
var SDK_VERSION = "0.2.4";
|
|
10
34
|
var ComplyEdgeClient = class {
|
|
11
35
|
http;
|
|
12
36
|
agentId;
|
|
13
37
|
jurisdiction;
|
|
14
38
|
constructor(config) {
|
|
15
|
-
const baseUrl =
|
|
39
|
+
const baseUrl = resolveBaseUrl({
|
|
40
|
+
apiKey: config.apiKey,
|
|
41
|
+
baseUrl: config.baseUrl,
|
|
42
|
+
region: config.region
|
|
43
|
+
});
|
|
16
44
|
this.agentId = config.agentId || "default";
|
|
17
45
|
this.jurisdiction = config.jurisdiction;
|
|
18
46
|
this.http = axios.create({
|
|
19
|
-
baseURL: baseUrl
|
|
47
|
+
baseURL: baseUrl,
|
|
20
48
|
timeout: config.timeout || 3e4,
|
|
21
49
|
headers: {
|
|
22
50
|
Authorization: `Bearer ${config.apiKey}`,
|
|
@@ -50,7 +78,7 @@ var ComplyEdgeClient = class {
|
|
|
50
78
|
});
|
|
51
79
|
const data = response.data;
|
|
52
80
|
const processingTimeMs = Date.now() - start;
|
|
53
|
-
const allowed = data.allowed
|
|
81
|
+
const allowed = data.allowed === true;
|
|
54
82
|
return {
|
|
55
83
|
eventId: data.event_id || "",
|
|
56
84
|
allowed,
|
|
@@ -68,7 +96,7 @@ var ComplyEdgeClient = class {
|
|
|
68
96
|
evaluatedRules: data.evaluated_rules || [],
|
|
69
97
|
enginePath: data.engine_path || "opa",
|
|
70
98
|
opaLatencyMs: data.opa_latency_ms,
|
|
71
|
-
auditLogged: data.audit_logged
|
|
99
|
+
auditLogged: data.audit_logged === true,
|
|
72
100
|
textHash: data.text_hash || "",
|
|
73
101
|
timestamp: data.timestamp,
|
|
74
102
|
jurisdiction,
|
|
@@ -147,6 +175,9 @@ var ComplyEdgeClient = class {
|
|
|
147
175
|
export {
|
|
148
176
|
ComplianceError,
|
|
149
177
|
ComplyEdgeClient,
|
|
178
|
+
REGION_BASE_URLS,
|
|
179
|
+
regionFromApiKey,
|
|
180
|
+
resolveBaseUrl,
|
|
150
181
|
withCompliance
|
|
151
182
|
};
|
|
152
183
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +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\";\n// Keep in sync with package.json. Hardcoding it here meant the User-Agent\n// silently reported a stale version after every release bump, which is the\n// one field support uses to tell which client a customer is actually on.\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 // Pass the caller's direction through untouched. This previously mapped\n // \"prompt\" to \"input\", a value the API's DirectionType enum does not\n // accept (\"prompt\" | \"output\"), so every input check 422'd and the\n // wrapped call threw. The SDK's own ComplianceContext type has always\n // declared the correct union; only this line disagreed with it.\n direction: context?.direction ?? \"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 textHash: data.text_hash || \"\",\n timestamp: data.timestamp,\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 // \"EU\" matches the Python SDK and the server default. This read \"US\",\n // so the two SDKs enforced different rule sets for identical code.\n const jurisdiction = context?.jurisdiction || this.jurisdiction || \"EU\";\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":[]}
|
|
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\n// ComplyEdge runs one independent stack per region. A tenant lives in exactly\n// one of them, and its API keys are only valid there. The key itself says\n// which: `ce_` -> US (api.complyedge.io), `ce_eu_` -> EU (eu.api.complyedge.io).\nexport type Region = \"us\" | \"eu\";\n\nexport const REGION_BASE_URLS: Record<Region, string> = {\n us: \"https://api.complyedge.io\",\n eu: \"https://eu.api.complyedge.io\",\n};\n\n/** Region an API key was issued in, read from its prefix; undefined if unknown. */\nexport function regionFromApiKey(apiKey?: string): Region | undefined {\n if (!apiKey) return undefined;\n // Longest prefix first: `ce_eu_` also starts with `ce_`.\n if (apiKey.startsWith(\"ce_eu_\")) return \"eu\";\n if (apiKey.startsWith(\"ce_\")) return \"us\";\n return undefined;\n}\n\n/**\n * Pick the API host. Precedence, highest first:\n * 1. `baseUrl` option\n * 2. `COMPLYEDGE_API_URL` environment variable\n * 3. `region` option, else `COMPLYEDGE_REGION` environment variable\n * 4. the region encoded in the API key prefix (`ce_eu_` -> EU)\n * 5. US\n */\nexport function resolveBaseUrl(opts: {\n apiKey?: string;\n baseUrl?: string;\n region?: Region;\n}): string {\n if (opts.baseUrl) return opts.baseUrl.replace(/\\/+$/, \"\");\n const envUrl = process.env.COMPLYEDGE_API_URL;\n if (envUrl) return envUrl.replace(/\\/+$/, \"\");\n const chosen = (opts.region || process.env.COMPLYEDGE_REGION || \"\").trim().toLowerCase();\n if (chosen) {\n if (!(chosen in REGION_BASE_URLS)) {\n throw new Error(\n `Unknown ComplyEdge region \"${chosen}\"; expected one of ${Object.keys(REGION_BASE_URLS).join(\", \")}`\n );\n }\n return REGION_BASE_URLS[chosen as Region];\n }\n return REGION_BASE_URLS[regionFromApiKey(opts.apiKey) || \"us\"];\n}\n// Keep in sync with package.json. Hardcoding it here meant the User-Agent\n// silently reported a stale version after every release bump, which is the\n// one field support uses to tell which client a customer is actually on.\nconst SDK_VERSION = \"0.2.4\";\n\nexport class ComplyEdgeClient {\n private http: AxiosInstance;\n private agentId: string;\n private jurisdiction?: string;\n\n constructor(config: ComplyEdgeConfig) {\n const baseUrl = resolveBaseUrl({\n apiKey: config.apiKey,\n baseUrl: config.baseUrl,\n region: config.region,\n });\n\n this.agentId = config.agentId || \"default\";\n this.jurisdiction = config.jurisdiction;\n\n this.http = axios.create({\n baseURL: baseUrl,\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 // Pass the caller's direction through untouched. This previously mapped\n // \"prompt\" to \"input\", a value the API's DirectionType enum does not\n // accept (\"prompt\" | \"output\"), so every input check 422'd and the\n // wrapped call threw. The SDK's own ComplianceContext type has always\n // declared the correct union; only this line disagreed with it.\n direction: context?.direction ?? \"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 // Missing `allowed` is a block. `!== false` treated a truncated 200 as a pass.\n const allowed = data.allowed === true;\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 === true,\n textHash: data.text_hash || \"\",\n timestamp: data.timestamp,\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 // \"EU\" matches the Python SDK and the server default. This read \"US\",\n // so the two SDKs enforced different rule sets for identical code.\n const jurisdiction = context?.jurisdiction || this.jurisdiction || \"EU\";\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":[]}
|
|
@@ -95,7 +95,13 @@ interface PreDeploymentResult {
|
|
|
95
95
|
}
|
|
96
96
|
interface ComplyEdgeConfig {
|
|
97
97
|
apiKey: string;
|
|
98
|
+
/** Overrides region and key inference. Also settable via COMPLYEDGE_API_URL. */
|
|
98
99
|
baseUrl?: string;
|
|
100
|
+
/**
|
|
101
|
+
* "us" | "eu". Defaults to the region encoded in the API key prefix
|
|
102
|
+
* (`ce_eu_` -> EU), else US. Also settable via COMPLYEDGE_REGION.
|
|
103
|
+
*/
|
|
104
|
+
region?: "us" | "eu";
|
|
99
105
|
agentId?: string;
|
|
100
106
|
jurisdiction?: string;
|
|
101
107
|
timeout?: number;
|
|
@@ -105,6 +111,23 @@ interface ComplyEdgeConfig {
|
|
|
105
111
|
* ComplyEdge TypeScript SDK — Client
|
|
106
112
|
*/
|
|
107
113
|
|
|
114
|
+
type Region = "us" | "eu";
|
|
115
|
+
declare const REGION_BASE_URLS: Record<Region, string>;
|
|
116
|
+
/** Region an API key was issued in, read from its prefix; undefined if unknown. */
|
|
117
|
+
declare function regionFromApiKey(apiKey?: string): Region | undefined;
|
|
118
|
+
/**
|
|
119
|
+
* Pick the API host. Precedence, highest first:
|
|
120
|
+
* 1. `baseUrl` option
|
|
121
|
+
* 2. `COMPLYEDGE_API_URL` environment variable
|
|
122
|
+
* 3. `region` option, else `COMPLYEDGE_REGION` environment variable
|
|
123
|
+
* 4. the region encoded in the API key prefix (`ce_eu_` -> EU)
|
|
124
|
+
* 5. US
|
|
125
|
+
*/
|
|
126
|
+
declare function resolveBaseUrl(opts: {
|
|
127
|
+
apiKey?: string;
|
|
128
|
+
baseUrl?: string;
|
|
129
|
+
region?: Region;
|
|
130
|
+
}): string;
|
|
108
131
|
declare class ComplyEdgeClient {
|
|
109
132
|
private http;
|
|
110
133
|
private agentId;
|
|
@@ -164,4 +187,4 @@ declare function withCompliance<T extends Record<string, unknown>>(openaiClient:
|
|
|
164
187
|
blockOnViolation?: boolean;
|
|
165
188
|
}): T;
|
|
166
189
|
|
|
167
|
-
export { ComplyEdgeClient as C, ComplianceError, type PreDeploymentInput as P, type SeverityLevel as S, type ComplyEdgeConfig as
|
|
190
|
+
export { ComplyEdgeClient as C, ComplianceError, type PreDeploymentInput as P, REGION_BASE_URLS as R, type SeverityLevel as S, resolveBaseUrl as a, type Region as b, type ComplyEdgeConfig as c, type ComplianceContext as d, type ComplianceResult as e, type ComplianceViolation as f, type SensitivityResult as g, type SensitivityDetection as h, type PreDeploymentResult as i, regionFromApiKey as r, withCompliance };
|
|
@@ -95,7 +95,13 @@ interface PreDeploymentResult {
|
|
|
95
95
|
}
|
|
96
96
|
interface ComplyEdgeConfig {
|
|
97
97
|
apiKey: string;
|
|
98
|
+
/** Overrides region and key inference. Also settable via COMPLYEDGE_API_URL. */
|
|
98
99
|
baseUrl?: string;
|
|
100
|
+
/**
|
|
101
|
+
* "us" | "eu". Defaults to the region encoded in the API key prefix
|
|
102
|
+
* (`ce_eu_` -> EU), else US. Also settable via COMPLYEDGE_REGION.
|
|
103
|
+
*/
|
|
104
|
+
region?: "us" | "eu";
|
|
99
105
|
agentId?: string;
|
|
100
106
|
jurisdiction?: string;
|
|
101
107
|
timeout?: number;
|
|
@@ -105,6 +111,23 @@ interface ComplyEdgeConfig {
|
|
|
105
111
|
* ComplyEdge TypeScript SDK — Client
|
|
106
112
|
*/
|
|
107
113
|
|
|
114
|
+
type Region = "us" | "eu";
|
|
115
|
+
declare const REGION_BASE_URLS: Record<Region, string>;
|
|
116
|
+
/** Region an API key was issued in, read from its prefix; undefined if unknown. */
|
|
117
|
+
declare function regionFromApiKey(apiKey?: string): Region | undefined;
|
|
118
|
+
/**
|
|
119
|
+
* Pick the API host. Precedence, highest first:
|
|
120
|
+
* 1. `baseUrl` option
|
|
121
|
+
* 2. `COMPLYEDGE_API_URL` environment variable
|
|
122
|
+
* 3. `region` option, else `COMPLYEDGE_REGION` environment variable
|
|
123
|
+
* 4. the region encoded in the API key prefix (`ce_eu_` -> EU)
|
|
124
|
+
* 5. US
|
|
125
|
+
*/
|
|
126
|
+
declare function resolveBaseUrl(opts: {
|
|
127
|
+
apiKey?: string;
|
|
128
|
+
baseUrl?: string;
|
|
129
|
+
region?: Region;
|
|
130
|
+
}): string;
|
|
108
131
|
declare class ComplyEdgeClient {
|
|
109
132
|
private http;
|
|
110
133
|
private agentId;
|
|
@@ -164,4 +187,4 @@ declare function withCompliance<T extends Record<string, unknown>>(openaiClient:
|
|
|
164
187
|
blockOnViolation?: boolean;
|
|
165
188
|
}): T;
|
|
166
189
|
|
|
167
|
-
export { ComplyEdgeClient as C, ComplianceError, type PreDeploymentInput as P, type SeverityLevel as S, type ComplyEdgeConfig as
|
|
190
|
+
export { ComplyEdgeClient as C, ComplianceError, type PreDeploymentInput as P, REGION_BASE_URLS as R, type SeverityLevel as S, resolveBaseUrl as a, type Region as b, type ComplyEdgeConfig as c, type ComplianceContext as d, type ComplianceResult as e, type ComplianceViolation as f, type SensitivityResult as g, type SensitivityDetection as h, type PreDeploymentResult as i, regionFromApiKey as r, withCompliance };
|
package/package.json
CHANGED