@neuroverseos/governance 0.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/LICENSE +21 -0
- package/README.md +198 -0
- package/dist/audit-logger.d.ts +38 -0
- package/dist/audit-logger.d.ts.map +1 -0
- package/dist/audit-logger.js +100 -0
- package/dist/audit-logger.js.map +1 -0
- package/dist/condition-engine.d.ts +16 -0
- package/dist/condition-engine.d.ts.map +1 -0
- package/dist/condition-engine.js +186 -0
- package/dist/condition-engine.js.map +1 -0
- package/dist/drift-monitor.d.ts +81 -0
- package/dist/drift-monitor.d.ts.map +1 -0
- package/dist/drift-monitor.js +228 -0
- package/dist/drift-monitor.js.map +1 -0
- package/dist/governance-engine.d.ts +131 -0
- package/dist/governance-engine.d.ts.map +1 -0
- package/dist/governance-engine.js +660 -0
- package/dist/governance-engine.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1170 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +196 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/world-bootstrap.d.ts +31 -0
- package/dist/world-bootstrap.d.ts.map +1 -0
- package/dist/world-bootstrap.js +415 -0
- package/dist/world-bootstrap.js.map +1 -0
- package/openclaw.plugin.json +59 -0
- package/package.json +36 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Drift Monitor — Background service tracking governance health
|
|
4
|
+
*
|
|
5
|
+
* Tracks:
|
|
6
|
+
* - Block frequency (are we blocking too much? too little?)
|
|
7
|
+
* - Manual overrides (humans overriding PAUSE decisions)
|
|
8
|
+
* - Tool friction (which tools cause the most governance friction?)
|
|
9
|
+
* - Rule friction (which rules fire most often?)
|
|
10
|
+
*
|
|
11
|
+
* Can also read from audit.jsonl for historical analysis.
|
|
12
|
+
* Stored in .neuroverseos/state.json — separate from MEMORY.md.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.DriftMonitor = void 0;
|
|
16
|
+
const fs_1 = require("fs");
|
|
17
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
18
|
+
// Monitor
|
|
19
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
20
|
+
class DriftMonitor {
|
|
21
|
+
constructor(config) {
|
|
22
|
+
this.saveInterval = null;
|
|
23
|
+
this.config = config;
|
|
24
|
+
this.state = this.loadState();
|
|
25
|
+
}
|
|
26
|
+
start() {
|
|
27
|
+
this.saveInterval = setInterval(() => this.saveState(), 30000);
|
|
28
|
+
}
|
|
29
|
+
stop() {
|
|
30
|
+
if (this.saveInterval) {
|
|
31
|
+
clearInterval(this.saveInterval);
|
|
32
|
+
this.saveInterval = null;
|
|
33
|
+
}
|
|
34
|
+
this.saveState();
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Record an action and its governance verdict.
|
|
38
|
+
*/
|
|
39
|
+
recordAction(tool, verdict, ruleId) {
|
|
40
|
+
this.state.totalActions++;
|
|
41
|
+
switch (verdict) {
|
|
42
|
+
case 'ALLOW':
|
|
43
|
+
this.state.allowCount++;
|
|
44
|
+
break;
|
|
45
|
+
case 'PAUSE':
|
|
46
|
+
this.state.pauseCount++;
|
|
47
|
+
break;
|
|
48
|
+
case 'BLOCK':
|
|
49
|
+
this.state.blockCount++;
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
// Tool friction
|
|
53
|
+
if (!this.state.toolFriction[tool]) {
|
|
54
|
+
this.state.toolFriction[tool] = { blocks: 0, pauses: 0, allows: 0 };
|
|
55
|
+
}
|
|
56
|
+
const tf = this.state.toolFriction[tool];
|
|
57
|
+
if (verdict === 'BLOCK')
|
|
58
|
+
tf.blocks++;
|
|
59
|
+
else if (verdict === 'PAUSE')
|
|
60
|
+
tf.pauses++;
|
|
61
|
+
else
|
|
62
|
+
tf.allows++;
|
|
63
|
+
// Rule friction
|
|
64
|
+
if (ruleId) {
|
|
65
|
+
this.state.ruleFriction[ruleId] = (this.state.ruleFriction[ruleId] ?? 0) + 1;
|
|
66
|
+
}
|
|
67
|
+
this.state.lastUpdated = Date.now();
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Record when a human overrides a PAUSE decision.
|
|
71
|
+
*/
|
|
72
|
+
recordOverride() {
|
|
73
|
+
this.state.overrideCount++;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get current drift statistics.
|
|
77
|
+
*/
|
|
78
|
+
getStats() {
|
|
79
|
+
const total = this.state.totalActions || 1;
|
|
80
|
+
const blockRate = this.state.blockCount / total;
|
|
81
|
+
const pauseRate = this.state.pauseCount / total;
|
|
82
|
+
const overrideRate = this.state.pauseCount > 0
|
|
83
|
+
? this.state.overrideCount / this.state.pauseCount
|
|
84
|
+
: 0;
|
|
85
|
+
const driftSignals = [];
|
|
86
|
+
if (blockRate > 0.3) {
|
|
87
|
+
driftSignals.push(`High block rate (${(blockRate * 100).toFixed(1)}%) — governance may be too strict`);
|
|
88
|
+
}
|
|
89
|
+
if (overrideRate > 0.5 && this.state.pauseCount >= 5) {
|
|
90
|
+
driftSignals.push(`High override rate (${(overrideRate * 100).toFixed(1)}%) — world rules may need amendment`);
|
|
91
|
+
}
|
|
92
|
+
for (const [tool, friction] of Object.entries(this.state.toolFriction)) {
|
|
93
|
+
const toolTotal = friction.blocks + friction.pauses + friction.allows;
|
|
94
|
+
const toolBlockRate = friction.blocks / Math.max(toolTotal, 1);
|
|
95
|
+
if (toolBlockRate > 0.5 && toolTotal >= 3) {
|
|
96
|
+
driftSignals.push(`Tool "${tool}" blocked ${(toolBlockRate * 100).toFixed(0)}% of the time`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (total > 20 && blockRate === 0 && pauseRate === 0) {
|
|
100
|
+
driftSignals.push('Zero blocks or pauses — governance may be too permissive');
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
totalActions: this.state.totalActions,
|
|
104
|
+
allowCount: this.state.allowCount,
|
|
105
|
+
pauseCount: this.state.pauseCount,
|
|
106
|
+
blockCount: this.state.blockCount,
|
|
107
|
+
blockRate,
|
|
108
|
+
pauseRate,
|
|
109
|
+
overrideRate,
|
|
110
|
+
driftSignals,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Generate amendment proposals based on drift patterns.
|
|
115
|
+
*/
|
|
116
|
+
generateProposals() {
|
|
117
|
+
const proposals = [];
|
|
118
|
+
const stats = this.getStats();
|
|
119
|
+
// High override rate → suggest loosening specific guards
|
|
120
|
+
if (stats.overrideRate > 0.5 && this.state.pauseCount >= 5) {
|
|
121
|
+
const topRule = Object.entries(this.state.ruleFriction)
|
|
122
|
+
.sort(([, a], [, b]) => b - a)[0];
|
|
123
|
+
if (topRule) {
|
|
124
|
+
proposals.push({
|
|
125
|
+
type: 'modify_threshold',
|
|
126
|
+
reason: `Rule "${topRule[0]}" triggered ${topRule[1]} times with ${(stats.overrideRate * 100).toFixed(0)}% override rate`,
|
|
127
|
+
suggestion: topRule[0],
|
|
128
|
+
evidence: `${(stats.overrideRate * 100).toFixed(0)}% of pauses were manually overridden`,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Tool constantly blocked → suggest more nuanced guard
|
|
133
|
+
for (const [tool, friction] of Object.entries(this.state.toolFriction)) {
|
|
134
|
+
const total = friction.blocks + friction.pauses + friction.allows;
|
|
135
|
+
if (friction.blocks > 5 && friction.blocks / total > 0.7) {
|
|
136
|
+
proposals.push({
|
|
137
|
+
type: 'add_guard',
|
|
138
|
+
reason: `Tool "${tool}" is blocked ${friction.blocks} out of ${total} times`,
|
|
139
|
+
suggestion: `Add granular guard for "${tool}" that allows safe patterns and blocks dangerous ones`,
|
|
140
|
+
evidence: `${tool}: ${friction.blocks} blocks, ${friction.pauses} pauses, ${friction.allows} allows`,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// Zero governance firing → suggest adding guards
|
|
145
|
+
if (this.state.totalActions > 20 && stats.blockRate === 0 && stats.pauseRate === 0) {
|
|
146
|
+
proposals.push({
|
|
147
|
+
type: 'add_guard',
|
|
148
|
+
reason: 'No governance constraints have fired in over 20 actions',
|
|
149
|
+
suggestion: 'Consider adding guards for destructive operations, external communication, or production access',
|
|
150
|
+
evidence: `${this.state.totalActions} actions with 0 blocks and 0 pauses`,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
return proposals;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Rebuild stats from the audit log (for historical analysis).
|
|
157
|
+
*/
|
|
158
|
+
rebuildFromAudit() {
|
|
159
|
+
if (!(0, fs_1.existsSync)(this.config.auditPath))
|
|
160
|
+
return;
|
|
161
|
+
try {
|
|
162
|
+
const raw = (0, fs_1.readFileSync)(this.config.auditPath, 'utf-8');
|
|
163
|
+
const lines = raw.split('\n').filter(l => l.trim());
|
|
164
|
+
// Reset state
|
|
165
|
+
this.state = this.freshState();
|
|
166
|
+
let decisionCount = 0;
|
|
167
|
+
for (const line of lines) {
|
|
168
|
+
try {
|
|
169
|
+
const entry = JSON.parse(line);
|
|
170
|
+
// Decision entries
|
|
171
|
+
if (entry.type === 'decision') {
|
|
172
|
+
const dec = entry;
|
|
173
|
+
if (dec.decision === 'allow-once' || dec.decision === 'allow-always') {
|
|
174
|
+
decisionCount++;
|
|
175
|
+
}
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
// Verdict entries
|
|
179
|
+
const verdict = entry;
|
|
180
|
+
this.recordAction(verdict.tool, verdict.status, verdict.ruleId ?? undefined);
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
this.state.overrideCount = decisionCount;
|
|
187
|
+
this.saveState();
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
// Silent failure
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// ── Persistence ────────────────────────────────────────────────
|
|
194
|
+
loadState() {
|
|
195
|
+
if ((0, fs_1.existsSync)(this.config.statePath)) {
|
|
196
|
+
try {
|
|
197
|
+
return JSON.parse((0, fs_1.readFileSync)(this.config.statePath, 'utf-8'));
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
// Corrupted state — start fresh
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return this.freshState();
|
|
204
|
+
}
|
|
205
|
+
freshState() {
|
|
206
|
+
return {
|
|
207
|
+
totalActions: 0,
|
|
208
|
+
allowCount: 0,
|
|
209
|
+
pauseCount: 0,
|
|
210
|
+
blockCount: 0,
|
|
211
|
+
overrideCount: 0,
|
|
212
|
+
toolFriction: {},
|
|
213
|
+
ruleFriction: {},
|
|
214
|
+
lastUpdated: Date.now(),
|
|
215
|
+
sessionStart: Date.now(),
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
saveState() {
|
|
219
|
+
try {
|
|
220
|
+
(0, fs_1.writeFileSync)(this.config.statePath, JSON.stringify(this.state, null, 2));
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
// Silent failure — don't crash on state save
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
exports.DriftMonitor = DriftMonitor;
|
|
228
|
+
//# sourceMappingURL=drift-monitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drift-monitor.js","sourceRoot":"","sources":["../drift-monitor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Governance Engine — Deterministic decision pipeline
|
|
3
|
+
*
|
|
4
|
+
* Evaluates tool calls against world rules in strict order:
|
|
5
|
+
* 1. Session allowlist → ALLOW silently if guard already approved
|
|
6
|
+
* 2. Invariants → any hit = BLOCK (immediate, no override)
|
|
7
|
+
* 3. Guards → condition engine + tool filter → PAUSE or BLOCK
|
|
8
|
+
* 4. Rules → trigger evaluation → verdict override
|
|
9
|
+
* 5. Role constraints → cannotDo = BLOCK, requiresApproval = PAUSE
|
|
10
|
+
* 6. Default → ALLOW
|
|
11
|
+
*
|
|
12
|
+
* Same world + same event = same verdict. Always.
|
|
13
|
+
* No AI. No network calls. Sub-millisecond per evaluation.
|
|
14
|
+
*/
|
|
15
|
+
import type { GovernanceWorld, GovernanceVerdict, ActiveWorldRecord, RoleBinding, BindingChangeSeverity, ToolCallEvent, EngineConfig, EngineStatus } from './types';
|
|
16
|
+
export declare class GovernanceEngine {
|
|
17
|
+
private config;
|
|
18
|
+
private world;
|
|
19
|
+
private worldMtimeMs;
|
|
20
|
+
private cachedWorldHash;
|
|
21
|
+
private metaRecord;
|
|
22
|
+
private surfacedAlerts;
|
|
23
|
+
private workspaceDir;
|
|
24
|
+
constructor(config: EngineConfig);
|
|
25
|
+
/** Set the workspace directory for md drift detection */
|
|
26
|
+
setWorkspaceDir(dir: string): void;
|
|
27
|
+
/** Clear surfaced alerts (e.g. on session reset) */
|
|
28
|
+
clearAlertHistory(): void;
|
|
29
|
+
loadWorld(): void;
|
|
30
|
+
getWorld(): GovernanceWorld | null;
|
|
31
|
+
setWorld(world: GovernanceWorld): void;
|
|
32
|
+
saveWorld(): void;
|
|
33
|
+
getStatus(): EngineStatus;
|
|
34
|
+
/** Load or create world.meta.json for integrity tracking */
|
|
35
|
+
loadMeta(): void;
|
|
36
|
+
saveMeta(): void;
|
|
37
|
+
getMetaRecord(): ActiveWorldRecord | null;
|
|
38
|
+
setMetaRecord(record: ActiveWorldRecord): void;
|
|
39
|
+
/**
|
|
40
|
+
* Get all role bindings from the meta record.
|
|
41
|
+
* Returns empty array if no bindings exist.
|
|
42
|
+
*/
|
|
43
|
+
getRoleBindings(): RoleBinding[];
|
|
44
|
+
/**
|
|
45
|
+
* Hydrate a Map<agentId, roleId> from stored bindings.
|
|
46
|
+
* Called at startup and after any binding change.
|
|
47
|
+
*/
|
|
48
|
+
hydrateRoleMap(roleMap: Map<string, string>): void;
|
|
49
|
+
/**
|
|
50
|
+
* Add or update a role binding. Returns the severity of the change.
|
|
51
|
+
* Does NOT auto-save — caller must call saveMeta().
|
|
52
|
+
*/
|
|
53
|
+
setRoleBinding(agentId: string, roleId: string, boundBy?: RoleBinding['boundBy']): BindingChangeSeverity;
|
|
54
|
+
/**
|
|
55
|
+
* Remove a role binding. Returns 'removal' severity.
|
|
56
|
+
* Does NOT auto-save — caller must call saveMeta().
|
|
57
|
+
*/
|
|
58
|
+
removeRoleBinding(agentId: string): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Classify the severity of changing from one role to another.
|
|
61
|
+
* Uses the role's requiresApproval and cannotDo as proxy for privilege level.
|
|
62
|
+
*/
|
|
63
|
+
private classifyBindingChange;
|
|
64
|
+
/**
|
|
65
|
+
* Estimate privilege level of a role (higher = more permissive).
|
|
66
|
+
* Simple heuristic: canDo breadth - cannotDo restrictions - approval overhead.
|
|
67
|
+
*/
|
|
68
|
+
private estimatePrivilege;
|
|
69
|
+
private getMetaPath;
|
|
70
|
+
/** Canonical SHA-256 hash of a world object (sorted keys, no whitespace) */
|
|
71
|
+
computeWorldHash(world: GovernanceWorld): string;
|
|
72
|
+
/**
|
|
73
|
+
* System-level protection: intercept modifications to governance source files.
|
|
74
|
+
*
|
|
75
|
+
* This runs BEFORE all user-defined rules and cannot be removed by
|
|
76
|
+
* modifying world.json. It is the engine's self-protection layer.
|
|
77
|
+
*
|
|
78
|
+
* - write_file / edit_file targeting .neuroverseos/ → BLOCK
|
|
79
|
+
* - write_file / edit_file targeting .md files → PAUSE
|
|
80
|
+
* - shell commands referencing .neuroverseos/ → BLOCK
|
|
81
|
+
*
|
|
82
|
+
* The PAUSE verdict flows through the existing interactive prompt in the
|
|
83
|
+
* before_tool_call hook. Session overrides ("always") are handled there.
|
|
84
|
+
*/
|
|
85
|
+
private checkGovernanceSourceProtection;
|
|
86
|
+
/**
|
|
87
|
+
* Run all integrity checks before the governance pipeline.
|
|
88
|
+
* Returns accumulated alerts. Critical alerts override the verdict.
|
|
89
|
+
*/
|
|
90
|
+
private checkIntegrity;
|
|
91
|
+
/**
|
|
92
|
+
* Verify world.json hash against stored hash.
|
|
93
|
+
* Uses mtime cache to avoid re-reading on every call.
|
|
94
|
+
*/
|
|
95
|
+
private verifyWorldHash;
|
|
96
|
+
/**
|
|
97
|
+
* Evaluate a tool call event against the loaded world.
|
|
98
|
+
* Returns a deterministic verdict: ALLOW, PAUSE, or BLOCK.
|
|
99
|
+
* Now includes runtime integrity checks (spec §8).
|
|
100
|
+
*/
|
|
101
|
+
evaluate(event: ToolCallEvent): GovernanceVerdict;
|
|
102
|
+
/**
|
|
103
|
+
* The actual ordered pipeline. This is the core of governance.
|
|
104
|
+
*/
|
|
105
|
+
private runPipeline;
|
|
106
|
+
/**
|
|
107
|
+
* Step 2: Invariants. Non-toggleable. Non-overridable. Hard BLOCK.
|
|
108
|
+
*/
|
|
109
|
+
private checkInvariants;
|
|
110
|
+
/**
|
|
111
|
+
* Step 3: Guards. Scoped + tool-filtered. Can PAUSE or BLOCK.
|
|
112
|
+
*/
|
|
113
|
+
private checkGuards;
|
|
114
|
+
/**
|
|
115
|
+
* Step 4: Rules. Contextual triggers with verdict effects.
|
|
116
|
+
*/
|
|
117
|
+
private checkRules;
|
|
118
|
+
/**
|
|
119
|
+
* Step 5: Role constraints. cannotDo = BLOCK, requiresApproval = PAUSE.
|
|
120
|
+
*/
|
|
121
|
+
private checkRoles;
|
|
122
|
+
/**
|
|
123
|
+
* Apply an approved amendment to the world.
|
|
124
|
+
*/
|
|
125
|
+
applyAmendment(proposal: {
|
|
126
|
+
type: 'add_guard' | 'modify_threshold' | 'add_role' | 'add_invariant';
|
|
127
|
+
suggestion: string;
|
|
128
|
+
reason: string;
|
|
129
|
+
}): void;
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=governance-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"governance-engine.d.ts","sourceRoot":"","sources":["../governance-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAOH,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EAEjB,iBAAiB,EACjB,WAAW,EACX,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,YAAY,EACb,MAAM,SAAS,CAAC;AA0BjB,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,KAAK,CAAgC;IAG7C,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,UAAU,CAAkC;IACpD,OAAO,CAAC,cAAc,CAA0B;IAChD,OAAO,CAAC,YAAY,CAAuB;gBAE/B,MAAM,EAAE,YAAY;IAIhC,yDAAyD;IACzD,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIlC,oDAAoD;IACpD,iBAAiB,IAAI,IAAI;IAMzB,SAAS,IAAI,IAAI;IAajB,QAAQ,IAAI,eAAe,GAAG,IAAI;IAIlC,QAAQ,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAItC,SAAS,IAAI,IAAI;IAMjB,SAAS,IAAI,YAAY;IAczB,4DAA4D;IAC5D,QAAQ,IAAI,IAAI;IAuBhB,QAAQ,IAAI,IAAI;IAMhB,aAAa,IAAI,iBAAiB,GAAG,IAAI;IAIzC,aAAa,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAM9C;;;OAGG;IACH,eAAe,IAAI,WAAW,EAAE;IAIhC;;;OAGG;IACH,cAAc,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAQlD;;;OAGG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,WAAW,CAAC,SAAS,CAAW,GAAG,qBAAqB;IA6BjH;;;OAGG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAQ3C;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAkB7B;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,WAAW;IAKnB,4EAA4E;IAC5E,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM;IAOhD;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,+BAA+B;IAuDvC;;;OAGG;IACH,OAAO,CAAC,cAAc;IA6EtB;;;OAGG;IACH,OAAO,CAAC,eAAe;IAiCvB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,iBAAiB;IAyCjD;;OAEG;IACH,OAAO,CAAC,WAAW;IA6CnB;;OAEG;IACH,OAAO,CAAC,eAAe;IAyBvB;;OAEG;IACH,OAAO,CAAC,WAAW;IA+BnB;;OAEG;IACH,OAAO,CAAC,UAAU;IAyBlB;;OAEG;IACH,OAAO,CAAC,UAAU;IAqClB;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE;QACvB,IAAI,EAAE,WAAW,GAAG,kBAAkB,GAAG,UAAU,GAAG,eAAe,CAAC;QACtE,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;KAChB,GAAG,IAAI;CAuDT"}
|