avantgate 1.9.0 → 2.0.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
@@ -88,10 +88,10 @@ Contact our team at [contact@gatewall.fr](mailto:contact@gatewall.fr) for privat
88
88
 
89
89
  | Pillar | Core Capabilities & Architecture |
90
90
  |---|---|
91
- | 🛡️ **AI-WAF & Privacy** | • **Prompt Guardrails**: Blocks prompt injections, jailbreaks & exfiltration *pre-flight*.<br/>• **Zero-Egress DLP**: In-process redaction of emails, phone numbers, IBANs & EU tax IDs.<br/>• **Self-Repairing Outputs**: Native Zod validation with automatic JSON heuristic repair. |
92
- | 🛑 **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/>• **Infinite Loop Shield**: Detects and breaks recursive agent tool execution loops. |
93
- | 💰 **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/>• **Live Cost Ledger**: Token burn calculation & pricing adapters with zero external DB. |
94
- | ⚡ **Sagas & Telemetry** | • **Deterministic Sagas (`avantgate/workflow`)**: In-process FSM with automatic reverse compensation ($k-1 \to 0$).<br/>• **Human-in-the-Loop (HITL)**: Non-blocking suspension & approval queues for high-risk tools.<br/>• **Lightweight Telemetry (`avantgate/client`)**: < 1.7 KB client SDK & async audit bridge to GateWall. |
91
+ | 🛡️ **AI-WAF & Privacy** | • **Prompt Guardrails**: Blocks prompt injections, jailbreaks & exfiltration *pre-flight*.<br/>• **Zero-Egress DLP**: In-process redaction of emails, phone numbers, IBANs & EU tax IDs.<br/>• **Bidirectional Secret Guard**: Active DLP masking of API keys & database credentials in LLM outputs and error traces.<br/>• **Self-Repairing Outputs**: Native Zod validation with automatic JSON heuristic repair. |
92
+ | 🛑 **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
+ | 💰 **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
+ | ⚡ **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. |
95
95
 
96
96
  ---
97
97
 
@@ -104,8 +104,9 @@ Contact our team at [contact@gatewall.fr](mailto:contact@gatewall.fr) for privat
104
104
  | 💰 **FinOps & Cost** | [Pre-Flight Budget Guards](docs/finops/budget-guards.md) • [Pricing Adapters & SQLite](docs/finops/pricing-adapters.md) |
105
105
  | 🤖 **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
106
  | 🔄 **Deterministic Sagas** | [Durable Workflows Engine](docs/workflows/durable-workflows.md) |
107
- | 📊 **Observability** | [GateWall Cockpit Console](docs/observability/gatewall-cockpit.md) • [Telemetry & Browser SDK](docs/observability/telemetry-and-browser-sdk.md) |
107
+ | 📊 **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
108
  | 💶 **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) |
109
110
 
110
111
  ---
111
112
 
@@ -119,10 +120,11 @@ Contact our team at [contact@gatewall.fr](mailto:contact@gatewall.fr) for privat
119
120
  | **Prompt Injection Defense** | ❌ None | ⚠️ Passive detection | ✅ **Active Pre-Flight Guard (Blocks before spend)** |
120
121
  | **Agent Tool Data Isolation** | ❌ Entire DB entity in LLM | ❌ No agent tool awareness | ✅ **Dual-Channel DTO (`clientDto` vs `llmDto`)** |
121
122
  | **Row-Level Security & Anti-IDOR** | ❌ Manual code | ❌ Not supported | ✅ **Native `dataAccessGuard` & Domain Boundary** |
123
+ | **Bidirectional Idempotency** | ❌ Manual / none | ⚠️ Basic header relay | ✅ **Native causal key derivation + server guard + batch deduplication** |
122
124
  | **Infrastructure Overhead** | None | SaaS Subscription | ✅ **$0 / Zero Servers (Pure npm package)** |
123
125
  | **Multi-Model Failover** | ❌ App crashes | ⚠️ Proxy-dependent | ✅ **Built-in Fallback Router & Exponential Retry** |
124
126
  | **Zod Schema Auto-Repair** | ❌ No | ❌ No | ✅ **Built-in JSON Heuristic Repair** |
125
- | **Hierarchical Session Replay** | ❌ None | ⚠️ Flat span waterfall | ✅ **Causality Tree + Dual-Channel Isolation** |
127
+ | **Hierarchical Session Replay** | ❌ None | ⚠️ Flat span waterfall | ✅ **Causality Tree + In-Context Replay (`useTask`)** |
126
128
 
127
129
  ---
128
130
 
@@ -142,9 +144,9 @@ yarn add avantgate zod
142
144
  |---|---|
143
145
  | `avantgate` | Core control plane: token budgets, cost ledger, prompt guards, multi-model failover & Zod repair. |
144
146
  | `avantgate/finance` | Financial data normalizer (accounting parentheses, EU/US/UK/CH currencies & magnitudes). |
145
- | `avantgate/agent` | *(Preview / Experimental)* Durable step runner, Human-in-the-Loop, dual-channel PII tool isolation & storage adapters. |
147
+ | `avantgate/agent` | Durable step runner, Human-in-the-Loop, dual-channel PII tool isolation, server idempotency (`withServerIdempotency`), & storage adapters. |
146
148
  | `avantgate/workflow` | Deterministic sequential state machine, automatic reverse Saga rollback, durable HITL checkpoints & agent tool conversion. |
147
- | `avantgate/client` | Lightweight front-end SDK (< 1.7 KB) & React hook to stream browser security alerts & metrics directly to GateWall. |
149
+ | `avantgate/client` | Front-end SDK (< 1.7 KB) with in-context task replay (`useTask`, `createTaskRunner`), causal idempotency helpers (`getIdempotencyHeaders`), & GateWall telemetry adapter. |
148
150
 
149
151
  ---
150
152
 
@@ -0,0 +1,13 @@
1
+ import type { StepStorageAdapter } from "./types";
2
+ export interface IdempotencyStore {
3
+ get(key: string): Promise<unknown | undefined> | unknown | undefined;
4
+ set(key: string, value: unknown, ttlSeconds?: number): Promise<void> | void;
5
+ }
6
+ export interface ServerIdempotencyResult<TResult> {
7
+ result: TResult;
8
+ isCached: boolean;
9
+ }
10
+ export declare const withServerIdempotency: <TResult>(idempotencyKey: string | null | undefined, store: IdempotencyStore, handler: () => Promise<TResult>, ttlSeconds?: number) => Promise<ServerIdempotencyResult<TResult>>;
11
+ export declare const createMemoryIdempotencyStore: () => IdempotencyStore;
12
+ export declare const createAdapterIdempotencyStore: (adapter: StepStorageAdapter, namespace?: string) => IdempotencyStore;
13
+ //# sourceMappingURL=idempotency-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idempotency-guard.d.ts","sourceRoot":"","sources":["../../src/agent/idempotency-guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,GAAG,OAAO,GAAG,SAAS,CAAC;IACrE,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC7E;AAED,MAAM,WAAW,uBAAuB,CAAC,OAAO;IAC9C,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,qBAAqB,GAAU,OAAO,EACjD,gBAAgB,MAAM,GAAG,IAAI,GAAG,SAAS,EACzC,OAAO,gBAAgB,EACvB,SAAS,MAAM,OAAO,CAAC,OAAO,CAAC,EAC/B,mBAAkB,KACjB,OAAO,CAAC,uBAAuB,CAAC,OAAO,CAAC,CAc1C,CAAC;AAEF,eAAO,MAAM,4BAA4B,QAAO,gBAoB/C,CAAC;AAEF,eAAO,MAAM,6BAA6B,GACxC,SAAS,kBAAkB,EAC3B,kBAAyB,KACxB,gBAyBF,CAAC"}
@@ -15,4 +15,5 @@ export * from "./tool-invoker";
15
15
  export * from "./tool-state";
16
16
  export * from "./adapters";
17
17
  export * from "./telemetry";
18
+ export * from "./idempotency-guard";
18
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,OAAO,CAAC;AACtB,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,OAAO,CAAC;AACtB,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC"}
@@ -45,13 +45,16 @@ __export(agent_exports, {
45
45
  ToolSubCallQuotaError: () => ToolSubCallQuotaError,
46
46
  applyToolStrategy: () => applyToolStrategy,
47
47
  auditToolResult: () => auditToolResult,
48
+ createAdapterIdempotencyStore: () => createAdapterIdempotencyStore,
48
49
  createCustomStorageAdapter: () => createCustomStorageAdapter,
49
50
  createIsolatedTool: () => createIsolatedTool,
51
+ createMemoryIdempotencyStore: () => createMemoryIdempotencyStore,
50
52
  createStepRunner: () => createStepRunner,
51
53
  createTenantTool: () => createTenantTool,
52
54
  createToolInvoker: () => createToolInvoker,
53
55
  createToolSharedState: () => createToolSharedState,
54
- dto: () => dto
56
+ dto: () => dto,
57
+ withServerIdempotency: () => withServerIdempotency
55
58
  });
56
59
  module.exports = __toCommonJS(agent_exports);
57
60
 
@@ -2072,6 +2075,67 @@ var HttpTelemetryExporter = class {
2072
2075
  await this.flush();
2073
2076
  }
2074
2077
  };
2078
+
2079
+ // src/agent/idempotency-guard.ts
2080
+ var withServerIdempotency = async (idempotencyKey, store, handler, ttlSeconds = 86400) => {
2081
+ if (!idempotencyKey) {
2082
+ const result2 = await handler();
2083
+ return { result: result2, isCached: false };
2084
+ }
2085
+ const cached = await store.get(idempotencyKey);
2086
+ if (cached !== void 0) {
2087
+ return { result: cached, isCached: true };
2088
+ }
2089
+ const result = await handler();
2090
+ await store.set(idempotencyKey, result, ttlSeconds);
2091
+ return { result, isCached: false };
2092
+ };
2093
+ var createMemoryIdempotencyStore = () => {
2094
+ const cache = /* @__PURE__ */ new Map();
2095
+ return {
2096
+ get: (key) => {
2097
+ const entry = cache.get(key);
2098
+ if (!entry) {
2099
+ return void 0;
2100
+ }
2101
+ if (entry.expiresAt && Date.now() > entry.expiresAt) {
2102
+ cache.delete(key);
2103
+ return void 0;
2104
+ }
2105
+ return entry.value;
2106
+ },
2107
+ set: (key, value, ttlSeconds) => {
2108
+ const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1e3 : void 0;
2109
+ cache.set(key, { value, expiresAt });
2110
+ }
2111
+ };
2112
+ };
2113
+ var createAdapterIdempotencyStore = (adapter, namespace = "idempotency") => {
2114
+ return {
2115
+ get: async (key) => {
2116
+ const scopedKey = `${namespace}:${key}`;
2117
+ if (adapter.getStateValue) {
2118
+ const val = await adapter.getStateValue(scopedKey);
2119
+ return val === null ? void 0 : val;
2120
+ }
2121
+ if (adapter.getCachedToolResult) {
2122
+ const val = await adapter.getCachedToolResult(scopedKey);
2123
+ return val === null ? void 0 : val;
2124
+ }
2125
+ return void 0;
2126
+ },
2127
+ set: async (key, value, ttlSeconds) => {
2128
+ const scopedKey = `${namespace}:${key}`;
2129
+ if (adapter.setStateValue) {
2130
+ await adapter.setStateValue(scopedKey, value, ttlSeconds);
2131
+ return;
2132
+ }
2133
+ if (adapter.setCachedToolResult) {
2134
+ await adapter.setCachedToolResult(scopedKey, value, ttlSeconds ?? 86400);
2135
+ }
2136
+ }
2137
+ };
2138
+ };
2075
2139
  // Annotate the CommonJS export names for ESM import in node:
2076
2140
  0 && (module.exports = {
2077
2141
  AccessControlToolStrategy,
@@ -2099,11 +2163,14 @@ var HttpTelemetryExporter = class {
2099
2163
  ToolSubCallQuotaError,
2100
2164
  applyToolStrategy,
2101
2165
  auditToolResult,
2166
+ createAdapterIdempotencyStore,
2102
2167
  createCustomStorageAdapter,
2103
2168
  createIsolatedTool,
2169
+ createMemoryIdempotencyStore,
2104
2170
  createStepRunner,
2105
2171
  createTenantTool,
2106
2172
  createToolInvoker,
2107
2173
  createToolSharedState,
2108
- dto
2174
+ dto,
2175
+ withServerIdempotency
2109
2176
  });
@@ -1630,6 +1630,67 @@ var HttpTelemetryExporter = class {
1630
1630
  await this.flush();
1631
1631
  }
1632
1632
  };
1633
+
1634
+ // src/agent/idempotency-guard.ts
1635
+ var withServerIdempotency = async (idempotencyKey, store, handler, ttlSeconds = 86400) => {
1636
+ if (!idempotencyKey) {
1637
+ const result2 = await handler();
1638
+ return { result: result2, isCached: false };
1639
+ }
1640
+ const cached = await store.get(idempotencyKey);
1641
+ if (cached !== void 0) {
1642
+ return { result: cached, isCached: true };
1643
+ }
1644
+ const result = await handler();
1645
+ await store.set(idempotencyKey, result, ttlSeconds);
1646
+ return { result, isCached: false };
1647
+ };
1648
+ var createMemoryIdempotencyStore = () => {
1649
+ const cache = /* @__PURE__ */ new Map();
1650
+ return {
1651
+ get: (key) => {
1652
+ const entry = cache.get(key);
1653
+ if (!entry) {
1654
+ return void 0;
1655
+ }
1656
+ if (entry.expiresAt && Date.now() > entry.expiresAt) {
1657
+ cache.delete(key);
1658
+ return void 0;
1659
+ }
1660
+ return entry.value;
1661
+ },
1662
+ set: (key, value, ttlSeconds) => {
1663
+ const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1e3 : void 0;
1664
+ cache.set(key, { value, expiresAt });
1665
+ }
1666
+ };
1667
+ };
1668
+ var createAdapterIdempotencyStore = (adapter, namespace = "idempotency") => {
1669
+ return {
1670
+ get: async (key) => {
1671
+ const scopedKey = `${namespace}:${key}`;
1672
+ if (adapter.getStateValue) {
1673
+ const val = await adapter.getStateValue(scopedKey);
1674
+ return val === null ? void 0 : val;
1675
+ }
1676
+ if (adapter.getCachedToolResult) {
1677
+ const val = await adapter.getCachedToolResult(scopedKey);
1678
+ return val === null ? void 0 : val;
1679
+ }
1680
+ return void 0;
1681
+ },
1682
+ set: async (key, value, ttlSeconds) => {
1683
+ const scopedKey = `${namespace}:${key}`;
1684
+ if (adapter.setStateValue) {
1685
+ await adapter.setStateValue(scopedKey, value, ttlSeconds);
1686
+ return;
1687
+ }
1688
+ if (adapter.setCachedToolResult) {
1689
+ await adapter.setCachedToolResult(scopedKey, value, ttlSeconds ?? 86400);
1690
+ }
1691
+ }
1692
+ };
1693
+ };
1633
1694
  export {
1634
1695
  AccessControlToolStrategy,
1635
1696
  AgentToolFactory,
@@ -1656,11 +1717,14 @@ export {
1656
1717
  ToolSubCallQuotaError,
1657
1718
  applyToolStrategy,
1658
1719
  auditToolResult,
1720
+ createAdapterIdempotencyStore,
1659
1721
  createCustomStorageAdapter,
1660
1722
  createIsolatedTool,
1723
+ createMemoryIdempotencyStore,
1661
1724
  createStepRunner,
1662
1725
  createTenantTool,
1663
1726
  createToolInvoker,
1664
1727
  createToolSharedState,
1665
- dto
1728
+ dto,
1729
+ withServerIdempotency
1666
1730
  };
@@ -3,7 +3,7 @@ export { createClient, type Client, type TrackDataRenderedOptions, type TrackFee
3
3
  export { useTask } from "./useTask";
4
4
  export { useTelemetry } from "./useTelemetry";
5
5
  export { createTaskRunner, type TaskRunner, type TaskRunnerOptions, } from "./task-runner";
6
- export { deriveOpaqueTaskId, generateRunId, createInitialTaskState, validateRetryEligibility, } from "./task-utils";
6
+ export { deriveOpaqueTaskId, generateRunId, createInitialTaskState, validateRetryEligibility, getIdempotencyKey, getIdempotencyHeaders, } from "./task-utils";
7
7
  export type { TaskExecutionContext, TaskState, UseTaskOptions, UseTaskReturn, } from "./task-types";
8
8
  export type { BrowserTelemetryExporterConfig, ClientDataRenderedEvent, ClientSecurityAlertEvent, ClientTelemetryEvent, ClientTelemetryIngestPayload, UserFeedbackEvent, } from "./types";
9
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EACL,YAAY,EACZ,KAAK,MAAM,EACX,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,GAC/B,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EACL,gBAAgB,EAChB,KAAK,UAAU,EACf,KAAK,iBAAiB,GACvB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,cAAc,CAAC;AAEtB,YAAY,EACV,oBAAoB,EACpB,SAAS,EACT,cAAc,EACd,aAAa,GACd,MAAM,cAAc,CAAC;AAGtB,YAAY,EACV,8BAA8B,EAC9B,uBAAuB,EACvB,wBAAwB,EACxB,oBAAoB,EACpB,4BAA4B,EAC5B,iBAAiB,GAClB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EACL,YAAY,EACZ,KAAK,MAAM,EACX,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,GAC/B,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EACL,gBAAgB,EAChB,KAAK,UAAU,EACf,KAAK,iBAAiB,GACvB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,wBAAwB,EACxB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,cAAc,CAAC;AAEtB,YAAY,EACV,oBAAoB,EACpB,SAAS,EACT,cAAc,EACd,aAAa,GACd,MAAM,cAAc,CAAC;AAGtB,YAAY,EACV,8BAA8B,EAC9B,uBAAuB,EACvB,wBAAwB,EACxB,oBAAoB,EACpB,4BAA4B,EAC5B,iBAAiB,GAClB,MAAM,SAAS,CAAC"}
@@ -26,6 +26,8 @@ __export(client_exports, {
26
26
  createTaskRunner: () => createTaskRunner,
27
27
  deriveOpaqueTaskId: () => deriveOpaqueTaskId,
28
28
  generateRunId: () => generateRunId,
29
+ getIdempotencyHeaders: () => getIdempotencyHeaders,
30
+ getIdempotencyKey: () => getIdempotencyKey,
29
31
  useTask: () => useTask,
30
32
  useTelemetry: () => useTelemetry,
31
33
  validateRetryEligibility: () => validateRetryEligibility
@@ -255,6 +257,10 @@ var validateRetryEligibility = ({
255
257
  throw new Error("Cannot retry: no previous execution input found");
256
258
  }
257
259
  };
260
+ var getIdempotencyKey = (ctx) => ctx.parentRunId ?? ctx.runId;
261
+ var getIdempotencyHeaders = (ctx) => ({
262
+ "Idempotency-Key": getIdempotencyKey(ctx)
263
+ });
258
264
 
259
265
  // src/client/task-runner.ts
260
266
  var createTaskRunner = (initialOptions) => {
@@ -308,6 +314,7 @@ var createTaskRunner = (initialOptions) => {
308
314
  markExecutionStart(newRunId, parentRunId);
309
315
  try {
310
316
  const result = await options.handler(input, {
317
+ runId: newRunId,
311
318
  parentRunId,
312
319
  attempt: state.attempts,
313
320
  taskId: opaqueTaskId,
@@ -462,6 +469,8 @@ var useTelemetry = (config) => {
462
469
  createTaskRunner,
463
470
  deriveOpaqueTaskId,
464
471
  generateRunId,
472
+ getIdempotencyHeaders,
473
+ getIdempotencyKey,
465
474
  useTask,
466
475
  useTelemetry,
467
476
  validateRetryEligibility
@@ -223,6 +223,10 @@ var validateRetryEligibility = ({
223
223
  throw new Error("Cannot retry: no previous execution input found");
224
224
  }
225
225
  };
226
+ var getIdempotencyKey = (ctx) => ctx.parentRunId ?? ctx.runId;
227
+ var getIdempotencyHeaders = (ctx) => ({
228
+ "Idempotency-Key": getIdempotencyKey(ctx)
229
+ });
226
230
 
227
231
  // src/client/task-runner.ts
228
232
  var createTaskRunner = (initialOptions) => {
@@ -276,6 +280,7 @@ var createTaskRunner = (initialOptions) => {
276
280
  markExecutionStart(newRunId, parentRunId);
277
281
  try {
278
282
  const result = await options.handler(input, {
283
+ runId: newRunId,
279
284
  parentRunId,
280
285
  attempt: state.attempts,
281
286
  taskId: opaqueTaskId,
@@ -429,6 +434,8 @@ export {
429
434
  createTaskRunner,
430
435
  deriveOpaqueTaskId,
431
436
  generateRunId,
437
+ getIdempotencyHeaders,
438
+ getIdempotencyKey,
432
439
  useTask,
433
440
  useTelemetry,
434
441
  validateRetryEligibility
@@ -1 +1 @@
1
- {"version":3,"file":"task-runner.d.ts","sourceRoot":"","sources":["../../src/client/task-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQzD,MAAM,MAAM,iBAAiB,CAAC,MAAM,EAAE,OAAO,IAAI,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEjF,MAAM,WAAW,UAAU,CAAC,MAAM,EAAE,OAAO;IACzC,QAAQ,EAAE,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;IACnC,SAAS,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IACzE,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,KAAK,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,aAAa,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,IAAI,CAAC;IAC9E,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,eAAO,MAAM,gBAAgB,GAAI,MAAM,EAAE,OAAO,EAC9C,gBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9C,UAAU,CAAC,MAAM,EAAE,OAAO,CAgI5B,CAAC"}
1
+ {"version":3,"file":"task-runner.d.ts","sourceRoot":"","sources":["../../src/client/task-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQzD,MAAM,MAAM,iBAAiB,CAAC,MAAM,EAAE,OAAO,IAAI,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEjF,MAAM,WAAW,UAAU,CAAC,MAAM,EAAE,OAAO;IACzC,QAAQ,EAAE,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;IACnC,SAAS,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IACzE,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,KAAK,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,aAAa,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,IAAI,CAAC;IAC9E,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,eAAO,MAAM,gBAAgB,GAAI,MAAM,EAAE,OAAO,EAC9C,gBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9C,UAAU,CAAC,MAAM,EAAE,OAAO,CAiI5B,CAAC"}
@@ -2,6 +2,7 @@
2
2
  * Context provided to task handlers during execution.
3
3
  */
4
4
  export interface TaskExecutionContext {
5
+ runId: string;
5
6
  parentRunId?: string;
6
7
  attempt: number;
7
8
  taskId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"task-types.d.ts","sourceRoot":"","sources":["../../src/client/task-types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,MAAM,EAAE,OAAO;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5E,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,SAAS,CAAC,OAAO;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,MAAM,EAAE,OAAO,CAAE,SAAQ,SAAS,CAAC,OAAO,CAAC;IACxE,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,KAAK,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB"}
1
+ {"version":3,"file":"task-types.d.ts","sourceRoot":"","sources":["../../src/client/task-types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,MAAM,EAAE,OAAO;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5E,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,SAAS,CAAC,OAAO;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,MAAM,EAAE,OAAO,CAAE,SAAQ,SAAS,CAAC,OAAO,CAAC;IACxE,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,KAAK,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB"}
@@ -26,4 +26,12 @@ export interface RetryValidationParams {
26
26
  * Why: Protects against FinOps token budget exhaustion and UI double-click race conditions.
27
27
  */
28
28
  export declare const validateRetryEligibility: ({ isRunning, attemptCount, maxRetries, hasPreviousInput, }: RetryValidationParams) => void;
29
+ export declare const getIdempotencyKey: (ctx: {
30
+ runId: string;
31
+ parentRunId?: string | null;
32
+ }) => string;
33
+ export declare const getIdempotencyHeaders: (ctx: {
34
+ runId: string;
35
+ parentRunId?: string | null;
36
+ }) => Record<string, string>;
29
37
  //# sourceMappingURL=task-utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"task-utils.d.ts","sourceRoot":"","sources":["../../src/client/task-utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,EAAE,aAAa,MAAM,KAAG,MAS1E,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,MAAM,KAAG,MAI9C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,GAAI,OAAO,EAC5C,QAAQ,MAAM,EACd,WAAW,MAAM,KAChB,SAAS,CAAC,OAAO,CAWlB,CAAC;AAEH,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GAAI,4DAKtC,qBAAqB,KAAG,IAU1B,CAAC"}
1
+ {"version":3,"file":"task-utils.d.ts","sourceRoot":"","sources":["../../src/client/task-utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,EAAE,aAAa,MAAM,KAAG,MAS1E,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,MAAM,KAAG,MAI9C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,GAAI,OAAO,EAC5C,QAAQ,MAAM,EACd,WAAW,MAAM,KAChB,SAAS,CAAC,OAAO,CAWlB,CAAC;AAEH,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GAAI,4DAKtC,qBAAqB,KAAG,IAU1B,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,KAAK;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,KAAG,MAAsC,CAAC;AAE3C,eAAO,MAAM,qBAAqB,GAAI,KAAK;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAEvB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "avantgate",
3
- "version": "1.9.0",
3
+ "version": "2.0.0",
4
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.",
5
5
  "author": "Gatewall Team",
6
6
  "license": "MIT",
@@ -88,7 +88,7 @@
88
88
  "test:finance": "tsx tests/financial-normalizer.test.ts",
89
89
  "test:prompts": "tsx tests/prompt-builder.test.ts",
90
90
  "test:pii": "tsx tests/pii-extended.test.ts",
91
- "test:agent": "tsx tests/agent/step-runner.test.ts && tsx tests/agent/isolated-tool.test.ts && tsx tests/agent/dto-pattern.test.ts && tsx tests/agent/tool-patterns.test.ts && tsx tests/agent/storage-adapters.test.ts && tsx tests/agent/tool-aliasing.test.ts && tsx tests/agent/tool-chaining.test.ts && tsx tests/agent/tool-storage.test.ts && tsx tests/agent/telemetry-exporter.test.ts && tsx tests/agent/platform-adapter.test.ts && tsx tests/agent/tool-governance.test.ts && tsx tests/agent/tool-impact.test.ts",
91
+ "test:agent": "tsx tests/agent/step-runner.test.ts && tsx tests/agent/isolated-tool.test.ts && tsx tests/agent/dto-pattern.test.ts && tsx tests/agent/tool-patterns.test.ts && tsx tests/agent/storage-adapters.test.ts && tsx tests/agent/tool-aliasing.test.ts && tsx tests/agent/tool-chaining.test.ts && tsx tests/agent/tool-storage.test.ts && tsx tests/agent/telemetry-exporter.test.ts && tsx tests/agent/platform-adapter.test.ts && tsx tests/agent/tool-governance.test.ts && tsx tests/agent/tool-impact.test.ts && tsx tests/agent/idempotency-guard.test.ts",
92
92
  "test:workflow": "tsx tests/workflow/workflow-saga.test.ts && tsx tests/workflow/workflow-abort.test.ts",
93
93
  "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
94
  "test:demo": "tsx tests/agent/prospect-ai-demo-scenario.test.ts",