avantgate 1.9.0 → 2.1.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 +26 -17
- package/dist/agent/idempotency-guard.d.ts +13 -0
- package/dist/agent/idempotency-guard.d.ts.map +1 -0
- package/dist/agent/index.d.ts +1 -0
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +69 -2
- package/dist/agent/index.mjs +65 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +9 -0
- package/dist/client/index.mjs +7 -0
- package/dist/client/task-runner.d.ts.map +1 -1
- package/dist/client/task-types.d.ts +1 -0
- package/dist/client/task-types.d.ts.map +1 -1
- package/dist/client/task-utils.d.ts +8 -0
- package/dist/client/task-utils.d.ts.map +1 -1
- package/dist/ui/define-canvas.d.ts +6 -0
- package/dist/ui/define-canvas.d.ts.map +1 -0
- package/dist/ui/envelope.d.ts +19 -0
- package/dist/ui/envelope.d.ts.map +1 -0
- package/dist/ui/index.d.ts +4 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +170 -0
- package/dist/ui/index.mjs +140 -0
- package/dist/ui/react/create-view-registry.d.ts +22 -0
- package/dist/ui/react/create-view-registry.d.ts.map +1 -0
- package/dist/ui/react/index.d.ts +3 -0
- package/dist/ui/react/index.d.ts.map +1 -0
- package/dist/ui/react/index.js +92 -0
- package/dist/ui/react/index.mjs +56 -0
- package/dist/ui/react/sanitize.d.ts +2 -0
- package/dist/ui/react/sanitize.d.ts.map +1 -0
- package/dist/ui/reducer.d.ts +15 -0
- package/dist/ui/reducer.d.ts.map +1 -0
- package/package.json +20 -5
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
|
|
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
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
[](https://www.typescriptlang.org/)
|
|
@@ -73,7 +73,7 @@ bun run dev # or npm run dev
|
|
|
73
73
|
| **🛡️ Loop Shield (Anti-Cycle Guard)** | Early visual detection of recursive agent loops and aberrant repetitive tool execution cycles. |
|
|
74
74
|
| **💾 Zero-External-DB SQLite Storage** | Zero setup overhead: persistent storage uses embedded SQLite (`gatewall/data/gatewall.db`) without requiring PostgreSQL, Redis, or ClickHouse. |
|
|
75
75
|
|
|
76
|
-
> 💡 **Agent Integration Recipes:** See [
|
|
76
|
+
> 💡 **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
77
|
|
|
78
78
|
---
|
|
79
79
|
|
|
@@ -88,10 +88,11 @@ 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
|
|
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
|
+
| 🎨 **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
96
|
|
|
96
97
|
---
|
|
97
98
|
|
|
@@ -99,13 +100,15 @@ Contact our team at [contact@gatewall.fr](mailto:contact@gatewall.fr) for privat
|
|
|
99
100
|
|
|
100
101
|
| Category | In-Depth Guides |
|
|
101
102
|
|---|---|
|
|
102
|
-
| 🚀 **Quickstart** | [Getting Started](docs/getting-started.md) • [Integration Cookbook](
|
|
103
|
+
| 🚀 **Quickstart** | [Getting Started](docs/getting-started.md) • [Integration Cookbook](examples/README.md) |
|
|
103
104
|
| 🛡️ **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
105
|
| 💰 **FinOps & Cost** | [Pre-Flight Budget Guards](docs/finops/budget-guards.md) • [Pricing Adapters & SQLite](docs/finops/pricing-adapters.md) |
|
|
105
106
|
| 🤖 **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
107
|
| 🔄 **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) |
|
|
108
|
+
| 📊 **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
109
|
| 💶 **Accounting** | [Financial Normalizer](docs/finance/normalizer.md) |
|
|
110
|
+
| 🎨 **Presentation Plane** | [Headless UI Canvas & React Bindings](docs/ui/headless-canvas.md) |
|
|
111
|
+
| 🚀 **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) |
|
|
109
112
|
|
|
110
113
|
---
|
|
111
114
|
|
|
@@ -119,10 +122,12 @@ Contact our team at [contact@gatewall.fr](mailto:contact@gatewall.fr) for privat
|
|
|
119
122
|
| **Prompt Injection Defense** | ❌ None | ⚠️ Passive detection | ✅ **Active Pre-Flight Guard (Blocks before spend)** |
|
|
120
123
|
| **Agent Tool Data Isolation** | ❌ Entire DB entity in LLM | ❌ No agent tool awareness | ✅ **Dual-Channel DTO (`clientDto` vs `llmDto`)** |
|
|
121
124
|
| **Row-Level Security & Anti-IDOR** | ❌ Manual code | ❌ Not supported | ✅ **Native `dataAccessGuard` & Domain Boundary** |
|
|
125
|
+
| **Bidirectional Idempotency** | ❌ Manual / none | ⚠️ Basic header relay | ✅ **Native causal key derivation + server guard + batch deduplication** |
|
|
122
126
|
| **Infrastructure Overhead** | None | SaaS Subscription | ✅ **$0 / Zero Servers (Pure npm package)** |
|
|
123
127
|
| **Multi-Model Failover** | ❌ App crashes | ⚠️ Proxy-dependent | ✅ **Built-in Fallback Router & Exponential Retry** |
|
|
124
128
|
| **Zod Schema Auto-Repair** | ❌ No | ❌ No | ✅ **Built-in JSON Heuristic Repair** |
|
|
125
|
-
| **Hierarchical Session Replay** | ❌ None | ⚠️ Flat span waterfall | ✅ **Causality Tree +
|
|
129
|
+
| **Hierarchical Session Replay** | ❌ None | ⚠️ Flat span waterfall | ✅ **Causality Tree + In-Context Replay (`useTask`)** |
|
|
130
|
+
| **Headless UI Canvas State** | ❌ Manual parsing | ❌ Not supported | ✅ **Canonical Envelopes + Parallel Reducer (`avantgate/ui`)** |
|
|
126
131
|
|
|
127
132
|
---
|
|
128
133
|
|
|
@@ -138,13 +143,17 @@ yarn add avantgate zod
|
|
|
138
143
|
|
|
139
144
|
### 🧩 Subpath Exports
|
|
140
145
|
|
|
141
|
-
| Import Path | Description |
|
|
142
|
-
|
|
143
|
-
| `avantgate` | Core control plane: token budgets, cost ledger, prompt guards, multi-model failover & Zod repair. |
|
|
144
|
-
| `avantgate/finance` | Financial data normalizer (accounting parentheses, EU/US/UK/CH currencies & magnitudes). |
|
|
145
|
-
| `avantgate/agent` |
|
|
146
|
-
| `avantgate/workflow` | Deterministic sequential state machine, automatic reverse Saga rollback, durable HITL checkpoints & agent tool conversion. |
|
|
147
|
-
| `avantgate/client` |
|
|
146
|
+
| Import Path | Description | Documentation |
|
|
147
|
+
|---|---|---|
|
|
148
|
+
| `avantgate` | Core control plane: token budgets, cost ledger, prompt guards, multi-model failover & Zod repair. | [Getting Started](docs/getting-started.md) |
|
|
149
|
+
| `avantgate/finance` | Financial data normalizer (accounting parentheses, EU/US/UK/CH currencies & magnitudes). | [Financial Normalizer](docs/finance/normalizer.md) |
|
|
150
|
+
| `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) |
|
|
151
|
+
| `avantgate/workflow` | Deterministic sequential state machine, automatic reverse Saga rollback, durable HITL checkpoints & agent tool conversion. | [Durable Workflows](docs/workflows/durable-workflows.md) |
|
|
152
|
+
| `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) |
|
|
153
|
+
| `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) |
|
|
154
|
+
| `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) |
|
|
155
|
+
|
|
156
|
+
> 💡 **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).
|
|
148
157
|
|
|
149
158
|
---
|
|
150
159
|
|
|
@@ -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"}
|
package/dist/agent/index.d.ts
CHANGED
|
@@ -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"}
|
package/dist/agent/index.js
CHANGED
|
@@ -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
|
});
|
package/dist/agent/index.mjs
CHANGED
|
@@ -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
|
};
|
package/dist/client/index.d.ts
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/client/index.js
CHANGED
|
@@ -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
|
package/dist/client/index.mjs
CHANGED
|
@@ -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,
|
|
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"}
|
|
@@ -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"}
|
|
@@ -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,4 @@
|
|
|
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
|
+
//# 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"}
|
package/dist/ui/index.js
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/ui/index.ts
|
|
21
|
+
var ui_exports = {};
|
|
22
|
+
__export(ui_exports, {
|
|
23
|
+
createCanvasReducer: () => createCanvasReducer,
|
|
24
|
+
createToolEnvelope: () => createToolEnvelope,
|
|
25
|
+
defineCanvas: () => defineCanvas,
|
|
26
|
+
isSafeKey: () => isSafeKey,
|
|
27
|
+
mergeUniqueEntities: () => mergeUniqueEntities,
|
|
28
|
+
updateEntityInPlace: () => updateEntityInPlace
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(ui_exports);
|
|
31
|
+
|
|
32
|
+
// src/ui/envelope.ts
|
|
33
|
+
var createToolEnvelope = (options) => {
|
|
34
|
+
return Object.freeze({
|
|
35
|
+
version: 1,
|
|
36
|
+
...options
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// src/ui/reducer.ts
|
|
41
|
+
var isSafeKey = (key) => {
|
|
42
|
+
return key !== "__proto__" && key !== "constructor" && key !== "prototype";
|
|
43
|
+
};
|
|
44
|
+
var filterSafeKeys = (source) => {
|
|
45
|
+
const result = {};
|
|
46
|
+
for (const key of Object.keys(source)) {
|
|
47
|
+
if (isSafeKey(key)) {
|
|
48
|
+
result[key] = source[key];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
};
|
|
53
|
+
var mergeEntityArrays = (prevItems, incomingItems, dedupeKey) => {
|
|
54
|
+
const seenKeys = new Set(
|
|
55
|
+
prevItems.filter((item) => item && typeof item === "object" && dedupeKey in item).map((item) => String(item[dedupeKey]))
|
|
56
|
+
);
|
|
57
|
+
const uniqueIncoming = incomingItems.filter((item) => {
|
|
58
|
+
const keyVal = item && typeof item === "object" ? String(item[dedupeKey]) : null;
|
|
59
|
+
if (!keyVal || seenKeys.has(keyVal)) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
seenKeys.add(keyVal);
|
|
63
|
+
return true;
|
|
64
|
+
});
|
|
65
|
+
return [...prevItems, ...uniqueIncoming];
|
|
66
|
+
};
|
|
67
|
+
var mergeUniqueEntities = (prevContent, data, dedupeKey) => {
|
|
68
|
+
if (Array.isArray(data) && Array.isArray(prevContent)) {
|
|
69
|
+
return mergeEntityArrays(prevContent, data, dedupeKey);
|
|
70
|
+
}
|
|
71
|
+
if (!data || typeof data !== "object") {
|
|
72
|
+
return { ...prevContent };
|
|
73
|
+
}
|
|
74
|
+
const result = filterSafeKeys(prevContent);
|
|
75
|
+
const safeData = filterSafeKeys(data);
|
|
76
|
+
for (const key of Object.keys(safeData)) {
|
|
77
|
+
const incoming = safeData[key];
|
|
78
|
+
const prev = result[key];
|
|
79
|
+
result[key] = Array.isArray(incoming) && Array.isArray(prev) ? mergeEntityArrays(prev, incoming, dedupeKey) : incoming;
|
|
80
|
+
}
|
|
81
|
+
return result;
|
|
82
|
+
};
|
|
83
|
+
var updateEntityInArray = (items, data, dedupeKey) => {
|
|
84
|
+
let updated = false;
|
|
85
|
+
const targetId = String(data[dedupeKey]);
|
|
86
|
+
const newItems = items.map((item) => {
|
|
87
|
+
if (item && typeof item === "object" && String(item[dedupeKey]) === targetId) {
|
|
88
|
+
updated = true;
|
|
89
|
+
return { ...item, ...filterSafeKeys(data) };
|
|
90
|
+
}
|
|
91
|
+
return item;
|
|
92
|
+
});
|
|
93
|
+
return { updated, items: newItems };
|
|
94
|
+
};
|
|
95
|
+
var updateInternalArray = (target, safeData, dedupeKey) => {
|
|
96
|
+
for (const key of Object.keys(target)) {
|
|
97
|
+
if (!Array.isArray(target[key])) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const { updated, items } = updateEntityInArray(target[key], safeData, dedupeKey);
|
|
101
|
+
if (updated) {
|
|
102
|
+
target[key] = items;
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
};
|
|
108
|
+
var updateEntityInPlace = (prevContent, data, dedupeKey) => {
|
|
109
|
+
if (!data || typeof data !== "object") {
|
|
110
|
+
return { ...prevContent };
|
|
111
|
+
}
|
|
112
|
+
const safeData = filterSafeKeys(data);
|
|
113
|
+
if (Array.isArray(prevContent)) {
|
|
114
|
+
return updateEntityInArray(prevContent, safeData, dedupeKey).items;
|
|
115
|
+
}
|
|
116
|
+
const result = filterSafeKeys(prevContent);
|
|
117
|
+
const targetId = safeData[dedupeKey] !== void 0 ? String(safeData[dedupeKey]) : null;
|
|
118
|
+
if (targetId && String(result[dedupeKey]) === targetId) {
|
|
119
|
+
return { ...result, ...safeData };
|
|
120
|
+
}
|
|
121
|
+
updateInternalArray(result, safeData, dedupeKey);
|
|
122
|
+
return result;
|
|
123
|
+
};
|
|
124
|
+
var createCanvasReducer = () => {
|
|
125
|
+
return (currentState, envelope) => {
|
|
126
|
+
const { kind, mergeStrategy, dedupeKey = "id", data, uiIntent } = envelope;
|
|
127
|
+
const prevContent = currentState?.content;
|
|
128
|
+
if (!prevContent || prevContent.kind !== kind || mergeStrategy === "REPLACE") {
|
|
129
|
+
return {
|
|
130
|
+
content: { kind, ...filterSafeKeys(data || {}) },
|
|
131
|
+
activeIntent: uiIntent
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
if (mergeStrategy === "APPEND_UNIQUE") {
|
|
135
|
+
return {
|
|
136
|
+
content: { kind, ...mergeUniqueEntities(prevContent, data, dedupeKey) },
|
|
137
|
+
activeIntent: uiIntent
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
if (mergeStrategy === "UPDATE_ENTITY") {
|
|
141
|
+
return {
|
|
142
|
+
content: { kind, ...updateEntityInPlace(prevContent, data, dedupeKey) },
|
|
143
|
+
activeIntent: uiIntent
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
content: prevContent,
|
|
148
|
+
activeIntent: uiIntent ?? currentState?.activeIntent
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
// src/ui/define-canvas.ts
|
|
154
|
+
var defineCanvas = () => {
|
|
155
|
+
return {
|
|
156
|
+
createEnvelope: (options) => {
|
|
157
|
+
return createToolEnvelope(options);
|
|
158
|
+
},
|
|
159
|
+
canvasReducer: createCanvasReducer()
|
|
160
|
+
};
|
|
161
|
+
};
|
|
162
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
163
|
+
0 && (module.exports = {
|
|
164
|
+
createCanvasReducer,
|
|
165
|
+
createToolEnvelope,
|
|
166
|
+
defineCanvas,
|
|
167
|
+
isSafeKey,
|
|
168
|
+
mergeUniqueEntities,
|
|
169
|
+
updateEntityInPlace
|
|
170
|
+
});
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import "../chunk-Y6FXYEAI.mjs";
|
|
2
|
+
|
|
3
|
+
// src/ui/envelope.ts
|
|
4
|
+
var createToolEnvelope = (options) => {
|
|
5
|
+
return Object.freeze({
|
|
6
|
+
version: 1,
|
|
7
|
+
...options
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// src/ui/reducer.ts
|
|
12
|
+
var isSafeKey = (key) => {
|
|
13
|
+
return key !== "__proto__" && key !== "constructor" && key !== "prototype";
|
|
14
|
+
};
|
|
15
|
+
var filterSafeKeys = (source) => {
|
|
16
|
+
const result = {};
|
|
17
|
+
for (const key of Object.keys(source)) {
|
|
18
|
+
if (isSafeKey(key)) {
|
|
19
|
+
result[key] = source[key];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return result;
|
|
23
|
+
};
|
|
24
|
+
var mergeEntityArrays = (prevItems, incomingItems, dedupeKey) => {
|
|
25
|
+
const seenKeys = new Set(
|
|
26
|
+
prevItems.filter((item) => item && typeof item === "object" && dedupeKey in item).map((item) => String(item[dedupeKey]))
|
|
27
|
+
);
|
|
28
|
+
const uniqueIncoming = incomingItems.filter((item) => {
|
|
29
|
+
const keyVal = item && typeof item === "object" ? String(item[dedupeKey]) : null;
|
|
30
|
+
if (!keyVal || seenKeys.has(keyVal)) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
seenKeys.add(keyVal);
|
|
34
|
+
return true;
|
|
35
|
+
});
|
|
36
|
+
return [...prevItems, ...uniqueIncoming];
|
|
37
|
+
};
|
|
38
|
+
var mergeUniqueEntities = (prevContent, data, dedupeKey) => {
|
|
39
|
+
if (Array.isArray(data) && Array.isArray(prevContent)) {
|
|
40
|
+
return mergeEntityArrays(prevContent, data, dedupeKey);
|
|
41
|
+
}
|
|
42
|
+
if (!data || typeof data !== "object") {
|
|
43
|
+
return { ...prevContent };
|
|
44
|
+
}
|
|
45
|
+
const result = filterSafeKeys(prevContent);
|
|
46
|
+
const safeData = filterSafeKeys(data);
|
|
47
|
+
for (const key of Object.keys(safeData)) {
|
|
48
|
+
const incoming = safeData[key];
|
|
49
|
+
const prev = result[key];
|
|
50
|
+
result[key] = Array.isArray(incoming) && Array.isArray(prev) ? mergeEntityArrays(prev, incoming, dedupeKey) : incoming;
|
|
51
|
+
}
|
|
52
|
+
return result;
|
|
53
|
+
};
|
|
54
|
+
var updateEntityInArray = (items, data, dedupeKey) => {
|
|
55
|
+
let updated = false;
|
|
56
|
+
const targetId = String(data[dedupeKey]);
|
|
57
|
+
const newItems = items.map((item) => {
|
|
58
|
+
if (item && typeof item === "object" && String(item[dedupeKey]) === targetId) {
|
|
59
|
+
updated = true;
|
|
60
|
+
return { ...item, ...filterSafeKeys(data) };
|
|
61
|
+
}
|
|
62
|
+
return item;
|
|
63
|
+
});
|
|
64
|
+
return { updated, items: newItems };
|
|
65
|
+
};
|
|
66
|
+
var updateInternalArray = (target, safeData, dedupeKey) => {
|
|
67
|
+
for (const key of Object.keys(target)) {
|
|
68
|
+
if (!Array.isArray(target[key])) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const { updated, items } = updateEntityInArray(target[key], safeData, dedupeKey);
|
|
72
|
+
if (updated) {
|
|
73
|
+
target[key] = items;
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
};
|
|
79
|
+
var updateEntityInPlace = (prevContent, data, dedupeKey) => {
|
|
80
|
+
if (!data || typeof data !== "object") {
|
|
81
|
+
return { ...prevContent };
|
|
82
|
+
}
|
|
83
|
+
const safeData = filterSafeKeys(data);
|
|
84
|
+
if (Array.isArray(prevContent)) {
|
|
85
|
+
return updateEntityInArray(prevContent, safeData, dedupeKey).items;
|
|
86
|
+
}
|
|
87
|
+
const result = filterSafeKeys(prevContent);
|
|
88
|
+
const targetId = safeData[dedupeKey] !== void 0 ? String(safeData[dedupeKey]) : null;
|
|
89
|
+
if (targetId && String(result[dedupeKey]) === targetId) {
|
|
90
|
+
return { ...result, ...safeData };
|
|
91
|
+
}
|
|
92
|
+
updateInternalArray(result, safeData, dedupeKey);
|
|
93
|
+
return result;
|
|
94
|
+
};
|
|
95
|
+
var createCanvasReducer = () => {
|
|
96
|
+
return (currentState, envelope) => {
|
|
97
|
+
const { kind, mergeStrategy, dedupeKey = "id", data, uiIntent } = envelope;
|
|
98
|
+
const prevContent = currentState?.content;
|
|
99
|
+
if (!prevContent || prevContent.kind !== kind || mergeStrategy === "REPLACE") {
|
|
100
|
+
return {
|
|
101
|
+
content: { kind, ...filterSafeKeys(data || {}) },
|
|
102
|
+
activeIntent: uiIntent
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
if (mergeStrategy === "APPEND_UNIQUE") {
|
|
106
|
+
return {
|
|
107
|
+
content: { kind, ...mergeUniqueEntities(prevContent, data, dedupeKey) },
|
|
108
|
+
activeIntent: uiIntent
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (mergeStrategy === "UPDATE_ENTITY") {
|
|
112
|
+
return {
|
|
113
|
+
content: { kind, ...updateEntityInPlace(prevContent, data, dedupeKey) },
|
|
114
|
+
activeIntent: uiIntent
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
content: prevContent,
|
|
119
|
+
activeIntent: uiIntent ?? currentState?.activeIntent
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
// src/ui/define-canvas.ts
|
|
125
|
+
var defineCanvas = () => {
|
|
126
|
+
return {
|
|
127
|
+
createEnvelope: (options) => {
|
|
128
|
+
return createToolEnvelope(options);
|
|
129
|
+
},
|
|
130
|
+
canvasReducer: createCanvasReducer()
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
export {
|
|
134
|
+
createCanvasReducer,
|
|
135
|
+
createToolEnvelope,
|
|
136
|
+
defineCanvas,
|
|
137
|
+
isSafeKey,
|
|
138
|
+
mergeUniqueEntities,
|
|
139
|
+
updateEntityInPlace
|
|
140
|
+
};
|
|
@@ -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 @@
|
|
|
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,56 @@
|
|
|
1
|
+
import "../../chunk-Y6FXYEAI.mjs";
|
|
2
|
+
|
|
3
|
+
// src/ui/react/create-view-registry.ts
|
|
4
|
+
import React from "react";
|
|
5
|
+
var createViewRegistry = (registry) => {
|
|
6
|
+
const CanvasRenderer = ({
|
|
7
|
+
state,
|
|
8
|
+
context = {}
|
|
9
|
+
}) => {
|
|
10
|
+
if (!state?.content) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
const kind = state.content.kind;
|
|
14
|
+
const Component = registry[kind];
|
|
15
|
+
if (!Component) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
return React.createElement(Component, {
|
|
19
|
+
data: state.content,
|
|
20
|
+
context,
|
|
21
|
+
activeIntent: state.activeIntent
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
return {
|
|
25
|
+
registry,
|
|
26
|
+
CanvasRenderer
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// src/ui/react/sanitize.ts
|
|
31
|
+
var ALLOWED_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
|
|
32
|
+
var isValidSafeUrl = (rawUrl) => {
|
|
33
|
+
if (!rawUrl || typeof rawUrl !== "string") {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
const trimmed = rawUrl.trim();
|
|
37
|
+
if (!trimmed) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
if (trimmed.startsWith("#")) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const parsed = new URL(trimmed);
|
|
48
|
+
return ALLOWED_PROTOCOLS.has(parsed.protocol);
|
|
49
|
+
} catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
export {
|
|
54
|
+
createViewRegistry,
|
|
55
|
+
isValidSafeUrl
|
|
56
|
+
};
|
|
@@ -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": "1.
|
|
4
|
-
"description": "Zero-infrastructure, in-process AI Application Firewall (AI-WAF)
|
|
3
|
+
"version": "2.1.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": {
|
|
73
|
+
"types": "./dist/ui/index.d.ts",
|
|
74
|
+
"import": "./dist/ui/index.mjs",
|
|
75
|
+
"require": "./dist/ui/index.js"
|
|
76
|
+
},
|
|
77
|
+
"./ui/react": {
|
|
78
|
+
"types": "./dist/ui/react/index.d.ts",
|
|
79
|
+
"import": "./dist/ui/react/index.mjs",
|
|
80
|
+
"require": "./dist/ui/react/index.js"
|
|
81
|
+
},
|
|
68
82
|
"./package.json": "./package.json"
|
|
69
83
|
},
|
|
70
84
|
"peerDependencies": {
|
|
@@ -81,14 +95,15 @@
|
|
|
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",
|
|
89
104
|
"test:prompts": "tsx tests/prompt-builder.test.ts",
|
|
90
105
|
"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",
|
|
106
|
+
"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
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",
|