avantgate 2.0.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
@@ -1,7 +1,7 @@
1
1
  # 🛡️ AvantGate (`avantgate`)
2
2
 
3
- > **The Zero-Infrastructure, In-Process AI Application Firewall (AI-WAF), Deterministic Workflow Engine & Privacy Guard for TypeScript.**
4
- > Real-time prompt guardrails, zero-egress PII redaction, deterministic Saga workflows, anti-IDOR tool boundary, and pre-flight token defense **without hosting Docker, proxies, PostgreSQL, ClickHouse, or Redis.**
3
+ > **The Zero-Infrastructure, In-Process AI Application Firewall (AI-WAF), Deterministic Workflow Engine, Privacy Guard & Headless UI Canvas for TypeScript.**
4
+ > Real-time prompt guardrails, zero-egress PII redaction, deterministic Saga workflows, canonical tool envelopes, anti-IDOR tool boundary, and pre-flight token defense **without hosting Docker, proxies, PostgreSQL, ClickHouse, or Redis.**
5
5
 
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7
7
  [![TypeScript](https://img.shields.io/badge/TypeScript-Strict-blue?logo=typescript)](https://www.typescriptlang.org/)
@@ -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,9 +56,10 @@ 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
- > 💡 **Agent Integration Recipes:** See [Connecting an Agent to GateWall Cockpit](docs/examples.md#12-connecting-an-agent-to-gatewall-cockpit-gatewall) in `docs/examples.md` for complete code recipes using `HttpTelemetryExporter` (`avantgate/agent`), direct HTTP ingestion, and React front-end streaming (`avantgate/client`).
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
 
78
64
  ---
79
65
 
@@ -92,6 +78,7 @@ Contact our team at [contact@gatewall.fr](mailto:contact@gatewall.fr) for privat
92
78
  | 🛑 **Agent Isolation & Anti-IDOR** | • **Dual-Channel DTOs**: Streams full records to UI while injecting sanitized summaries into LLM.<br/>• **Anti-IDOR Boundary**: Compile-time tenant scoping (`createTenantTool`) & runtime ownership checks.<br/>• **Server Idempotency Guard**: Zero-infra in-process guard (`withServerIdempotency`) with memory or storage adapters.<br/>• **Infinite Loop Shield**: Detects and breaks recursive agent tool execution loops. |
93
79
  | 💰 **FinOps & Resilience** | • **Denial-of-Wallet**: Enforces hard token & USD budgets *before* external inference spend.<br/>• **Multi-Model Failover**: Instant client-side routing to fallback models or local Ollama on 429/500.<br/>• **FinOps Batch Deduplication**: Prevents double-counting of tokens & costs during network retries on GateWall.<br/>• **Live Cost Ledger**: Token burn calculation & pricing adapters with zero external DB. |
94
80
  | ⚡ **Sagas, Replay & Telemetry** | • **Deterministic Sagas (`avantgate/workflow`)**: In-process FSM with automatic reverse compensation ($k-1 \to 0$).<br/>• **In-Context Replay (`avantgate/client`)**: React hook (`useTask`) with causal parent linkage (`parentRunId`) & `Idempotency-Key`.<br/>• **Human-in-the-Loop (HITL)**: Non-blocking suspension, approval queues & fail-closed 24h SLA timeout (TTL).<br/>• **Lightweight Telemetry**: < 1.7 KB client SDK & async audit bridge to GateWall. |
81
+ | 🎨 **Presentation Plane (`avantgate/ui`)** | • **Canonical Tool Envelopes**: Typed format carrying merge strategies (`REPLACE`, `APPEND_UNIQUE`, `UPDATE_ENTITY`) & `UIIntent`.<br/>• **Deterministic Concurrency Reducer**: Algebraic $O(N)$ Set-based convergence solving parallel tool calling races.<br/>• **React View Registry (`avantgate/ui/react`)**: Polymorphic $O(1)$ dynamic dispatch linking tools to your design system (shadcn/ui).<br/>• **Native Anti-XSS Guard**: Zero-dependency WHATWG `URL` scanner neutralizing `javascript:` & protocol-relative (`//evil.com`) vectors. |
95
82
 
96
83
  ---
97
84
 
@@ -99,14 +86,15 @@ Contact our team at [contact@gatewall.fr](mailto:contact@gatewall.fr) for privat
99
86
 
100
87
  | Category | In-Depth Guides |
101
88
  |---|---|
102
- | 🚀 **Quickstart** | [Getting Started](docs/getting-started.md) • [Integration Cookbook](docs/examples.md) |
89
+ | 🚀 **Quickstart** | [Getting Started](docs/getting-started.md) • [Integration Cookbook](examples/README.md) |
103
90
  | 🛡️ **Security & AI-WAF** | [Prompt Guardrails](docs/security/prompt-guardrails.md) • [PII Redaction](docs/security/pii-redaction.md) • [Anti-IDOR Defense](docs/security/anti-idor.md) • [End-to-End Security](docs/security/end-to-end-security.md) |
104
91
  | 💰 **FinOps & Cost** | [Pre-Flight Budget Guards](docs/finops/budget-guards.md) • [Pricing Adapters & SQLite](docs/finops/pricing-adapters.md) |
105
92
  | 🤖 **Agents & Tools** | [Isolated Tools & DTOs](docs/agents/isolated-tools.md) • [Agent Runtime Manual](docs/agents/agent-runtime.md) • [Inter-Tool Chaining](docs/agents/inter-tool-chaining.md) |
106
93
  | 🔄 **Deterministic Sagas** | [Durable Workflows Engine](docs/workflows/durable-workflows.md) |
107
94
  | 📊 **Observability & Cockpit** | [GateWall Cockpit Console](docs/observability/gatewall-cockpit.md) • [Telemetry & Browser SDK](docs/observability/telemetry-and-browser-sdk.md) • [GateWall vs. Temporal](docs/observability/temporal-and-gatewall.md) |
108
95
  | 💶 **Accounting** | [Financial Normalizer](docs/finance/normalizer.md) |
109
- | 🚀 **Release Notes** | [v2.0.0 Release Notes](docs/release/release-2.0.0.md) • [v1.9.0 Release Notes](docs/release/release-1.9.0.md) |
96
+ | 🎨 **Presentation Plane** | [Headless UI Canvas & React Bindings](docs/ui/headless-canvas.md) |
97
+ | 🚀 **Release Notes** | [v2.1.0 Release Notes](docs/release/release-2.1.0.md) • [v2.0.0 Release Notes](docs/release/release-2.0.0.md) • [v1.9.0 Release Notes](docs/release/release-1.9.0.md) |
110
98
 
111
99
  ---
112
100
 
@@ -125,6 +113,7 @@ Contact our team at [contact@gatewall.fr](mailto:contact@gatewall.fr) for privat
125
113
  | **Multi-Model Failover** | ❌ App crashes | ⚠️ Proxy-dependent | ✅ **Built-in Fallback Router & Exponential Retry** |
126
114
  | **Zod Schema Auto-Repair** | ❌ No | ❌ No | ✅ **Built-in JSON Heuristic Repair** |
127
115
  | **Hierarchical Session Replay** | ❌ None | ⚠️ Flat span waterfall | ✅ **Causality Tree + In-Context Replay (`useTask`)** |
116
+ | **Headless UI Canvas State** | ❌ Manual parsing | ❌ Not supported | ✅ **Canonical Envelopes + Parallel Reducer (`avantgate/ui`)** |
128
117
 
129
118
  ---
130
119
 
@@ -140,13 +129,17 @@ yarn add avantgate zod
140
129
 
141
130
  ### 🧩 Subpath Exports
142
131
 
143
- | Import Path | Description |
144
- |---|---|
145
- | `avantgate` | Core control plane: token budgets, cost ledger, prompt guards, multi-model failover & Zod repair. |
146
- | `avantgate/finance` | Financial data normalizer (accounting parentheses, EU/US/UK/CH currencies & magnitudes). |
147
- | `avantgate/agent` | Durable step runner, Human-in-the-Loop, dual-channel PII tool isolation, server idempotency (`withServerIdempotency`), & storage adapters. |
148
- | `avantgate/workflow` | Deterministic sequential state machine, automatic reverse Saga rollback, durable HITL checkpoints & agent tool conversion. |
149
- | `avantgate/client` | Front-end SDK (< 1.7 KB) with in-context task replay (`useTask`, `createTaskRunner`), causal idempotency helpers (`getIdempotencyHeaders`), & GateWall telemetry adapter. |
132
+ | Import Path | Description | Documentation |
133
+ |---|---|---|
134
+ | `avantgate` | Core control plane: token budgets, cost ledger, prompt guards, multi-model failover & Zod repair. | [Getting Started](docs/getting-started.md) |
135
+ | `avantgate/finance` | Financial data normalizer (accounting parentheses, EU/US/UK/CH currencies & magnitudes). | [Financial Normalizer](docs/finance/normalizer.md) |
136
+ | `avantgate/agent` | Durable step runner, Human-in-the-Loop, dual-channel PII tool isolation, server idempotency (`withServerIdempotency`), & storage adapters. | [Isolated Tools & DTOs](docs/agents/isolated-tools.md) |
137
+ | `avantgate/workflow` | Deterministic sequential state machine, automatic reverse Saga rollback, durable HITL checkpoints & agent tool conversion. | [Durable Workflows](docs/workflows/durable-workflows.md) |
138
+ | `avantgate/client` | Front-end SDK (< 1.7 KB) with in-context task replay (`useTask`, `createTaskRunner`), causal idempotency helpers (`getIdempotencyHeaders`), & GateWall telemetry adapter. | [Telemetry & Browser SDK](docs/observability/telemetry-and-browser-sdk.md) |
139
+ | `avantgate/ui` | Headless UI canvas core (< 2.5 KB): canonical tool envelopes, deterministic $O(N)$ parallel reducer, `defineCanvas` factory. | [Headless UI Canvas](docs/ui/headless-canvas.md) |
140
+ | `avantgate/ui/react` | React presentation plane: polymorphic $O(1)$ view registry (`createViewRegistry`), `CanvasRenderer`, & anti-XSS URL sanitizer (`isValidSafeUrl`). | [Headless UI Canvas](docs/ui/headless-canvas.md) |
141
+
142
+ > 💡 **UI Canvas Cookbook:** See [Headless UI Canvas & React Bindings](docs/ui/headless-canvas.md) for complete step-by-step recipes connecting agent tools with typed envelopes and custom React views (shadcn/ui, Tailwind).
150
143
 
151
144
  ---
152
145
 
@@ -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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"}
@@ -0,0 +1,6 @@
1
+ import { type ToolExecutionEnvelope } from "./envelope";
2
+ export declare const defineCanvas: <TContentMap extends Record<string, unknown>>() => {
3
+ createEnvelope: <K extends Extract<keyof TContentMap, string>>(options: Omit<ToolExecutionEnvelope<TContentMap[K], K>, "version">) => ToolExecutionEnvelope<TContentMap[K], K>;
4
+ canvasReducer: (currentState: import("./reducer").CanvasState<TContentMap> | null | undefined, envelope: ToolExecutionEnvelope<unknown, Extract<keyof TContentMap, string>>) => import("./reducer").CanvasState<TContentMap>;
5
+ };
6
+ //# sourceMappingURL=define-canvas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-canvas.d.ts","sourceRoot":"","sources":["../../src/ui/define-canvas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAG5E,eAAO,MAAM,YAAY,GAAI,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;qBAEnD,CAAC,SAAS,OAAO,CAAC,MAAM,WAAW,EAAE,MAAM,CAAC,WAClD,IAAI,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,CAAC,KACjE,qBAAqB,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;;CAM9C,CAAC"}
@@ -0,0 +1,19 @@
1
+ export type ToolMergeStrategy = "REPLACE" | "APPEND_UNIQUE" | "UPDATE_ENTITY";
2
+ export type UIIntentAction = "HIGHLIGHT" | "SELECT" | "OPEN_MODAL" | "NAVIGATE";
3
+ export interface UIIntent {
4
+ action: UIIntentAction;
5
+ targetId: string;
6
+ targetType: "prospect" | "company" | "task" | "event" | string;
7
+ metadata?: Record<string, unknown>;
8
+ }
9
+ export interface ToolExecutionEnvelope<TPayload = unknown, TKind extends string = string> {
10
+ readonly version: 1;
11
+ readonly toolId: string;
12
+ readonly kind: TKind;
13
+ readonly mergeStrategy: ToolMergeStrategy;
14
+ readonly dedupeKey?: string;
15
+ readonly uiIntent?: UIIntent;
16
+ readonly data: TPayload;
17
+ }
18
+ export declare const createToolEnvelope: <TKind extends string, TPayload>(options: Omit<ToolExecutionEnvelope<TPayload, TKind>, "version">) => ToolExecutionEnvelope<TPayload, TKind>;
19
+ //# sourceMappingURL=envelope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../../src/ui/envelope.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,eAAe,GAAG,eAAe,CAAC;AAE9E,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,QAAQ,GAAG,YAAY,GAAG,UAAU,CAAC;AAEhF,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,qBAAqB,CAAC,QAAQ,GAAG,OAAO,EAAE,KAAK,SAAS,MAAM,GAAG,MAAM;IACtF,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,aAAa,EAAE,iBAAiB,CAAC;IAC1C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;CACzB;AAED,eAAO,MAAM,kBAAkB,GAAI,KAAK,SAAS,MAAM,EAAE,QAAQ,EAC/D,SAAS,IAAI,CAAC,qBAAqB,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,SAAS,CAAC,KAC/D,qBAAqB,CAAC,QAAQ,EAAE,KAAK,CAKvC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { createToolEnvelope, type ToolExecutionEnvelope, type ToolMergeStrategy, type UIIntent, type UIIntentAction, } from "./envelope";
2
+ export { createCanvasReducer, isSafeKey, mergeUniqueEntities, updateEntityInPlace, type CanvasContentState, type CanvasState, } from "./reducer";
3
+ export { defineCanvas } from "./define-canvas";
4
+ export { createViewRegistry, type CanvasRendererProps, type CanvasViewComponent, type CanvasViewContext, isValidSafeUrl, } from "./react";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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;AAE/C,OAAO,EACL,kBAAkB,EAClB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,cAAc,GACf,MAAM,SAAS,CAAC"}
@@ -0,0 +1,235 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
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
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/ui/index.ts
31
+ var ui_exports = {};
32
+ __export(ui_exports, {
33
+ createCanvasReducer: () => createCanvasReducer,
34
+ createToolEnvelope: () => createToolEnvelope,
35
+ createViewRegistry: () => createViewRegistry,
36
+ defineCanvas: () => defineCanvas,
37
+ isSafeKey: () => isSafeKey,
38
+ isValidSafeUrl: () => isValidSafeUrl,
39
+ mergeUniqueEntities: () => mergeUniqueEntities,
40
+ updateEntityInPlace: () => updateEntityInPlace
41
+ });
42
+ module.exports = __toCommonJS(ui_exports);
43
+
44
+ // src/ui/envelope.ts
45
+ var createToolEnvelope = (options) => {
46
+ return Object.freeze({
47
+ version: 1,
48
+ ...options
49
+ });
50
+ };
51
+
52
+ // src/ui/reducer.ts
53
+ var isSafeKey = (key) => {
54
+ return key !== "__proto__" && key !== "constructor" && key !== "prototype";
55
+ };
56
+ var filterSafeKeys = (source) => {
57
+ const result = {};
58
+ for (const key of Object.keys(source)) {
59
+ if (isSafeKey(key)) {
60
+ result[key] = source[key];
61
+ }
62
+ }
63
+ return result;
64
+ };
65
+ var mergeEntityArrays = (prevItems, incomingItems, dedupeKey) => {
66
+ const seenKeys = new Set(
67
+ prevItems.filter((item) => item && typeof item === "object" && dedupeKey in item).map((item) => String(item[dedupeKey]))
68
+ );
69
+ const uniqueIncoming = incomingItems.filter((item) => {
70
+ const keyVal = item && typeof item === "object" ? String(item[dedupeKey]) : null;
71
+ if (!keyVal || seenKeys.has(keyVal)) {
72
+ return false;
73
+ }
74
+ seenKeys.add(keyVal);
75
+ return true;
76
+ });
77
+ return [...prevItems, ...uniqueIncoming];
78
+ };
79
+ var mergeUniqueEntities = (prevContent, data, dedupeKey) => {
80
+ if (Array.isArray(data) && Array.isArray(prevContent)) {
81
+ return mergeEntityArrays(prevContent, data, dedupeKey);
82
+ }
83
+ if (!data || typeof data !== "object") {
84
+ return { ...prevContent };
85
+ }
86
+ const result = filterSafeKeys(prevContent);
87
+ const safeData = filterSafeKeys(data);
88
+ for (const key of Object.keys(safeData)) {
89
+ const incoming = safeData[key];
90
+ const prev = result[key];
91
+ result[key] = Array.isArray(incoming) && Array.isArray(prev) ? mergeEntityArrays(prev, incoming, dedupeKey) : incoming;
92
+ }
93
+ return result;
94
+ };
95
+ var updateEntityInArray = (items, data, dedupeKey) => {
96
+ let updated = false;
97
+ const targetId = String(data[dedupeKey]);
98
+ const newItems = items.map((item) => {
99
+ if (item && typeof item === "object" && String(item[dedupeKey]) === targetId) {
100
+ updated = true;
101
+ return { ...item, ...filterSafeKeys(data) };
102
+ }
103
+ return item;
104
+ });
105
+ return { updated, items: newItems };
106
+ };
107
+ var updateInternalArray = (target, safeData, dedupeKey) => {
108
+ for (const key of Object.keys(target)) {
109
+ if (!Array.isArray(target[key])) {
110
+ continue;
111
+ }
112
+ const { updated, items } = updateEntityInArray(target[key], safeData, dedupeKey);
113
+ if (updated) {
114
+ target[key] = items;
115
+ return true;
116
+ }
117
+ }
118
+ return false;
119
+ };
120
+ var updateEntityInPlace = (prevContent, data, dedupeKey) => {
121
+ if (!data || typeof data !== "object") {
122
+ return { ...prevContent };
123
+ }
124
+ const safeData = filterSafeKeys(data);
125
+ if (Array.isArray(prevContent)) {
126
+ return updateEntityInArray(prevContent, safeData, dedupeKey).items;
127
+ }
128
+ const result = filterSafeKeys(prevContent);
129
+ const targetId = safeData[dedupeKey] !== void 0 ? String(safeData[dedupeKey]) : null;
130
+ if (targetId && String(result[dedupeKey]) === targetId) {
131
+ return { ...result, ...safeData };
132
+ }
133
+ updateInternalArray(result, safeData, dedupeKey);
134
+ return result;
135
+ };
136
+ var createCanvasReducer = () => {
137
+ return (currentState, envelope) => {
138
+ const { kind, mergeStrategy, dedupeKey = "id", data, uiIntent } = envelope;
139
+ const prevContent = currentState?.content;
140
+ if (!prevContent || prevContent.kind !== kind || mergeStrategy === "REPLACE") {
141
+ return {
142
+ content: { kind, ...filterSafeKeys(data || {}) },
143
+ activeIntent: uiIntent
144
+ };
145
+ }
146
+ if (mergeStrategy === "APPEND_UNIQUE") {
147
+ return {
148
+ content: { kind, ...mergeUniqueEntities(prevContent, data, dedupeKey) },
149
+ activeIntent: uiIntent
150
+ };
151
+ }
152
+ if (mergeStrategy === "UPDATE_ENTITY") {
153
+ return {
154
+ content: { kind, ...updateEntityInPlace(prevContent, data, dedupeKey) },
155
+ activeIntent: uiIntent
156
+ };
157
+ }
158
+ return {
159
+ content: prevContent,
160
+ activeIntent: uiIntent ?? currentState?.activeIntent
161
+ };
162
+ };
163
+ };
164
+
165
+ // src/ui/define-canvas.ts
166
+ var defineCanvas = () => {
167
+ return {
168
+ createEnvelope: (options) => {
169
+ return createToolEnvelope(options);
170
+ },
171
+ canvasReducer: createCanvasReducer()
172
+ };
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
+ };
225
+ // Annotate the CommonJS export names for ESM import in node:
226
+ 0 && (module.exports = {
227
+ createCanvasReducer,
228
+ createToolEnvelope,
229
+ createViewRegistry,
230
+ defineCanvas,
231
+ isSafeKey,
232
+ isValidSafeUrl,
233
+ mergeUniqueEntities,
234
+ updateEntityInPlace
235
+ });
@@ -0,0 +1,146 @@
1
+ import {
2
+ createViewRegistry,
3
+ isValidSafeUrl
4
+ } from "../chunk-Z6QOMLZ2.mjs";
5
+ import "../chunk-Y6FXYEAI.mjs";
6
+
7
+ // src/ui/envelope.ts
8
+ var createToolEnvelope = (options) => {
9
+ return Object.freeze({
10
+ version: 1,
11
+ ...options
12
+ });
13
+ };
14
+
15
+ // src/ui/reducer.ts
16
+ var isSafeKey = (key) => {
17
+ return key !== "__proto__" && key !== "constructor" && key !== "prototype";
18
+ };
19
+ var filterSafeKeys = (source) => {
20
+ const result = {};
21
+ for (const key of Object.keys(source)) {
22
+ if (isSafeKey(key)) {
23
+ result[key] = source[key];
24
+ }
25
+ }
26
+ return result;
27
+ };
28
+ var mergeEntityArrays = (prevItems, incomingItems, dedupeKey) => {
29
+ const seenKeys = new Set(
30
+ prevItems.filter((item) => item && typeof item === "object" && dedupeKey in item).map((item) => String(item[dedupeKey]))
31
+ );
32
+ const uniqueIncoming = incomingItems.filter((item) => {
33
+ const keyVal = item && typeof item === "object" ? String(item[dedupeKey]) : null;
34
+ if (!keyVal || seenKeys.has(keyVal)) {
35
+ return false;
36
+ }
37
+ seenKeys.add(keyVal);
38
+ return true;
39
+ });
40
+ return [...prevItems, ...uniqueIncoming];
41
+ };
42
+ var mergeUniqueEntities = (prevContent, data, dedupeKey) => {
43
+ if (Array.isArray(data) && Array.isArray(prevContent)) {
44
+ return mergeEntityArrays(prevContent, data, dedupeKey);
45
+ }
46
+ if (!data || typeof data !== "object") {
47
+ return { ...prevContent };
48
+ }
49
+ const result = filterSafeKeys(prevContent);
50
+ const safeData = filterSafeKeys(data);
51
+ for (const key of Object.keys(safeData)) {
52
+ const incoming = safeData[key];
53
+ const prev = result[key];
54
+ result[key] = Array.isArray(incoming) && Array.isArray(prev) ? mergeEntityArrays(prev, incoming, dedupeKey) : incoming;
55
+ }
56
+ return result;
57
+ };
58
+ var updateEntityInArray = (items, data, dedupeKey) => {
59
+ let updated = false;
60
+ const targetId = String(data[dedupeKey]);
61
+ const newItems = items.map((item) => {
62
+ if (item && typeof item === "object" && String(item[dedupeKey]) === targetId) {
63
+ updated = true;
64
+ return { ...item, ...filterSafeKeys(data) };
65
+ }
66
+ return item;
67
+ });
68
+ return { updated, items: newItems };
69
+ };
70
+ var updateInternalArray = (target, safeData, dedupeKey) => {
71
+ for (const key of Object.keys(target)) {
72
+ if (!Array.isArray(target[key])) {
73
+ continue;
74
+ }
75
+ const { updated, items } = updateEntityInArray(target[key], safeData, dedupeKey);
76
+ if (updated) {
77
+ target[key] = items;
78
+ return true;
79
+ }
80
+ }
81
+ return false;
82
+ };
83
+ var updateEntityInPlace = (prevContent, data, dedupeKey) => {
84
+ if (!data || typeof data !== "object") {
85
+ return { ...prevContent };
86
+ }
87
+ const safeData = filterSafeKeys(data);
88
+ if (Array.isArray(prevContent)) {
89
+ return updateEntityInArray(prevContent, safeData, dedupeKey).items;
90
+ }
91
+ const result = filterSafeKeys(prevContent);
92
+ const targetId = safeData[dedupeKey] !== void 0 ? String(safeData[dedupeKey]) : null;
93
+ if (targetId && String(result[dedupeKey]) === targetId) {
94
+ return { ...result, ...safeData };
95
+ }
96
+ updateInternalArray(result, safeData, dedupeKey);
97
+ return result;
98
+ };
99
+ var createCanvasReducer = () => {
100
+ return (currentState, envelope) => {
101
+ const { kind, mergeStrategy, dedupeKey = "id", data, uiIntent } = envelope;
102
+ const prevContent = currentState?.content;
103
+ if (!prevContent || prevContent.kind !== kind || mergeStrategy === "REPLACE") {
104
+ return {
105
+ content: { kind, ...filterSafeKeys(data || {}) },
106
+ activeIntent: uiIntent
107
+ };
108
+ }
109
+ if (mergeStrategy === "APPEND_UNIQUE") {
110
+ return {
111
+ content: { kind, ...mergeUniqueEntities(prevContent, data, dedupeKey) },
112
+ activeIntent: uiIntent
113
+ };
114
+ }
115
+ if (mergeStrategy === "UPDATE_ENTITY") {
116
+ return {
117
+ content: { kind, ...updateEntityInPlace(prevContent, data, dedupeKey) },
118
+ activeIntent: uiIntent
119
+ };
120
+ }
121
+ return {
122
+ content: prevContent,
123
+ activeIntent: uiIntent ?? currentState?.activeIntent
124
+ };
125
+ };
126
+ };
127
+
128
+ // src/ui/define-canvas.ts
129
+ var defineCanvas = () => {
130
+ return {
131
+ createEnvelope: (options) => {
132
+ return createToolEnvelope(options);
133
+ },
134
+ canvasReducer: createCanvasReducer()
135
+ };
136
+ };
137
+ export {
138
+ createCanvasReducer,
139
+ createToolEnvelope,
140
+ createViewRegistry,
141
+ defineCanvas,
142
+ isSafeKey,
143
+ isValidSafeUrl,
144
+ mergeUniqueEntities,
145
+ updateEntityInPlace
146
+ };
@@ -0,0 +1,22 @@
1
+ import React from "react";
2
+ import type { UIIntent } from "../envelope";
3
+ import type { CanvasState } from "../reducer";
4
+ export interface CanvasViewContext {
5
+ onSendMessage?: (prompt: string) => void;
6
+ onSelectEntity?: (id: string, type?: string) => void;
7
+ isAgentBusy?: boolean;
8
+ }
9
+ export type CanvasViewComponent<TData> = React.FC<{
10
+ data: TData;
11
+ context: CanvasViewContext;
12
+ activeIntent?: UIIntent;
13
+ }>;
14
+ export interface CanvasRendererProps<TContentMap extends Record<string, unknown>> {
15
+ state: CanvasState<TContentMap> | null | undefined;
16
+ context?: CanvasViewContext;
17
+ }
18
+ export declare const createViewRegistry: <TContentMap extends Record<string, unknown>>(registry: { [K in keyof TContentMap]: CanvasViewComponent<TContentMap[K]>; }) => {
19
+ registry: { [K in keyof TContentMap]: CanvasViewComponent<TContentMap[K]>; };
20
+ CanvasRenderer: React.FC<CanvasRendererProps<TContentMap>>;
21
+ };
22
+ //# sourceMappingURL=create-view-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-view-registry.d.ts","sourceRoot":"","sources":["../../../src/ui/react/create-view-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,cAAc,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,MAAM,mBAAmB,CAAC,KAAK,IAAI,KAAK,CAAC,EAAE,CAAC;IAChD,IAAI,EAAE,KAAK,CAAC;IACZ,OAAO,EAAE,iBAAiB,CAAC;IAC3B,YAAY,CAAC,EAAE,QAAQ,CAAC;CACzB,CAAC,CAAC;AAEH,MAAM,WAAW,mBAAmB,CAAC,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC9E,KAAK,EAAE,WAAW,CAAC,WAAW,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;IACnD,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC7B;AAED,eAAO,MAAM,kBAAkB,GAAI,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5E,UAAU,GAAG,CAAC,IAAI,MAAM,WAAW,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GAAE;iBAA9D,CAAC;;CA4Bf,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { createViewRegistry, type CanvasRendererProps, type CanvasViewComponent, type CanvasViewContext, } from "./create-view-registry";
2
+ export { isValidSafeUrl } from "./sanitize";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/react/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,GACvB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
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
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/ui/react/index.ts
31
+ var react_exports = {};
32
+ __export(react_exports, {
33
+ createViewRegistry: () => createViewRegistry,
34
+ isValidSafeUrl: () => isValidSafeUrl
35
+ });
36
+ module.exports = __toCommonJS(react_exports);
37
+
38
+ // src/ui/react/create-view-registry.ts
39
+ var import_react = __toESM(require("react"));
40
+ var createViewRegistry = (registry) => {
41
+ const CanvasRenderer = ({
42
+ state,
43
+ context = {}
44
+ }) => {
45
+ if (!state?.content) {
46
+ return null;
47
+ }
48
+ const kind = state.content.kind;
49
+ const Component = registry[kind];
50
+ if (!Component) {
51
+ return null;
52
+ }
53
+ return import_react.default.createElement(Component, {
54
+ data: state.content,
55
+ context,
56
+ activeIntent: state.activeIntent
57
+ });
58
+ };
59
+ return {
60
+ registry,
61
+ CanvasRenderer
62
+ };
63
+ };
64
+
65
+ // src/ui/react/sanitize.ts
66
+ var ALLOWED_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
67
+ var isValidSafeUrl = (rawUrl) => {
68
+ if (!rawUrl || typeof rawUrl !== "string") {
69
+ return false;
70
+ }
71
+ const trimmed = rawUrl.trim();
72
+ if (!trimmed) {
73
+ return false;
74
+ }
75
+ if (trimmed.startsWith("#")) {
76
+ return true;
77
+ }
78
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
79
+ return true;
80
+ }
81
+ try {
82
+ const parsed = new URL(trimmed);
83
+ return ALLOWED_PROTOCOLS.has(parsed.protocol);
84
+ } catch {
85
+ return false;
86
+ }
87
+ };
88
+ // Annotate the CommonJS export names for ESM import in node:
89
+ 0 && (module.exports = {
90
+ createViewRegistry,
91
+ isValidSafeUrl
92
+ });
@@ -0,0 +1,9 @@
1
+ import {
2
+ createViewRegistry,
3
+ isValidSafeUrl
4
+ } from "../../chunk-Z6QOMLZ2.mjs";
5
+ import "../../chunk-Y6FXYEAI.mjs";
6
+ export {
7
+ createViewRegistry,
8
+ isValidSafeUrl
9
+ };
@@ -0,0 +1,2 @@
1
+ export declare const isValidSafeUrl: (rawUrl: string | null | undefined) => boolean;
2
+ //# sourceMappingURL=sanitize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../../src/ui/react/sanitize.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,cAAc,GAAI,QAAQ,MAAM,GAAG,IAAI,GAAG,SAAS,KAAG,OAwBlE,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { ToolExecutionEnvelope, UIIntent } from "./envelope";
2
+ export type CanvasContentState<TContentMap extends Record<string, unknown>> = {
3
+ [K in keyof TContentMap]: {
4
+ kind: K;
5
+ } & TContentMap[K];
6
+ }[keyof TContentMap] | null;
7
+ export interface CanvasState<TContentMap extends Record<string, unknown>> {
8
+ content: CanvasContentState<TContentMap>;
9
+ activeIntent?: UIIntent;
10
+ }
11
+ export declare const isSafeKey: (key: string) => boolean;
12
+ export declare const mergeUniqueEntities: (prevContent: Record<string, any>, data: any, dedupeKey: string) => Record<string, any>;
13
+ export declare const updateEntityInPlace: (prevContent: Record<string, any>, data: any, dedupeKey: string) => Record<string, any>;
14
+ export declare const createCanvasReducer: <TContentMap extends Record<string, unknown>>() => (currentState: CanvasState<TContentMap> | null | undefined, envelope: ToolExecutionEnvelope<unknown, Extract<keyof TContentMap, string>>) => CanvasState<TContentMap>;
15
+ //# sourceMappingURL=reducer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reducer.d.ts","sourceRoot":"","sources":["../../src/ui/reducer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAElE,MAAM,MAAM,kBAAkB,CAAC,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;KAC3E,CAAC,IAAI,MAAM,WAAW,GAAG;QAAE,IAAI,EAAE,CAAC,CAAA;KAAE,GAAG,WAAW,CAAC,CAAC,CAAC;CACvD,CAAC,MAAM,WAAW,CAAC,GAAG,IAAI,CAAC;AAE5B,MAAM,WAAW,WAAW,CAAC,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACtE,OAAO,EAAE,kBAAkB,CAAC,WAAW,CAAC,CAAC;IACzC,YAAY,CAAC,EAAE,QAAQ,CAAC;CACzB;AAED,eAAO,MAAM,SAAS,GAAI,KAAK,MAAM,KAAG,OAEvC,CAAC;AAmCF,eAAO,MAAM,mBAAmB,GAC9B,aAAa,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAChC,MAAM,GAAG,EACT,WAAW,MAAM,KAChB,MAAM,CAAC,MAAM,EAAE,GAAG,CAoBpB,CAAC;AAuCF,eAAO,MAAM,mBAAmB,GAC9B,aAAa,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAChC,MAAM,GAAG,EACT,WAAW,MAAM,KAChB,MAAM,CAAC,MAAM,EAAE,GAAG,CAmBpB,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAE3E,cAAc,WAAW,CAAC,WAAW,CAAC,GAAG,IAAI,GAAG,SAAS,EACzD,UAAU,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,WAAW,EAAE,MAAM,CAAC,CAAC,KAC3E,WAAW,CAAC,WAAW,CA8B3B,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "avantgate",
3
- "version": "2.0.0",
4
- "description": "Zero-infrastructure, in-process AI Application Firewall (AI-WAF) & privacy control plane for TypeScript: real-time prompt guardrails, zero-egress PII redaction, agent tool isolation, anti-IDOR defense, pre-flight token budgets, and multi-model failover.",
3
+ "version": "2.2.0",
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",
7
7
  "keywords": [
@@ -16,6 +16,10 @@
16
16
  "llm",
17
17
  "ai",
18
18
  "agent",
19
+ "canvas",
20
+ "headless-ui",
21
+ "tool-envelope",
22
+ "copilot-ui",
19
23
  "dual-channel",
20
24
  "tool-governance",
21
25
  "blast-radius",
@@ -65,6 +69,16 @@
65
69
  "import": "./dist/client/index.mjs",
66
70
  "require": "./dist/client/index.js"
67
71
  },
72
+ "./ui/react": {
73
+ "types": "./dist/ui/react/index.d.ts",
74
+ "import": "./dist/ui/react/index.mjs",
75
+ "require": "./dist/ui/react/index.js"
76
+ },
77
+ "./ui": {
78
+ "types": "./dist/ui/index.d.ts",
79
+ "import": "./dist/ui/index.mjs",
80
+ "require": "./dist/ui/index.js"
81
+ },
68
82
  "./package.json": "./package.json"
69
83
  },
70
84
  "peerDependencies": {
@@ -81,8 +95,9 @@
81
95
  "LICENSE"
82
96
  ],
83
97
  "scripts": {
84
- "build": "tsup src/index.ts src/finance/index.ts src/agent/index.ts src/workflow/index.ts src/client/index.ts --format cjs --format esm --clean && tsc --emitDeclarationOnly --outDir dist",
85
- "test": "tsx tests/avantgate.test.ts && tsx tests/preflight-budget.test.ts && tsx tests/sqlite-pricing-adapter.test.ts && tsx tests/financial-normalizer.test.ts && tsx tests/prompt-builder.test.ts && tsx tests/pii-extended.test.ts && tsx tests/output-dlp-secret-guard.test.ts && npm run test:agent && npm run test:workflow && npm run test:client",
98
+ "build": "tsup src/index.ts src/finance/index.ts src/agent/index.ts src/workflow/index.ts src/client/index.ts src/ui/index.ts src/ui/react/index.ts --format cjs --format esm --clean && tsc --emitDeclarationOnly --outDir dist",
99
+ "test": "tsx tests/avantgate.test.ts && tsx tests/preflight-budget.test.ts && tsx tests/sqlite-pricing-adapter.test.ts && tsx tests/financial-normalizer.test.ts && tsx tests/prompt-builder.test.ts && tsx tests/pii-extended.test.ts && tsx tests/output-dlp-secret-guard.test.ts && npm run test:agent && npm run test:workflow && npm run test:client && npm run test:ui",
100
+ "test:ui": "tsx tests/ui/envelope.test.ts && tsx tests/ui/reducer.test.ts && tsx tests/ui/sanitize.test.ts && tsx tests/ui/react-registry.test.tsx",
86
101
  "test:secrets": "tsx tests/output-dlp-secret-guard.test.ts",
87
102
  "test:pricing": "tsx tests/sqlite-pricing-adapter.test.ts",
88
103
  "test:finance": "tsx tests/financial-normalizer.test.ts",
@@ -92,12 +107,6 @@
92
107
  "test:workflow": "tsx tests/workflow/workflow-saga.test.ts && tsx tests/workflow/workflow-abort.test.ts",
93
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",
94
109
  "test:demo": "tsx tests/agent/prospect-ai-demo-scenario.test.ts",
95
- "gatewall": "npm --prefix gatewall run dev",
96
- "gatewall:dev": "npm --prefix gatewall run dev",
97
- "gatewall:build": "npm --prefix gatewall run build",
98
- "gatewall:seed": "npm --prefix gatewall run seed:mock",
99
- "gatewall:start": "npm --prefix gatewall run start",
100
- "gatewall:docker": "docker compose up -d",
101
110
  "lint": "tsc --noEmit",
102
111
  "prepublishOnly": "npm run build && npm test"
103
112
  },
@@ -124,3 +133,4 @@
124
133
  "url": "https://github.com/thienban/avantGate/issues"
125
134
  }
126
135
  }
136
+