@salimassili/ai-costguard 1.1.8 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,107 +1,202 @@
1
1
  # AI CostGuard
2
2
 
3
- The kill-switch for AI agents.
3
+ AI CostGuard is a small TypeScript library that wraps OpenAI-like clients and blocks requests before they run when local safety checks predict unsafe AI API spend.
4
4
 
5
- Prevent runaway AI agent loops, token bombs, and budget explosions before they happen.
5
+ It is ESM-only, targets Node.js 18+, and is built with `tsc`.
6
+
7
+ ## What Works Today
8
+
9
+ - `guard()` wraps a client with budget, loop, and retry protection.
10
+ - `GuardError` is thrown when a request is blocked.
11
+ - Budget blocking estimates request cost before the API call.
12
+ - Loop detection blocks repeated prompts within the current process.
13
+ - Retry detection blocks repeated failure/retry prompts within the current process.
14
+ - `middleware()` adds the same local checks to web request flows.
15
+ - `getPricing()` returns known built-in model pricing.
16
+ - `registerPricing()` and `listPricing()` let you manage runtime pricing entries.
17
+
18
+ ## Install
6
19
 
7
20
  ```bash
8
21
  npm install @salimassili/ai-costguard
9
22
  ```
10
23
 
11
- ## Install & Protect (30 seconds)
24
+ ## Basic Usage
12
25
 
13
26
  ```ts
14
- import { withCostGuard } from '@salimassili/ai-costguard';
27
+ import OpenAI from 'openai';
28
+ import { guard, GuardError } from '@salimassili/ai-costguard';
15
29
 
16
- const openai = withCostGuard(client, {
17
- maxTotalCostPerDay: 5
18
- });
30
+ const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
31
+ const ai = guard(client, { budget: 1 });
32
+
33
+ try {
34
+ const response = await ai.chat.completions.create({
35
+ model: 'gpt-4o-mini',
36
+ messages: [{ role: 'user', content: 'Write a short project summary.' }],
37
+ max_tokens: 200
38
+ });
39
+
40
+ console.log(response);
41
+ } catch (error) {
42
+ if (error instanceof GuardError) {
43
+ console.error('AI request blocked:', error.message, error.context);
44
+ } else {
45
+ throw error;
46
+ }
47
+ }
19
48
  ```
20
49
 
21
- ## What You Get
50
+ ## How `guard()` Works
22
51
 
23
- When your agent spirals:
52
+ `guard(client, config)` returns a `Proxy` around your client. When code calls a method such as `client.chat.completions.create(...)`, CostGuard:
24
53
 
25
- ```
26
- [CostGuard] BLOCKED LOOP 12 recursive cycles detected estimated save: $18.42
27
- ```
54
+ 1. Reads the request model, messages, and `max_tokens`.
55
+ 2. Estimates input tokens from message length and combines them with the requested output limit.
56
+ 3. Looks up pricing for the model.
57
+ 4. Estimates the request cost.
58
+ 5. Blocks the call with `GuardError` if the local budget would be exceeded.
59
+ 6. Blocks repeated prompts that look like loops.
60
+ 7. Blocks repeated prompts that look like retry storms.
61
+ 8. Lets the original client method run when checks pass.
28
62
 
29
- A financial save event. Not a vague error.
63
+ The free guard state is process-local. Separate Node.js processes do not share budget state.
30
64
 
31
- ## Why This Exists
65
+ ## Budget Blocking
32
66
 
33
- AI agents don't fail gracefully. They fail exponentially.
67
+ ```ts
68
+ import { guard } from '@salimassili/ai-costguard';
34
69
 
35
- A stuck agent can burn hundreds of dollars in API credits overnight. Not because it's fast. Because it's relentless.
70
+ const ai = guard(openai, { budget: 0.25 });
36
71
 
37
- Your agent framework has no kill-switch. Rate limiters don't detect semantic loops. Cost alerts tell you after the money is gone.
72
+ await ai.chat.completions.create({
73
+ model: 'gpt-4o-mini',
74
+ messages: [{ role: 'user', content: 'Hello' }],
75
+ max_tokens: 100
76
+ });
77
+ ```
38
78
 
39
- This is the missing layer.
79
+ When the estimated cumulative spend in the current process would exceed `budget`, CostGuard throws `GuardError` before calling the underlying AI client.
40
80
 
41
- ## Real-World Protection
81
+ ## Loop And Retry Detection
42
82
 
43
- ### 1. Recursive Loop
44
- Agent repeats the same reasoning forever.
83
+ CostGuard keeps a short in-memory history of recent prompts for the wrapped client:
45
84
 
46
- ### 2. Tool Retry Explosion
47
- Agent retries a failing tool endlessly.
85
+ - Loop detection blocks repeated prompt hashes.
86
+ - Retry detection blocks repeated prompts containing retry/failure language such as `retry`, `again`, `repeat`, `error`, `fail`, or `timeout`.
48
87
 
49
- ### 3. Budget Breach
50
- Agent burns tokens rapidly until blocked.
88
+ These checks are intentionally local and lightweight.
51
89
 
52
- ## API
90
+ ## Middleware
53
91
 
54
92
  ```ts
55
- withCostGuard(client, {
56
- maxTotalCostPerDay: 10, // Hard USD limit
57
- maxTokensPerRequest: 4000, // Per-call limit
58
- maxRequestsPerMinute: 30, // Rate limit
59
- loopDetection: true // Catch repeated prompts
60
- })
93
+ import express from 'express';
94
+ import { middleware, GuardError } from '@salimassili/ai-costguard';
95
+
96
+ const app = express();
97
+
98
+ app.use(middleware({ budget: 2 }));
99
+
100
+ app.post('/chat', async (req, res, next) => {
101
+ try {
102
+ req.localSafety.check({
103
+ model: 'gpt-4o-mini',
104
+ tokens: 1000,
105
+ estimatedCost: 0.001,
106
+ timestamp: Date.now(),
107
+ prompt: req.body?.prompt ?? ''
108
+ });
109
+
110
+ res.json({ ok: true });
111
+ } catch (error) {
112
+ if (error instanceof GuardError) {
113
+ res.status(402).json({ error: error.message, context: error.context });
114
+ return;
115
+ }
116
+
117
+ next(error);
118
+ }
119
+ });
61
120
  ```
62
121
 
63
- ## Example
122
+ ## Pricing
64
123
 
65
124
  ```ts
66
- import { withCostGuard, CostGuardError } from '@salimassili/ai-costguard';
125
+ import { getPricing, listPricing, registerPricing } from '@salimassili/ai-costguard';
67
126
 
68
- const openai = withCostGuard(
69
- new OpenAI({ apiKey: process.env.OPENAI_API_KEY }),
70
- { maxTotalCostPerDay: 5 }
71
- );
127
+ console.log(getPricing('gpt-4o-mini'));
72
128
 
73
- try {
74
- const response = await openai.chat.completions.create({
75
- model: 'gpt-4',
76
- messages: [{ role: 'user', content: 'Hello' }],
77
- });
78
- } catch (err) {
79
- if (err instanceof CostGuardError) {
80
- console.log('Agent blocked:', err.message);
81
- // Handle gracefully
129
+ registerPricing([
130
+ {
131
+ model: 'custom-model',
132
+ inputPer1kTokens: 0.001,
133
+ outputPer1kTokens: 0.002,
134
+ lastUpdated: '2026-05-21',
135
+ source: 'internal'
82
136
  }
83
- }
137
+ ]);
138
+
139
+ console.log(listPricing());
84
140
  ```
85
141
 
86
- ## Express Middleware
142
+ `getPricing(model)` returns an exact match when available, then falls back to simple fuzzy matching. Unknown models return `undefined`.
143
+
144
+ ## Pro Features (Coming Soon)
145
+
146
+ > These features are under active development and not yet available:
147
+ > - Distributed Redis-backed budget state
148
+ > - Real Slack/Discord webhook alerts
149
+ > - Multi-instance coordination
150
+ > - Production license validation
151
+
152
+ ## API
153
+
154
+ ### `guard(client, config)`
155
+
156
+ Wraps an OpenAI-like client.
87
157
 
88
158
  ```ts
89
- import { costGuardMiddleware } from '@salimassili/ai-costguard';
159
+ guard(client, { budget: 10 });
160
+ ```
90
161
 
91
- app.use(costGuardMiddleware({ maxTotalCostPerDay: 10 }));
162
+ ### `GuardError`
163
+
164
+ Thrown when CostGuard blocks a request.
165
+
166
+ ```ts
167
+ try {
168
+ await ai.chat.completions.create(params);
169
+ } catch (error) {
170
+ if (error instanceof GuardError) {
171
+ console.log(error.context);
172
+ }
173
+ }
92
174
  ```
93
175
 
94
- ## Features
176
+ ### `middleware(config)`
95
177
 
96
- - **Loop detection** kills repeated prompts and recursive cycles
97
- - **Daily cost caps** — hard USD limits, no overages
98
- - **Token limits** — block oversized single requests
99
- - **RPM limits** — catch agents hammering the API
178
+ Creates request middleware with local budget, loop, and retry checks.
100
179
 
101
- ## Install Before You Deploy
180
+ ### `getPricing(model, overrides?)`
102
181
 
103
- ```bash
104
- npm install @salimassili/ai-costguard
105
- ```
182
+ Returns pricing for a model from overrides, runtime registrations, or built-in entries.
183
+
184
+ ### `registerPricing(entries)`
185
+
186
+ Registers or replaces runtime pricing entries by model name.
187
+
188
+ ### `listPricing()`
189
+
190
+ Returns built-in and runtime pricing entries, deduplicated by model name.
191
+
192
+ ## Limitations
193
+
194
+ - Free guard state is stored in memory only.
195
+ - Budget checks are estimates, not billing records.
196
+ - Token estimation is approximate.
197
+ - Pricing entries are static until the package or runtime registry is updated.
198
+ - The library does not include dashboards, analytics, governance workflows, or hosted services.
199
+
200
+ ## License
106
201
 
107
- MIT | [GitHub](https://github.com/salimassili62-afk/ai-costguard)
202
+ MIT
@@ -1,27 +1,7 @@
1
- /**
2
- * CostGuard.ts AI Agent Loop & Cost Firewall
3
- *
4
- * Wraps your AI client and kills runaway loops before they burn money.
5
- * When it blocks, it tells you exactly how much it saved.
6
- */
7
- import { CostGuardConfig, RequestContext, GuardState } from './types.js';
8
- /**
9
- * Wraps any AI client. Detects loops. Enforces hard limits.
10
- * Throws on block so your app handles it.
11
- */
12
- export declare function withCostGuard(client: any, config: any, sharedState?: GuardState): any;
13
- /**
14
- * Standalone middleware for Express/Fastify
15
- */
16
- export declare function costGuardMiddleware(config?: Partial<CostGuardConfig>): (req: any, res: any, next: any) => void;
17
- /** Custom error so users can catch it specifically */
18
- export declare class CostGuardError extends Error {
19
- context: RequestContext;
20
- constructor(message: string, context: RequestContext);
21
- }
22
- /** Get current pricing for a model (cents per 1K tokens) */
23
- export declare function getPricing(model: string): {
24
- input: number;
25
- output: number;
26
- } | undefined;
1
+ export { guard, GuardError, middleware } from './GuardFree.js';
2
+ export { GuardPro, validateLicense, getProGuard } from './GuardPro.js';
3
+ export type { GuardProConfig } from './GuardPro.js';
4
+ export { getPricing, registerPricing, listPricing } from '../pricing/index.js';
5
+ export type { ModelPricing } from '../pricing/index.js';
6
+ export type { GuardConfig } from './types.js';
27
7
  //# sourceMappingURL=CostGuard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CostGuard.d.ts","sourceRoot":"","sources":["../../src/core/CostGuard.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,UAAU,EAAiB,MAAM,YAAY,CAAC;AAYxF;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,CAAC,EAAE,UAAU,OAmE/E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM,IAiB/D,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,GAAG,UAgBtC;AAoFD,sDAAsD;AACtD,qBAAa,cAAe,SAAQ,KAAK;IACvC,OAAO,EAAE,cAAc,CAAC;gBACZ,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc;CAKrD;AAED,4DAA4D;AAC5D,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAEvF"}
1
+ {"version":3,"file":"CostGuard.d.ts","sourceRoot":"","sources":["../../src/core/CostGuard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACvE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC/E,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
@@ -1,191 +1,4 @@
1
- /**
2
- * CostGuard.ts AI Agent Loop & Cost Firewall
3
- *
4
- * Wraps your AI client and kills runaway loops before they burn money.
5
- * When it blocks, it tells you exactly how much it saved.
6
- */
7
- const MODEL_PRICING = {
8
- 'gpt-4': { input: 0.03, output: 0.06 },
9
- 'gpt-4o': { input: 0.005, output: 0.015 },
10
- 'gpt-4o-mini': { input: 0.00015, output: 0.0006 },
11
- 'gpt-3.5-turbo': { input: 0.0005, output: 0.0015 },
12
- 'claude-3-opus': { input: 0.015, output: 0.075 },
13
- 'claude-3-sonnet': { input: 0.003, output: 0.015 },
14
- 'claude-3-haiku': { input: 0.00025, output: 0.00125 },
15
- };
16
- /**
17
- * Wraps any AI client. Detects loops. Enforces hard limits.
18
- * Throws on block so your app handles it.
19
- */
20
- export function withCostGuard(client, config, sharedState) {
21
- const defaults = {
22
- maxTokensPerRequest: 4000,
23
- maxRequestsPerMinute: 30,
24
- maxTotalCostPerDay: 10.00,
25
- loopDetection: true,
26
- };
27
- const guard = { ...defaults, ...config };
28
- // Use shared state if provided (for nested objects), otherwise create new
29
- const state = sharedState || {
30
- requestCount: 0,
31
- totalCost: 0,
32
- lastRequestTime: 0,
33
- recentPrompts: [],
34
- blockedCount: 0,
35
- };
36
- return new Proxy(client, {
37
- get(target, prop) {
38
- const value = target[prop];
39
- // If it's a function (like .create), wrap it
40
- if (typeof value === 'function') {
41
- return (...args) => {
42
- // Extract request details from args
43
- const ctx = extractContext(args, prop);
44
- // Evaluate against limits
45
- const decision = evaluate(guard, state, ctx);
46
- if (decision === 'block') {
47
- state.blockedCount++;
48
- // Build a financial save message
49
- const saveMsg = buildSaveMessage(state, ctx);
50
- console.error(saveMsg);
51
- if (guard.onLimitHit)
52
- guard.onLimitHit('Limit exceeded', ctx.estimatedCost);
53
- throw new CostGuardError(saveMsg.replace('[AI CostGuard] ', ''), ctx);
54
- }
55
- // Update state
56
- state.requestCount++;
57
- state.totalCost += ctx.estimatedCost;
58
- state.lastRequestTime = Date.now();
59
- if (guard.loopDetection)
60
- state.recentPrompts.push(ctx.prompt);
61
- if (state.recentPrompts.length > 20)
62
- state.recentPrompts.shift();
63
- console.log(`[AI CostGuard] ALLOW: ${ctx.model} | ${ctx.tokens}t | $${ctx.estimatedCost.toFixed(4)} | Total: $${state.totalCost.toFixed(2)}`);
64
- // Pass through to actual API call
65
- return value.apply(target, args);
66
- };
67
- }
68
- // If it's a nested object (like .chat.completions), recurse with shared state
69
- if (value && typeof value === 'object') {
70
- return withCostGuard(value, guard, state);
71
- }
72
- return value;
73
- },
74
- });
75
- }
76
- /**
77
- * Standalone middleware for Express/Fastify
78
- */
79
- export function costGuardMiddleware(config = {}) {
80
- const guard = {
81
- maxTokensPerRequest: 4000,
82
- maxRequestsPerMinute: 30,
83
- maxTotalCostPerDay: 10.00,
84
- loopDetection: true,
85
- ...config,
86
- };
87
- const state = {
88
- requestCount: 0,
89
- totalCost: 0,
90
- lastRequestTime: 0,
91
- recentPrompts: [],
92
- blockedCount: 0,
93
- };
94
- return (req, res, next) => {
95
- req.costGuard = {
96
- state,
97
- evaluate: (ctx) => {
98
- const decision = evaluate(guard, state, ctx);
99
- if (decision === 'block') {
100
- state.blockedCount++;
101
- throw new CostGuardError('Request blocked by cost guard', ctx);
102
- }
103
- state.requestCount++;
104
- state.totalCost += ctx.estimatedCost;
105
- state.lastRequestTime = Date.now();
106
- },
107
- };
108
- next();
109
- };
110
- }
111
- /** Extract request context from API call args */
112
- function extractContext(args, prop) {
113
- const params = args[0] || {};
114
- const model = params.model || 'unknown';
115
- const messages = params.messages || [];
116
- const prompt = messages.map((m) => m.content).join(' ').slice(0, 200);
117
- // Estimate tokens (rough: 1 token ≈ 4 chars for English)
118
- const inputText = JSON.stringify(messages);
119
- const estimatedInputTokens = Math.ceil(inputText.length / 4);
120
- const maxOutputTokens = params.max_tokens || 1000;
121
- const tokens = estimatedInputTokens + maxOutputTokens;
122
- // Estimate cost
123
- const pricing = MODEL_PRICING[model] || { input: 0.01, output: 0.03 };
124
- const estimatedCost = (estimatedInputTokens / 1000) * pricing.input +
125
- (maxOutputTokens / 1000) * pricing.output;
126
- return {
127
- model,
128
- tokens,
129
- estimatedCost,
130
- timestamp: Date.now(),
131
- prompt,
132
- };
133
- }
134
- /** Build a human-readable "financial save" message */
135
- function buildSaveMessage(state, ctx) {
136
- const duplicates = state.recentPrompts.filter(p => p === ctx.prompt).length;
137
- const isLoop = duplicates >= 2;
138
- // Estimate how much we saved by blocking this + projected future calls
139
- // Assume a runaway loop would repeat ~50 more times if unchecked
140
- const projectedCycles = isLoop ? 50 : 10;
141
- const estimatedSave = (ctx.estimatedCost * projectedCycles) + ctx.estimatedCost;
142
- if (isLoop) {
143
- return `[AI CostGuard] BLOCKED LOOP → ${duplicates + 1} recursive cycles detected → estimated save: $${estimatedSave.toFixed(2)}`;
144
- }
145
- if (ctx.tokens > 4000) {
146
- return `[AI CostGuard] BLOCKED TOKEN BOMB → ${ctx.tokens} tokens → estimated save: $${ctx.estimatedCost.toFixed(2)}`;
147
- }
148
- if (state.totalCost + ctx.estimatedCost > 5) {
149
- const remaining = (state.totalCost + ctx.estimatedCost) - 5;
150
- return `[AI CostGuard] BLOCKED BUDGET BREACH → daily cap reached → estimated save: $${remaining.toFixed(2)}`;
151
- }
152
- return `[AI CostGuard] BLOCKED → estimated save: $${ctx.estimatedCost.toFixed(2)}`;
153
- }
154
- /** Evaluate request against all limits */
155
- function evaluate(guard, state, ctx) {
156
- // 1. Token limit
157
- if (ctx.tokens > guard.maxTokensPerRequest) {
158
- return 'block';
159
- }
160
- // 2. RPM limit
161
- const oneMinuteAgo = Date.now() - 60000;
162
- if (state.lastRequestTime > oneMinuteAgo && state.requestCount >= guard.maxRequestsPerMinute) {
163
- return 'block';
164
- }
165
- // 3. Daily cost limit
166
- if (state.totalCost + ctx.estimatedCost > guard.maxTotalCostPerDay) {
167
- return 'block';
168
- }
169
- // 4. Loop detection (simple: same prompt repeated)
170
- if (guard.loopDetection && state.recentPrompts.length > 0) {
171
- const duplicates = state.recentPrompts.filter(p => p === ctx.prompt).length;
172
- if (duplicates >= 2) {
173
- return 'block';
174
- }
175
- }
176
- return 'allow';
177
- }
178
- /** Custom error so users can catch it specifically */
179
- export class CostGuardError extends Error {
180
- context;
181
- constructor(message, context) {
182
- super(message);
183
- this.name = 'CostGuardError';
184
- this.context = context;
185
- }
186
- }
187
- /** Get current pricing for a model (cents per 1K tokens) */
188
- export function getPricing(model) {
189
- return MODEL_PRICING[model];
190
- }
1
+ export { guard, GuardError, middleware } from './GuardFree.js';
2
+ export { GuardPro, validateLicense, getProGuard } from './GuardPro.js';
3
+ export { getPricing, registerPricing, listPricing } from '../pricing/index.js';
191
4
  //# sourceMappingURL=CostGuard.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CostGuard.js","sourceRoot":"","sources":["../../src/core/CostGuard.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CostGuard.js","sourceRoot":"","sources":["../../src/core/CostGuard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEvE,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * GuardCore.ts - FREE CORE (VIRAL ENGINE)
3
+ *
4
+ * Maximum simplicity. Maximum virality. Zero complexity.
5
+ * Instant safety layer every AI developer installs by default.
6
+ */
7
+ import { GuardConfig, RequestContext, GuardState } from './types.js';
8
+ /**
9
+ * Guard your AI client from wasting money
10
+ * FREE CORE: Local protection + viral logs + real-time risk warnings
11
+ */
12
+ export declare function guard(client: any, config: GuardConfig, sharedState?: GuardState): any;
13
+ /**
14
+ * Express middleware (FREE CORE - LOCAL ONLY)
15
+ */
16
+ export declare function middleware(config: GuardConfig): (req: any, res: any, next: any) => void;
17
+ export declare class GuardError extends Error {
18
+ context: RequestContext;
19
+ constructor(message: string, context: RequestContext);
20
+ }
21
+ export { getPricing } from '../pricing/index.js';
22
+ //# sourceMappingURL=GuardCore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GuardCore.d.ts","sourceRoot":"","sources":["../../src/core/GuardCore.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAErE;;;GAGG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,CAAC,EAAE,UAAU,OAgF/E;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,IAGpC,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,GAAG,UAiCtC;AAiED,qBAAa,UAAW,SAAQ,KAAK;IACnC,OAAO,EAAE,cAAc,CAAC;gBACZ,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc;CAKrD;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC"}