avantgate 2.1.0 → 2.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/README.md CHANGED
@@ -33,32 +33,17 @@ flowchart LR
33
33
 
34
34
  ---
35
35
 
36
- ## 🖥️ GateWall Cockpit — Self-Hosted AI-WAF & Governance Console (`gatewall/`)
36
+ ## 🖥️ Optional Visual Cockpit — GateWall (`gatewall`)
37
37
 
38
- While the **AvantGate SDK** provides zero-infrastructure, in-process control inside your application runtime, the included **GateWall Cockpit** (`gatewall/`) provides a full-featured, self-hosted visual control plane, real-time audit inspector, and Human-in-the-Loop approval.
38
+ While the **AvantGate SDK (`avantgate`)** runs **100% headless and in-process** inside your application runtime (zero servers, zero network latency), an optional visual control plane, **GateWall**, is available as a standalone repository for teams requiring a visual dashboard, real-time audit inspector, and Human-in-the-Loop approval interface.
39
39
 
40
40
  ```mermaid
41
41
  flowchart LR
42
- Agent[🤖 AvantGate Agent / SDK] -- "POST /api/v1/ingest/events<br/>(Async Telemetry)" --> GateWall["🛡️ GateWall Cockpit<br/>(Next.js + SQLite)"]
43
- GateWall -- "SSE /api/v1/realtime" --> Browser["💻 Web Dashboard<br/>(http://localhost:3000)"]
44
- Browser -- "POST /api/v1/approvals<br/>(Approve / Reject)" --> GateWall
42
+ Agent[🤖 AvantGate In-Process Agent] -- "Optional HTTP Telemetry" --> GateWall["🛡️ Standalone GateWall Cockpit<br/>(Dedicated Repository)"]
43
+ GateWall -- "SSE Real-Time Stream" --> Browser["💻 Web Dashboard<br/>(localhost:3000)"]
45
44
  ```
46
45
 
47
- ### 🚀 Quickstart: Run GateWall Cockpit
48
-
49
- #### Option 1: One-Line Docker Compose (Recommended)
50
- ```bash
51
- docker compose up -d
52
- # or: npm run gatewall:docker
53
- ```
54
- Open **`http://localhost:3000`** in your browser 🎉. Traces and audit sessions are automatically persisted.
55
-
56
- #### Option 2: Run with Bun or Node.js
57
- ```bash
58
- cd gatewall
59
- bun install # or npm install
60
- bun run dev # or npm run dev
61
- ```
46
+ > 💡 **Standalone Repository:** GateWall Cockpit is maintained independently at `../gatewall`. If your application runs headless, you do **not** need to deploy or run GateWall — all guardrails, PII redactions, and token budgets execute directly within your Node.js process.
62
47
 
63
48
  ---
64
49
 
@@ -71,7 +56,8 @@ bun run dev # or npm run dev
71
56
  | **⚡ Real-Time Streaming (SSE)** | Low-latency Server-Sent Events (`/api/v1/realtime`) updating session trees, metrics, and alerts dynamically without manual page refresh. |
72
57
  | **💰 FinOps & Token Tracking** | Automated token cost estimation and USD burn tracking across providers (GPT-4o, Claude 3.5 Sonnet, DeepSeek, etc.). |
73
58
  | **🛡️ Loop Shield (Anti-Cycle Guard)** | Early visual detection of recursive agent loops and aberrant repetitive tool execution cycles. |
74
- | **💾 Zero-External-DB SQLite Storage** | Zero setup overhead: persistent storage uses embedded SQLite (`gatewall/data/gatewall.db`) without requiring PostgreSQL, Redis, or ClickHouse. |
59
+ | **💾 Pluggable Hexagonal Storage** | Zero setup overhead by default with embedded SQLite (`gatewall/data/gatewall.db`), zero-disk in-memory storage for CI tests, and production-ready PostgreSQL/Prisma adapter (`STORAGE_DRIVER=prisma`). |
60
+ | **🔏 Custom Redaction Terms Manager** | Interactive visual manager in the Security Cockpit to register, categorize (Project, Company, Infra), and redact proprietary secrets and NDA keywords in-flight. |
75
61
 
76
62
  > 💡 **Agent Integration Recipes:** See [GateWall Telemetry Recipe](examples/observability/10-gatewall-telemetry.ts) and [Integration Cookbook](examples/README.md) for complete code recipes using `HttpTelemetryExporter` (`avantgate/agent`), direct HTTP ingestion, and React front-end streaming (`avantgate/client`).
77
63
 
@@ -0,0 +1,55 @@
1
+ // src/ui/react/create-view-registry.ts
2
+ import React from "react";
3
+ var createViewRegistry = (registry) => {
4
+ const CanvasRenderer = ({
5
+ state,
6
+ context = {}
7
+ }) => {
8
+ if (!state?.content) {
9
+ return null;
10
+ }
11
+ const kind = state.content.kind;
12
+ const Component = registry[kind];
13
+ if (!Component) {
14
+ return null;
15
+ }
16
+ return React.createElement(Component, {
17
+ data: state.content,
18
+ context,
19
+ activeIntent: state.activeIntent
20
+ });
21
+ };
22
+ return {
23
+ registry,
24
+ CanvasRenderer
25
+ };
26
+ };
27
+
28
+ // src/ui/react/sanitize.ts
29
+ var ALLOWED_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
30
+ var isValidSafeUrl = (rawUrl) => {
31
+ if (!rawUrl || typeof rawUrl !== "string") {
32
+ return false;
33
+ }
34
+ const trimmed = rawUrl.trim();
35
+ if (!trimmed) {
36
+ return false;
37
+ }
38
+ if (trimmed.startsWith("#")) {
39
+ return true;
40
+ }
41
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
42
+ return true;
43
+ }
44
+ try {
45
+ const parsed = new URL(trimmed);
46
+ return ALLOWED_PROTOCOLS.has(parsed.protocol);
47
+ } catch {
48
+ return false;
49
+ }
50
+ };
51
+
52
+ export {
53
+ createViewRegistry,
54
+ isValidSafeUrl
55
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"control-layer.d.ts","sourceRoot":"","sources":["../src/control-layer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EACf,yBAAyB,EACzB,+BAA+B,EAC/B,eAAe,EAIhB,MAAM,SAAS,CAAC;AAiBjB,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,oBAAoB,CAAC,CAAuB;gBAExC,MAAM,EAAE,kBAAkB;IAgBtC,OAAO,CAAC,qBAAqB,CAU3B;IAEF,OAAO,CAAC,kBAAkB,CAaxB;IAEF,OAAO,CAAC,aAAa,CAcnB;IAEF,OAAO,CAAC,mBAAmB,CAezB;IAEF,OAAO,CAAC,yBAAyB,CAe/B;IAEF,OAAO,CAAC,oBAAoB,CAkC1B;IAEF,OAAO,CAAC,wBAAwB,CAW9B;IAEF,OAAO,CAAC,aAAa,CAOnB;IAEF,OAAO,CAAC,aAAa,CAUnB;IAEF,OAAO,CAAC,gBAAgB,CAMtB;IAEF,OAAO,CAAC,iBAAiB,CAsBvB;IAEF,OAAO,CAAC,uBAAuB,CAmB7B;IAEF,OAAO,CAAC,uBAAuB,CA+B7B;IAEF,OAAO,CAAC,cAAc,CAqBpB;IAEF,OAAO,CAAC,eAAe,CAarB;IAEF,OAAO,GAAU,SAAS;QACxB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,gBAAgB,CAAC,EAAE,eAAe,CAAC;KACpC,KAAG,OAAO,CAAC,eAAe,CAAC,CA2B1B;IAGF,iBAAiB,GAAU,CAAC,EAAE,SAAS;QACrC,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,gBAAgB,CAAC,EAAE,eAAe,CAAC;KACpC,KAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAyBvC;IAEF,OAAO,CAAC,wBAAwB,CAO9B;IAEF,OAAO,CAAC,kBAAkB,CAIxB;IAEF,OAAO,CAAC,uBAAuB,CAe7B;IAEF,OAAO,CAAC,wBAAwB,CAqB9B;IAEF,OAAO,CAAC,uBAAuB,CAkB7B;IAEF,OAAO,CAAC,uBAAuB,CAY7B;IAEF,OAAO,CAAC,gCAAgC,CAiBtC;IAEF,OAAO,CAAC,qBAAqB,CAwB3B;IAEF,OAAO,CAAC,mBAAmB,CAazB;IAEF,OAAO,CAAC,gBAAgB,CAQtB;IAEF,wBAAwB,GAAU,CAAC,EACjC,SAAS,+BAA+B,CAAC,CAAC,CAAC,KAC1C,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAwCtC;CACH;AAED,eAAO,MAAM,qBAAqB,GAAI,QAAQ,kBAAkB,KAAG,qBAElE,CAAC;AAEF,eAAO,MAAM,eAAe,WAJkB,kBAAkB,KAAG,qBAIf,CAAC;AACrD,OAAO,EAAE,qBAAqB,IAAI,kBAAkB,EAAE,CAAC"}
1
+ {"version":3,"file":"control-layer.d.ts","sourceRoot":"","sources":["../src/control-layer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EACf,yBAAyB,EACzB,+BAA+B,EAC/B,eAAe,EAIhB,MAAM,SAAS,CAAC;AAiBjB,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,oBAAoB,CAAC,CAAuB;gBAExC,MAAM,EAAE,kBAAkB;IAgBtC,OAAO,CAAC,qBAAqB,CAU3B;IAEF,OAAO,CAAC,kBAAkB,CAaxB;IAEF,OAAO,CAAC,aAAa,CAcnB;IAEF,OAAO,CAAC,mBAAmB,CAqBzB;IAEF,OAAO,CAAC,yBAAyB,CAiB/B;IAEF,OAAO,CAAC,oBAAoB,CAkC1B;IAEF,OAAO,CAAC,wBAAwB,CAW9B;IAEF,OAAO,CAAC,aAAa,CAOnB;IAEF,OAAO,CAAC,aAAa,CAUnB;IAEF,OAAO,CAAC,gBAAgB,CAMtB;IAEF,OAAO,CAAC,iBAAiB,CAsBvB;IAEF,OAAO,CAAC,uBAAuB,CAmB7B;IAEF,OAAO,CAAC,uBAAuB,CA+B7B;IAEF,OAAO,CAAC,cAAc,CAqBpB;IAEF,OAAO,CAAC,eAAe,CAarB;IAEF,OAAO,GAAU,SAAS;QACxB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,gBAAgB,CAAC,EAAE,eAAe,CAAC;KACpC,KAAG,OAAO,CAAC,eAAe,CAAC,CA2B1B;IAGF,iBAAiB,GAAU,CAAC,EAAE,SAAS;QACrC,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,gBAAgB,CAAC,EAAE,eAAe,CAAC;KACpC,KAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAyBvC;IAEF,OAAO,CAAC,wBAAwB,CAO9B;IAEF,OAAO,CAAC,kBAAkB,CAIxB;IAEF,OAAO,CAAC,uBAAuB,CAe7B;IAEF,OAAO,CAAC,wBAAwB,CAqB9B;IAEF,OAAO,CAAC,uBAAuB,CAkB7B;IAEF,OAAO,CAAC,uBAAuB,CAY7B;IAEF,OAAO,CAAC,gCAAgC,CAiBtC;IAEF,OAAO,CAAC,qBAAqB,CAwB3B;IAEF,OAAO,CAAC,mBAAmB,CAazB;IAEF,OAAO,CAAC,gBAAgB,CAQtB;IAEF,wBAAwB,GAAU,CAAC,EACjC,SAAS,+BAA+B,CAAC,CAAC,CAAC,KAC1C,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAwCtC;CACH;AAED,eAAO,MAAM,qBAAqB,GAAI,QAAQ,kBAAkB,KAAG,qBAElE,CAAC;AAEF,eAAO,MAAM,eAAe,WAJkB,kBAAkB,KAAG,qBAIf,CAAC;AACrD,OAAO,EAAE,qBAAqB,IAAI,kBAAkB,EAAE,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { CustomRedactionTermDef } from "./types";
2
+ export interface CustomTermsSanitizationResult {
3
+ text: string;
4
+ maskedCount: number;
5
+ matchedTerms: string[];
6
+ }
7
+ export declare const sanitizeCustomTerms: (input: string, terms?: Array<string | CustomRedactionTermDef>) => CustomTermsSanitizationResult;
8
+ //# sourceMappingURL=custom-terms.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-terms.d.ts","sourceRoot":"","sources":["../src/custom-terms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAgB,MAAM,SAAS,CAAC;AAEpE,MAAM,WAAW,6BAA6B;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAsED,eAAO,MAAM,mBAAmB,GAC9B,OAAO,MAAM,EACb,QAAQ,KAAK,CAAC,MAAM,GAAG,sBAAsB,CAAC,KAC7C,6BAeF,CAAC"}
package/dist/index.d.ts CHANGED
@@ -9,4 +9,5 @@ export * from "./prompts";
9
9
  export * from "./providers/http-client";
10
10
  export * from "./workflow";
11
11
  export * from "./secret-guard";
12
+ export * from "./custom-terms";
12
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,0BAA0B,CAAC;AACzC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,0BAA0B,CAAC;AACzC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -61,6 +61,7 @@ __export(index_exports, {
61
61
  isWorkflowAbortSignal: () => isWorkflowAbortSignal,
62
62
  resolveModelPrice: () => resolveModelPrice,
63
63
  resolveModelPriceAsync: () => resolveModelPriceAsync,
64
+ sanitizeCustomTerms: () => sanitizeCustomTerms,
64
65
  sanitizePII: () => sanitizePII,
65
66
  sanitizeSecrets: () => sanitizeSecrets,
66
67
  validateUserInput: () => validateUserInput,
@@ -1172,6 +1173,70 @@ var createHttpProviderClient = (config) => {
1172
1173
  return new HttpProviderClient(config);
1173
1174
  };
1174
1175
 
1176
+ // src/custom-terms.ts
1177
+ var DEFAULT_MASKS = {
1178
+ PROJECT: "[REDACTED_PROJECT]",
1179
+ COMPANY: "[REDACTED_COMPANY]",
1180
+ INFRA: "[REDACTED_INFRA]",
1181
+ CUSTOM: "[REDACTED_CUSTOM]"
1182
+ };
1183
+ var escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1184
+ var resolveTermDefinition = (entry) => {
1185
+ if (typeof entry === "string") {
1186
+ return {
1187
+ term: entry.trim(),
1188
+ mask: DEFAULT_MASKS.CUSTOM,
1189
+ category: "CUSTOM",
1190
+ caseSensitive: false
1191
+ };
1192
+ }
1193
+ const category = entry.category ?? "CUSTOM";
1194
+ return {
1195
+ term: entry.term.trim(),
1196
+ mask: entry.mask ?? (DEFAULT_MASKS[category] ?? DEFAULT_MASKS.CUSTOM),
1197
+ category,
1198
+ caseSensitive: Boolean(entry.caseSensitive)
1199
+ };
1200
+ };
1201
+ var buildTermRegex = (def) => {
1202
+ const escaped = escapeRegex(def.term);
1203
+ const leadingBoundary = /^\w/.test(def.term) ? "\\b" : "";
1204
+ const trailingBoundary = /\w$/.test(def.term) ? "\\b" : "";
1205
+ return new RegExp(`${leadingBoundary}${escaped}${trailingBoundary}`, def.caseSensitive ? "g" : "gi");
1206
+ };
1207
+ var replaceTermsInText = (initialText, definitions) => {
1208
+ let currentText = initialText;
1209
+ let totalMaskedCount = 0;
1210
+ const matchedTermsSet = /* @__PURE__ */ new Set();
1211
+ for (const item of definitions) {
1212
+ const regex = buildTermRegex(item);
1213
+ let matchCount = 0;
1214
+ currentText = currentText.replace(regex, () => {
1215
+ matchCount++;
1216
+ return item.mask;
1217
+ });
1218
+ if (matchCount > 0) {
1219
+ totalMaskedCount += matchCount;
1220
+ matchedTermsSet.add(item.term);
1221
+ }
1222
+ }
1223
+ return {
1224
+ text: currentText,
1225
+ maskedCount: totalMaskedCount,
1226
+ matchedTerms: Array.from(matchedTermsSet)
1227
+ };
1228
+ };
1229
+ var sanitizeCustomTerms = (input, terms) => {
1230
+ if (!input || !terms || terms.length === 0) {
1231
+ return { text: input, maskedCount: 0, matchedTerms: [] };
1232
+ }
1233
+ const normalized = terms.map(resolveTermDefinition).filter((t) => t.term.length > 0).sort((a, b) => b.term.length - a.term.length);
1234
+ if (normalized.length === 0) {
1235
+ return { text: input, maskedCount: 0, matchedTerms: [] };
1236
+ }
1237
+ return replaceTermsInText(input, normalized);
1238
+ };
1239
+
1175
1240
  // src/secret-guard.ts
1176
1241
  var SECRET_PATTERNS = [
1177
1242
  // 1. Clés privées (RSA, OpenSSH, EC, DSA)
@@ -1252,6 +1317,7 @@ var sanitizeSecrets = (input) => {
1252
1317
  var applyOutputGuards = (rawOutput, options) => {
1253
1318
  let currentText = rawOutput;
1254
1319
  let piiCount = 0;
1320
+ let customTermsCount = 0;
1255
1321
  if (options?.maskPII) {
1256
1322
  const piiResult = sanitizePII(currentText);
1257
1323
  currentText = piiResult.text;
@@ -1259,6 +1325,11 @@ var applyOutputGuards = (rawOutput, options) => {
1259
1325
  }
1260
1326
  const secretResult = sanitizeSecrets(currentText);
1261
1327
  currentText = secretResult.text;
1328
+ if (options?.customRedactionTerms && options.customRedactionTerms.length > 0) {
1329
+ const customResult = sanitizeCustomTerms(currentText, options.customRedactionTerms);
1330
+ currentText = customResult.text;
1331
+ customTermsCount = customResult.maskedCount;
1332
+ }
1262
1333
  if (secretResult.hasSecrets && options?.secretLeakAction === "BLOCK") {
1263
1334
  const types = secretResult.detections.map((d) => d.type).join(", ");
1264
1335
  throw new SecretLeakBlockedError(
@@ -1268,9 +1339,10 @@ var applyOutputGuards = (rawOutput, options) => {
1268
1339
  }
1269
1340
  return {
1270
1341
  text: currentText,
1271
- sanitized: piiCount > 0 || secretResult.hasSecrets,
1342
+ sanitized: piiCount > 0 || secretResult.hasSecrets || customTermsCount > 0,
1272
1343
  secretDetected: secretResult.hasSecrets,
1273
1344
  piiMaskedCount: piiCount,
1345
+ customTermsMaskedCount: customTermsCount,
1274
1346
  detections: secretResult.detections
1275
1347
  };
1276
1348
  };
@@ -1335,21 +1407,27 @@ var AvantGateControlLayer = class {
1335
1407
  if (!guard.valid) {
1336
1408
  throw new Error(`[AvantGate Security Guard] Request blocked: ${guard.blockedReason}`);
1337
1409
  }
1410
+ let processed = userQuery;
1411
+ if (this.config.security?.customRedactionTerms && this.config.security.customRedactionTerms.length > 0) {
1412
+ processed = sanitizeCustomTerms(processed, this.config.security.customRedactionTerms).text;
1413
+ }
1338
1414
  if (this.config.security?.maskPII) {
1339
- return sanitizePII(userQuery).text;
1415
+ return sanitizePII(processed).text;
1340
1416
  }
1341
- return userQuery;
1417
+ return processed;
1342
1418
  };
1343
1419
  applyOutputSecurityGuards = (rawOutput) => {
1344
1420
  const isDlpEnabled = this.config.security?.outputDLP ?? this.config.security?.maskPII ?? false;
1345
1421
  const shouldCheckSecrets = this.config.security?.blockSecretLeaks ?? true;
1346
- if (!isDlpEnabled && !shouldCheckSecrets) {
1422
+ const customTerms = this.config.security?.customRedactionTerms;
1423
+ if (!isDlpEnabled && !shouldCheckSecrets && (!customTerms || customTerms.length === 0)) {
1347
1424
  return rawOutput;
1348
1425
  }
1349
1426
  const guardResult = applyOutputGuards(rawOutput, {
1350
1427
  maskPII: isDlpEnabled,
1351
1428
  blockSecretLeaks: shouldCheckSecrets,
1352
- secretLeakAction: this.config.security?.secretLeakAction ?? "REDACT"
1429
+ secretLeakAction: this.config.security?.secretLeakAction ?? "REDACT",
1430
+ customRedactionTerms: customTerms
1353
1431
  });
1354
1432
  return guardResult.text;
1355
1433
  };
@@ -2642,6 +2720,7 @@ var defineWorkflow = (config) => {
2642
2720
  isWorkflowAbortSignal,
2643
2721
  resolveModelPrice,
2644
2722
  resolveModelPriceAsync,
2723
+ sanitizeCustomTerms,
2645
2724
  sanitizePII,
2646
2725
  sanitizeSecrets,
2647
2726
  validateUserInput,
package/dist/index.mjs CHANGED
@@ -562,6 +562,70 @@ var createHttpProviderClient = (config) => {
562
562
  return new HttpProviderClient(config);
563
563
  };
564
564
 
565
+ // src/custom-terms.ts
566
+ var DEFAULT_MASKS = {
567
+ PROJECT: "[REDACTED_PROJECT]",
568
+ COMPANY: "[REDACTED_COMPANY]",
569
+ INFRA: "[REDACTED_INFRA]",
570
+ CUSTOM: "[REDACTED_CUSTOM]"
571
+ };
572
+ var escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
573
+ var resolveTermDefinition = (entry) => {
574
+ if (typeof entry === "string") {
575
+ return {
576
+ term: entry.trim(),
577
+ mask: DEFAULT_MASKS.CUSTOM,
578
+ category: "CUSTOM",
579
+ caseSensitive: false
580
+ };
581
+ }
582
+ const category = entry.category ?? "CUSTOM";
583
+ return {
584
+ term: entry.term.trim(),
585
+ mask: entry.mask ?? (DEFAULT_MASKS[category] ?? DEFAULT_MASKS.CUSTOM),
586
+ category,
587
+ caseSensitive: Boolean(entry.caseSensitive)
588
+ };
589
+ };
590
+ var buildTermRegex = (def) => {
591
+ const escaped = escapeRegex(def.term);
592
+ const leadingBoundary = /^\w/.test(def.term) ? "\\b" : "";
593
+ const trailingBoundary = /\w$/.test(def.term) ? "\\b" : "";
594
+ return new RegExp(`${leadingBoundary}${escaped}${trailingBoundary}`, def.caseSensitive ? "g" : "gi");
595
+ };
596
+ var replaceTermsInText = (initialText, definitions) => {
597
+ let currentText = initialText;
598
+ let totalMaskedCount = 0;
599
+ const matchedTermsSet = /* @__PURE__ */ new Set();
600
+ for (const item of definitions) {
601
+ const regex = buildTermRegex(item);
602
+ let matchCount = 0;
603
+ currentText = currentText.replace(regex, () => {
604
+ matchCount++;
605
+ return item.mask;
606
+ });
607
+ if (matchCount > 0) {
608
+ totalMaskedCount += matchCount;
609
+ matchedTermsSet.add(item.term);
610
+ }
611
+ }
612
+ return {
613
+ text: currentText,
614
+ maskedCount: totalMaskedCount,
615
+ matchedTerms: Array.from(matchedTermsSet)
616
+ };
617
+ };
618
+ var sanitizeCustomTerms = (input, terms) => {
619
+ if (!input || !terms || terms.length === 0) {
620
+ return { text: input, maskedCount: 0, matchedTerms: [] };
621
+ }
622
+ const normalized = terms.map(resolveTermDefinition).filter((t) => t.term.length > 0).sort((a, b) => b.term.length - a.term.length);
623
+ if (normalized.length === 0) {
624
+ return { text: input, maskedCount: 0, matchedTerms: [] };
625
+ }
626
+ return replaceTermsInText(input, normalized);
627
+ };
628
+
565
629
  // src/secret-guard.ts
566
630
  var SECRET_PATTERNS = [
567
631
  // 1. Clés privées (RSA, OpenSSH, EC, DSA)
@@ -642,6 +706,7 @@ var sanitizeSecrets = (input) => {
642
706
  var applyOutputGuards = (rawOutput, options) => {
643
707
  let currentText = rawOutput;
644
708
  let piiCount = 0;
709
+ let customTermsCount = 0;
645
710
  if (options?.maskPII) {
646
711
  const piiResult = sanitizePII(currentText);
647
712
  currentText = piiResult.text;
@@ -649,6 +714,11 @@ var applyOutputGuards = (rawOutput, options) => {
649
714
  }
650
715
  const secretResult = sanitizeSecrets(currentText);
651
716
  currentText = secretResult.text;
717
+ if (options?.customRedactionTerms && options.customRedactionTerms.length > 0) {
718
+ const customResult = sanitizeCustomTerms(currentText, options.customRedactionTerms);
719
+ currentText = customResult.text;
720
+ customTermsCount = customResult.maskedCount;
721
+ }
652
722
  if (secretResult.hasSecrets && options?.secretLeakAction === "BLOCK") {
653
723
  const types = secretResult.detections.map((d) => d.type).join(", ");
654
724
  throw new SecretLeakBlockedError(
@@ -658,9 +728,10 @@ var applyOutputGuards = (rawOutput, options) => {
658
728
  }
659
729
  return {
660
730
  text: currentText,
661
- sanitized: piiCount > 0 || secretResult.hasSecrets,
731
+ sanitized: piiCount > 0 || secretResult.hasSecrets || customTermsCount > 0,
662
732
  secretDetected: secretResult.hasSecrets,
663
733
  piiMaskedCount: piiCount,
734
+ customTermsMaskedCount: customTermsCount,
664
735
  detections: secretResult.detections
665
736
  };
666
737
  };
@@ -725,21 +796,27 @@ var AvantGateControlLayer = class {
725
796
  if (!guard.valid) {
726
797
  throw new Error(`[AvantGate Security Guard] Request blocked: ${guard.blockedReason}`);
727
798
  }
799
+ let processed = userQuery;
800
+ if (this.config.security?.customRedactionTerms && this.config.security.customRedactionTerms.length > 0) {
801
+ processed = sanitizeCustomTerms(processed, this.config.security.customRedactionTerms).text;
802
+ }
728
803
  if (this.config.security?.maskPII) {
729
- return sanitizePII(userQuery).text;
804
+ return sanitizePII(processed).text;
730
805
  }
731
- return userQuery;
806
+ return processed;
732
807
  };
733
808
  applyOutputSecurityGuards = (rawOutput) => {
734
809
  const isDlpEnabled = this.config.security?.outputDLP ?? this.config.security?.maskPII ?? false;
735
810
  const shouldCheckSecrets = this.config.security?.blockSecretLeaks ?? true;
736
- if (!isDlpEnabled && !shouldCheckSecrets) {
811
+ const customTerms = this.config.security?.customRedactionTerms;
812
+ if (!isDlpEnabled && !shouldCheckSecrets && (!customTerms || customTerms.length === 0)) {
737
813
  return rawOutput;
738
814
  }
739
815
  const guardResult = applyOutputGuards(rawOutput, {
740
816
  maskPII: isDlpEnabled,
741
817
  blockSecretLeaks: shouldCheckSecrets,
742
- secretLeakAction: this.config.security?.secretLeakAction ?? "REDACT"
818
+ secretLeakAction: this.config.security?.secretLeakAction ?? "REDACT",
819
+ customRedactionTerms: customTerms
743
820
  });
744
821
  return guardResult.text;
745
822
  };
@@ -1444,6 +1521,7 @@ export {
1444
1521
  isWorkflowAbortSignal,
1445
1522
  resolveModelPrice,
1446
1523
  resolveModelPriceAsync,
1524
+ sanitizeCustomTerms,
1447
1525
  sanitizePII,
1448
1526
  sanitizeSecrets,
1449
1527
  validateUserInput,
@@ -1,3 +1,6 @@
1
+ import { CustomRedactionTermDef } from "./types";
2
+ import { sanitizeCustomTerms, CustomTermsSanitizationResult } from "./custom-terms";
3
+ export { sanitizeCustomTerms, CustomTermsSanitizationResult };
1
4
  export interface SecretPatternDef {
2
5
  type: string;
3
6
  regex: RegExp;
@@ -17,12 +20,14 @@ export interface OutputGuardOptions {
17
20
  maskPII?: boolean;
18
21
  blockSecretLeaks?: boolean;
19
22
  secretLeakAction?: "REDACT" | "BLOCK";
23
+ customRedactionTerms?: Array<string | CustomRedactionTermDef>;
20
24
  }
21
25
  export interface OutputGuardResult {
22
26
  text: string;
23
27
  sanitized: boolean;
24
28
  secretDetected: boolean;
25
29
  piiMaskedCount: number;
30
+ customTermsMaskedCount: number;
26
31
  detections: SecretDetection[];
27
32
  }
28
33
  export declare const applyOutputGuards: (rawOutput: string, options?: OutputGuardOptions) => OutputGuardResult;
@@ -1 +1 @@
1
- {"version":3,"file":"secret-guard.d.ts","sourceRoot":"","sources":["../src/secret-guard.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAqDD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B;AAED,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,KAAG,qBA4B/C,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;CACvC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B;AAED,eAAO,MAAM,iBAAiB,GAC5B,WAAW,MAAM,EACjB,UAAU,kBAAkB,KAC3B,iBA+BF,CAAC"}
1
+ {"version":3,"file":"secret-guard.d.ts","sourceRoot":"","sources":["../src/secret-guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAEzE,OAAO,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AAEpF,OAAO,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAqDD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B;AAED,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,KAAG,qBA4B/C,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IACtC,oBAAoB,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,sBAAsB,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B;AAED,eAAO,MAAM,iBAAiB,GAC5B,WAAW,MAAM,EACjB,UAAU,kBAAkB,KAC3B,iBAwCF,CAAC"}
package/dist/types.d.ts CHANGED
@@ -67,6 +67,14 @@ export interface ProviderConfig {
67
67
  client?: LLMProviderPort;
68
68
  pricing?: ModelPrice;
69
69
  }
70
+ export type TermCategory = "PROJECT" | "COMPANY" | "INFRA" | "CUSTOM";
71
+ export interface CustomRedactionTermDef {
72
+ id?: string;
73
+ term: string;
74
+ mask?: string;
75
+ category?: TermCategory;
76
+ caseSensitive?: boolean;
77
+ }
70
78
  export interface SecurityConfig {
71
79
  detectPromptInjection?: boolean;
72
80
  maskPII?: boolean;
@@ -74,6 +82,7 @@ export interface SecurityConfig {
74
82
  outputDLP?: boolean;
75
83
  blockSecretLeaks?: boolean;
76
84
  secretLeakAction?: "REDACT" | "BLOCK";
85
+ customRedactionTerms?: Array<string | CustomRedactionTermDef>;
77
86
  }
78
87
  export interface RetryConfig {
79
88
  maxRetries?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  export { createToolEnvelope, type ToolExecutionEnvelope, type ToolMergeStrategy, type UIIntent, type UIIntentAction, } from "./envelope";
2
2
  export { createCanvasReducer, isSafeKey, mergeUniqueEntities, updateEntityInPlace, type CanvasContentState, type CanvasState, } from "./reducer";
3
3
  export { defineCanvas } from "./define-canvas";
4
+ export { createViewRegistry, type CanvasRendererProps, type CanvasViewComponent, type CanvasViewContext, isValidSafeUrl, } from "./react";
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,QAAQ,EACb,KAAK,cAAc,GACpB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,kBAAkB,EACvB,KAAK,WAAW,GACjB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,QAAQ,EACb,KAAK,cAAc,GACpB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,kBAAkB,EACvB,KAAK,WAAW,GACjB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EACL,kBAAkB,EAClB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,cAAc,GACf,MAAM,SAAS,CAAC"}
package/dist/ui/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/ui/index.ts
@@ -22,8 +32,10 @@ var ui_exports = {};
22
32
  __export(ui_exports, {
23
33
  createCanvasReducer: () => createCanvasReducer,
24
34
  createToolEnvelope: () => createToolEnvelope,
35
+ createViewRegistry: () => createViewRegistry,
25
36
  defineCanvas: () => defineCanvas,
26
37
  isSafeKey: () => isSafeKey,
38
+ isValidSafeUrl: () => isValidSafeUrl,
27
39
  mergeUniqueEntities: () => mergeUniqueEntities,
28
40
  updateEntityInPlace: () => updateEntityInPlace
29
41
  });
@@ -159,12 +171,65 @@ var defineCanvas = () => {
159
171
  canvasReducer: createCanvasReducer()
160
172
  };
161
173
  };
174
+
175
+ // src/ui/react/create-view-registry.ts
176
+ var import_react = __toESM(require("react"));
177
+ var createViewRegistry = (registry) => {
178
+ const CanvasRenderer = ({
179
+ state,
180
+ context = {}
181
+ }) => {
182
+ if (!state?.content) {
183
+ return null;
184
+ }
185
+ const kind = state.content.kind;
186
+ const Component = registry[kind];
187
+ if (!Component) {
188
+ return null;
189
+ }
190
+ return import_react.default.createElement(Component, {
191
+ data: state.content,
192
+ context,
193
+ activeIntent: state.activeIntent
194
+ });
195
+ };
196
+ return {
197
+ registry,
198
+ CanvasRenderer
199
+ };
200
+ };
201
+
202
+ // src/ui/react/sanitize.ts
203
+ var ALLOWED_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
204
+ var isValidSafeUrl = (rawUrl) => {
205
+ if (!rawUrl || typeof rawUrl !== "string") {
206
+ return false;
207
+ }
208
+ const trimmed = rawUrl.trim();
209
+ if (!trimmed) {
210
+ return false;
211
+ }
212
+ if (trimmed.startsWith("#")) {
213
+ return true;
214
+ }
215
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
216
+ return true;
217
+ }
218
+ try {
219
+ const parsed = new URL(trimmed);
220
+ return ALLOWED_PROTOCOLS.has(parsed.protocol);
221
+ } catch {
222
+ return false;
223
+ }
224
+ };
162
225
  // Annotate the CommonJS export names for ESM import in node:
163
226
  0 && (module.exports = {
164
227
  createCanvasReducer,
165
228
  createToolEnvelope,
229
+ createViewRegistry,
166
230
  defineCanvas,
167
231
  isSafeKey,
232
+ isValidSafeUrl,
168
233
  mergeUniqueEntities,
169
234
  updateEntityInPlace
170
235
  });
package/dist/ui/index.mjs CHANGED
@@ -1,3 +1,7 @@
1
+ import {
2
+ createViewRegistry,
3
+ isValidSafeUrl
4
+ } from "../chunk-Z6QOMLZ2.mjs";
1
5
  import "../chunk-Y6FXYEAI.mjs";
2
6
 
3
7
  // src/ui/envelope.ts
@@ -133,8 +137,10 @@ var defineCanvas = () => {
133
137
  export {
134
138
  createCanvasReducer,
135
139
  createToolEnvelope,
140
+ createViewRegistry,
136
141
  defineCanvas,
137
142
  isSafeKey,
143
+ isValidSafeUrl,
138
144
  mergeUniqueEntities,
139
145
  updateEntityInPlace
140
146
  };
@@ -1,55 +1,8 @@
1
+ import {
2
+ createViewRegistry,
3
+ isValidSafeUrl
4
+ } from "../../chunk-Z6QOMLZ2.mjs";
1
5
  import "../../chunk-Y6FXYEAI.mjs";
2
-
3
- // src/ui/react/create-view-registry.ts
4
- import React from "react";
5
- var createViewRegistry = (registry) => {
6
- const CanvasRenderer = ({
7
- state,
8
- context = {}
9
- }) => {
10
- if (!state?.content) {
11
- return null;
12
- }
13
- const kind = state.content.kind;
14
- const Component = registry[kind];
15
- if (!Component) {
16
- return null;
17
- }
18
- return React.createElement(Component, {
19
- data: state.content,
20
- context,
21
- activeIntent: state.activeIntent
22
- });
23
- };
24
- return {
25
- registry,
26
- CanvasRenderer
27
- };
28
- };
29
-
30
- // src/ui/react/sanitize.ts
31
- var ALLOWED_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
32
- var isValidSafeUrl = (rawUrl) => {
33
- if (!rawUrl || typeof rawUrl !== "string") {
34
- return false;
35
- }
36
- const trimmed = rawUrl.trim();
37
- if (!trimmed) {
38
- return false;
39
- }
40
- if (trimmed.startsWith("#")) {
41
- return true;
42
- }
43
- if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
44
- return true;
45
- }
46
- try {
47
- const parsed = new URL(trimmed);
48
- return ALLOWED_PROTOCOLS.has(parsed.protocol);
49
- } catch {
50
- return false;
51
- }
52
- };
53
6
  export {
54
7
  createViewRegistry,
55
8
  isValidSafeUrl
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "avantgate",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "Zero-infrastructure, in-process AI Application Firewall (AI-WAF), privacy control plane & headless UI canvas for TypeScript: real-time prompt guardrails, zero-egress PII redaction, deterministic tool envelopes, anti-IDOR defense, pre-flight token budgets, and multi-model failover.",
5
5
  "author": "Gatewall Team",
6
6
  "license": "MIT",
@@ -69,16 +69,16 @@
69
69
  "import": "./dist/client/index.mjs",
70
70
  "require": "./dist/client/index.js"
71
71
  },
72
- "./ui": {
73
- "types": "./dist/ui/index.d.ts",
74
- "import": "./dist/ui/index.mjs",
75
- "require": "./dist/ui/index.js"
76
- },
77
72
  "./ui/react": {
78
73
  "types": "./dist/ui/react/index.d.ts",
79
74
  "import": "./dist/ui/react/index.mjs",
80
75
  "require": "./dist/ui/react/index.js"
81
76
  },
77
+ "./ui": {
78
+ "types": "./dist/ui/index.d.ts",
79
+ "import": "./dist/ui/index.mjs",
80
+ "require": "./dist/ui/index.js"
81
+ },
82
82
  "./package.json": "./package.json"
83
83
  },
84
84
  "peerDependencies": {
@@ -107,12 +107,6 @@
107
107
  "test:workflow": "tsx tests/workflow/workflow-saga.test.ts && tsx tests/workflow/workflow-abort.test.ts",
108
108
  "test:client": "tsx tests/client/browser-exporter.test.ts && tsx tests/client/use-avantgate-task.test.ts && tsx tests/client/task-runner.test.ts",
109
109
  "test:demo": "tsx tests/agent/prospect-ai-demo-scenario.test.ts",
110
- "gatewall": "npm --prefix gatewall run dev",
111
- "gatewall:dev": "npm --prefix gatewall run dev",
112
- "gatewall:build": "npm --prefix gatewall run build",
113
- "gatewall:seed": "npm --prefix gatewall run seed:mock",
114
- "gatewall:start": "npm --prefix gatewall run start",
115
- "gatewall:docker": "docker compose up -d",
116
110
  "lint": "tsc --noEmit",
117
111
  "prepublishOnly": "npm run build && npm test"
118
112
  },
@@ -139,3 +133,4 @@
139
133
  "url": "https://github.com/thienban/avantGate/issues"
140
134
  }
141
135
  }
136
+