@peac/capture-core 0.10.7

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/dist/mapper.js ADDED
@@ -0,0 +1,212 @@
1
+ "use strict";
2
+ /**
3
+ * @peac/capture-core - Evidence Mapper
4
+ *
5
+ * Transforms SpoolEntry into InteractionEvidenceV01.
6
+ * This is a pure transformation with no side effects.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.toInteractionEvidence = toInteractionEvidence;
10
+ exports.toInteractionEvidenceBatch = toInteractionEvidenceBatch;
11
+ // =============================================================================
12
+ // Pure Transformation Functions
13
+ // =============================================================================
14
+ /**
15
+ * Build executor from action.
16
+ */
17
+ function buildExecutor(action) {
18
+ const executor = {
19
+ platform: action.platform,
20
+ };
21
+ if (action.platform_version) {
22
+ executor.version = action.platform_version;
23
+ }
24
+ if (action.plugin_id) {
25
+ executor.plugin_id = action.plugin_id;
26
+ }
27
+ return executor;
28
+ }
29
+ /**
30
+ * Build tool target from action (if applicable).
31
+ */
32
+ function buildToolTarget(action) {
33
+ if (!action.tool_name) {
34
+ return undefined;
35
+ }
36
+ const tool = {
37
+ name: action.tool_name,
38
+ };
39
+ if (action.tool_provider) {
40
+ tool.provider = action.tool_provider;
41
+ }
42
+ return tool;
43
+ }
44
+ /**
45
+ * Build resource target from action (if applicable).
46
+ */
47
+ function buildResourceTarget(action) {
48
+ if (!action.resource_uri && !action.resource_method) {
49
+ return undefined;
50
+ }
51
+ const resource = {};
52
+ if (action.resource_uri) {
53
+ resource.uri = action.resource_uri;
54
+ }
55
+ if (action.resource_method) {
56
+ resource.method = action.resource_method;
57
+ }
58
+ return resource;
59
+ }
60
+ /**
61
+ * Build payload reference from digest.
62
+ */
63
+ function buildPayloadRef(digest, redaction) {
64
+ if (!digest) {
65
+ return undefined;
66
+ }
67
+ return {
68
+ digest,
69
+ redaction,
70
+ };
71
+ }
72
+ /**
73
+ * Build result from action.
74
+ */
75
+ function buildResult(action) {
76
+ if (!action.status) {
77
+ return undefined;
78
+ }
79
+ const result = {
80
+ status: action.status,
81
+ };
82
+ if (action.error_code) {
83
+ result.error_code = action.error_code;
84
+ }
85
+ if (action.retryable !== undefined) {
86
+ result.retryable = action.retryable;
87
+ }
88
+ return result;
89
+ }
90
+ /**
91
+ * Build policy context from action.
92
+ */
93
+ function buildPolicyContext(action) {
94
+ if (!action.policy) {
95
+ return undefined;
96
+ }
97
+ const policy = {
98
+ decision: action.policy.decision,
99
+ };
100
+ if (action.policy.sandbox_enabled !== undefined) {
101
+ policy.sandbox_enabled = action.policy.sandbox_enabled;
102
+ }
103
+ if (action.policy.elevated !== undefined) {
104
+ policy.elevated = action.policy.elevated;
105
+ }
106
+ // Note: effective_policy_digest would require converting the string to Digest
107
+ // This is left for the adapter to handle if needed
108
+ return policy;
109
+ }
110
+ // =============================================================================
111
+ // Main Mapper
112
+ // =============================================================================
113
+ /**
114
+ * Convert a SpoolEntry to InteractionEvidenceV01.
115
+ *
116
+ * This is a pure, deterministic transformation.
117
+ * The same SpoolEntry will always produce the same InteractionEvidence.
118
+ */
119
+ function toInteractionEvidence(entry, options = {}) {
120
+ const { defaultRedaction = 'hash_only', includeSpoolAnchor = false } = options;
121
+ const { action } = entry;
122
+ // Build the evidence object
123
+ const evidence = {
124
+ interaction_id: action.id,
125
+ kind: action.kind,
126
+ executor: buildExecutor(action),
127
+ started_at: action.started_at,
128
+ };
129
+ // Optional tool target
130
+ const tool = buildToolTarget(action);
131
+ if (tool) {
132
+ evidence.tool = tool;
133
+ }
134
+ // Optional resource target
135
+ const resource = buildResourceTarget(action);
136
+ if (resource) {
137
+ evidence.resource = resource;
138
+ }
139
+ // Optional input payload reference
140
+ const input = buildPayloadRef(entry.input_digest, defaultRedaction);
141
+ if (input) {
142
+ evidence.input = input;
143
+ }
144
+ // Optional output payload reference
145
+ const output = buildPayloadRef(entry.output_digest, defaultRedaction);
146
+ if (output) {
147
+ evidence.output = output;
148
+ }
149
+ // Optional completed_at
150
+ if (action.completed_at) {
151
+ evidence.completed_at = action.completed_at;
152
+ }
153
+ // Optional duration
154
+ if (action.duration_ms !== undefined) {
155
+ evidence.duration_ms = action.duration_ms;
156
+ }
157
+ // Optional result
158
+ const result = buildResult(action);
159
+ if (result) {
160
+ evidence.result = result;
161
+ }
162
+ // Optional policy context
163
+ const policy = buildPolicyContext(action);
164
+ if (policy) {
165
+ evidence.policy = policy;
166
+ }
167
+ // Build extensions
168
+ const extensions = {};
169
+ // Add platform-specific metadata if present
170
+ if (action.metadata && Object.keys(action.metadata).length > 0) {
171
+ // Check if metadata keys are already properly namespaced
172
+ // Namespaced keys (e.g., org.openclaw/context) go directly into extensions
173
+ // Non-namespaced keys go under the generic capture-metadata key
174
+ const EXTENSION_KEY_PATTERN = /^[a-z0-9-]+\.[a-z0-9-]+\//;
175
+ const genericMetadata = {};
176
+ for (const [key, value] of Object.entries(action.metadata)) {
177
+ if (EXTENSION_KEY_PATTERN.test(key)) {
178
+ // Already namespaced - add directly to extensions
179
+ extensions[key] = value;
180
+ }
181
+ else {
182
+ // Not namespaced - collect for generic key
183
+ genericMetadata[key] = value;
184
+ }
185
+ }
186
+ // Add non-namespaced metadata under generic key
187
+ if (Object.keys(genericMetadata).length > 0) {
188
+ extensions['org.peacprotocol/capture-metadata@0.1'] = genericMetadata;
189
+ }
190
+ }
191
+ // Add spool anchor if requested
192
+ if (includeSpoolAnchor) {
193
+ const anchor = {
194
+ spool_head_digest: entry.entry_digest,
195
+ sequence: entry.sequence,
196
+ anchored_at: entry.captured_at,
197
+ };
198
+ extensions['org.peacprotocol/spool-anchor@0.1'] = anchor;
199
+ }
200
+ // Only add extensions if non-empty
201
+ if (Object.keys(extensions).length > 0) {
202
+ evidence.extensions = extensions;
203
+ }
204
+ return evidence;
205
+ }
206
+ /**
207
+ * Batch convert SpoolEntries to InteractionEvidence array.
208
+ */
209
+ function toInteractionEvidenceBatch(entries, options = {}) {
210
+ return entries.map((entry) => toInteractionEvidence(entry, options));
211
+ }
212
+ //# sourceMappingURL=mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.js","sourceRoot":"","sources":["../src/mapper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * @peac/capture-core - In-Memory Implementations
3
+ *
4
+ * Reference implementations for testing and development.
5
+ * NOT for production use - use @peac/capture-node for durable storage.
6
+ */
7
+ import type { SpoolStore, SpoolEntry, DedupeIndex, DedupeEntry } from './types';
8
+ /**
9
+ * In-memory spool store for testing.
10
+ *
11
+ * Features:
12
+ * - Entries stored in array (ordered by sequence)
13
+ * - commit() is a no-op (no durability)
14
+ * - Useful for unit tests and development
15
+ */
16
+ export declare class InMemorySpoolStore implements SpoolStore {
17
+ private entries;
18
+ private headDigest;
19
+ private currentSequence;
20
+ private closed;
21
+ /**
22
+ * Append an entry to the spool.
23
+ */
24
+ append(entry: SpoolEntry): Promise<number>;
25
+ /**
26
+ * Commit is a no-op for in-memory store.
27
+ */
28
+ commit(): Promise<void>;
29
+ /**
30
+ * Read entries starting from a sequence number.
31
+ */
32
+ read(fromSequence: number, limit?: number): Promise<SpoolEntry[]>;
33
+ /**
34
+ * Get the current head digest.
35
+ */
36
+ getHeadDigest(): Promise<string>;
37
+ /**
38
+ * Get the current sequence number.
39
+ */
40
+ getSequence(): Promise<number>;
41
+ /**
42
+ * Close the store.
43
+ */
44
+ close(): Promise<void>;
45
+ /**
46
+ * Check if store is closed.
47
+ */
48
+ private assertNotClosed;
49
+ /**
50
+ * Get all entries (for testing).
51
+ */
52
+ getAllEntries(): SpoolEntry[];
53
+ /**
54
+ * Clear all entries (for testing).
55
+ */
56
+ clear(): void;
57
+ }
58
+ /**
59
+ * In-memory dedupe index for testing.
60
+ *
61
+ * Features:
62
+ * - Entries stored in Map
63
+ * - No persistence
64
+ * - Returns resolved Promises (async interface, sync implementation)
65
+ * - Useful for unit tests and development
66
+ */
67
+ export declare class InMemoryDedupeIndex implements DedupeIndex {
68
+ private entries;
69
+ /**
70
+ * Get entry by action ID.
71
+ */
72
+ get(actionId: string): Promise<DedupeEntry | undefined>;
73
+ /**
74
+ * Set entry for action ID.
75
+ */
76
+ set(actionId: string, entry: DedupeEntry): Promise<void>;
77
+ /**
78
+ * Check if action ID exists.
79
+ */
80
+ has(actionId: string): Promise<boolean>;
81
+ /**
82
+ * Mark an entry as emitted.
83
+ */
84
+ markEmitted(actionId: string): Promise<boolean>;
85
+ /**
86
+ * Delete entry.
87
+ */
88
+ delete(actionId: string): Promise<boolean>;
89
+ /**
90
+ * Get count of entries.
91
+ */
92
+ size(): Promise<number>;
93
+ /**
94
+ * Clear all entries.
95
+ */
96
+ clear(): Promise<void>;
97
+ /**
98
+ * Get all entries as array (for testing).
99
+ */
100
+ getAllEntries(): Array<[string, DedupeEntry]>;
101
+ }
102
+ /**
103
+ * Create an in-memory spool store.
104
+ */
105
+ export declare function createInMemorySpoolStore(): InMemorySpoolStore;
106
+ /**
107
+ * Create an in-memory dedupe index.
108
+ */
109
+ export declare function createInMemoryDedupeIndex(): InMemoryDedupeIndex;
110
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAOhF;;;;;;;GAOG;AACH,qBAAa,kBAAmB,YAAW,UAAU;IACnD,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,MAAM,CAAkB;IAEhC;;OAEG;IACG,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAwBhD;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAK7B;;OAEG;IACG,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAavE;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAKtC;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IAKpC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;OAEG;IACH,OAAO,CAAC,eAAe;IAQvB;;OAEG;IACH,aAAa,IAAI,UAAU,EAAE;IAI7B;;OAEG;IACH,KAAK,IAAI,IAAI;CAKd;AAMD;;;;;;;;GAQG;AACH,qBAAa,mBAAoB,YAAW,WAAW;IACrD,OAAO,CAAC,OAAO,CAAuC;IAEtD;;OAEG;IACG,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAI7D;;OAEG;IACG,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9D;;OAEG;IACG,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7C;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASrD;;OAEG;IACG,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIhD;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAI7B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B;;OAEG;IACH,aAAa,IAAI,KAAK,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CAG9C;AAMD;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,kBAAkB,CAE7D;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,mBAAmB,CAE/D"}
package/dist/memory.js ADDED
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ /**
3
+ * @peac/capture-core - In-Memory Implementations
4
+ *
5
+ * Reference implementations for testing and development.
6
+ * NOT for production use - use @peac/capture-node for durable storage.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.InMemoryDedupeIndex = exports.InMemorySpoolStore = void 0;
10
+ exports.createInMemorySpoolStore = createInMemorySpoolStore;
11
+ exports.createInMemoryDedupeIndex = createInMemoryDedupeIndex;
12
+ const types_1 = require("./types");
13
+ // =============================================================================
14
+ // In-Memory Spool Store
15
+ // =============================================================================
16
+ /**
17
+ * In-memory spool store for testing.
18
+ *
19
+ * Features:
20
+ * - Entries stored in array (ordered by sequence)
21
+ * - commit() is a no-op (no durability)
22
+ * - Useful for unit tests and development
23
+ */
24
+ class InMemorySpoolStore {
25
+ entries = [];
26
+ headDigest = types_1.GENESIS_DIGEST;
27
+ currentSequence = 0;
28
+ closed = false;
29
+ /**
30
+ * Append an entry to the spool.
31
+ */
32
+ async append(entry) {
33
+ this.assertNotClosed();
34
+ // Validate sequence
35
+ if (entry.sequence !== this.currentSequence + 1) {
36
+ throw new Error(`Invalid sequence: expected ${this.currentSequence + 1}, got ${entry.sequence}`);
37
+ }
38
+ // Validate chain
39
+ if (entry.prev_entry_digest !== this.headDigest) {
40
+ throw new Error(`Invalid chain: expected prev_entry_digest ${this.headDigest}, got ${entry.prev_entry_digest}`);
41
+ }
42
+ this.entries.push(entry);
43
+ this.headDigest = entry.entry_digest;
44
+ this.currentSequence = entry.sequence;
45
+ return entry.sequence;
46
+ }
47
+ /**
48
+ * Commit is a no-op for in-memory store.
49
+ */
50
+ async commit() {
51
+ this.assertNotClosed();
52
+ // No-op for in-memory
53
+ }
54
+ /**
55
+ * Read entries starting from a sequence number.
56
+ */
57
+ async read(fromSequence, limit) {
58
+ this.assertNotClosed();
59
+ const startIndex = fromSequence > 0 ? fromSequence - 1 : 0;
60
+ const entries = this.entries.slice(startIndex);
61
+ if (limit !== undefined && limit > 0) {
62
+ return entries.slice(0, limit);
63
+ }
64
+ return entries;
65
+ }
66
+ /**
67
+ * Get the current head digest.
68
+ */
69
+ async getHeadDigest() {
70
+ this.assertNotClosed();
71
+ return this.headDigest;
72
+ }
73
+ /**
74
+ * Get the current sequence number.
75
+ */
76
+ async getSequence() {
77
+ this.assertNotClosed();
78
+ return this.currentSequence;
79
+ }
80
+ /**
81
+ * Close the store.
82
+ */
83
+ async close() {
84
+ this.closed = true;
85
+ }
86
+ /**
87
+ * Check if store is closed.
88
+ */
89
+ assertNotClosed() {
90
+ if (this.closed) {
91
+ throw new Error('SpoolStore is closed');
92
+ }
93
+ }
94
+ // Test helpers (not part of interface)
95
+ /**
96
+ * Get all entries (for testing).
97
+ */
98
+ getAllEntries() {
99
+ return [...this.entries];
100
+ }
101
+ /**
102
+ * Clear all entries (for testing).
103
+ */
104
+ clear() {
105
+ this.entries = [];
106
+ this.headDigest = types_1.GENESIS_DIGEST;
107
+ this.currentSequence = 0;
108
+ }
109
+ }
110
+ exports.InMemorySpoolStore = InMemorySpoolStore;
111
+ // =============================================================================
112
+ // In-Memory Dedupe Index
113
+ // =============================================================================
114
+ /**
115
+ * In-memory dedupe index for testing.
116
+ *
117
+ * Features:
118
+ * - Entries stored in Map
119
+ * - No persistence
120
+ * - Returns resolved Promises (async interface, sync implementation)
121
+ * - Useful for unit tests and development
122
+ */
123
+ class InMemoryDedupeIndex {
124
+ entries = new Map();
125
+ /**
126
+ * Get entry by action ID.
127
+ */
128
+ async get(actionId) {
129
+ return this.entries.get(actionId);
130
+ }
131
+ /**
132
+ * Set entry for action ID.
133
+ */
134
+ async set(actionId, entry) {
135
+ this.entries.set(actionId, entry);
136
+ }
137
+ /**
138
+ * Check if action ID exists.
139
+ */
140
+ async has(actionId) {
141
+ return this.entries.has(actionId);
142
+ }
143
+ /**
144
+ * Mark an entry as emitted.
145
+ */
146
+ async markEmitted(actionId) {
147
+ const entry = this.entries.get(actionId);
148
+ if (!entry) {
149
+ return false;
150
+ }
151
+ entry.emitted = true;
152
+ return true;
153
+ }
154
+ /**
155
+ * Delete entry.
156
+ */
157
+ async delete(actionId) {
158
+ return this.entries.delete(actionId);
159
+ }
160
+ /**
161
+ * Get count of entries.
162
+ */
163
+ async size() {
164
+ return this.entries.size;
165
+ }
166
+ /**
167
+ * Clear all entries.
168
+ */
169
+ async clear() {
170
+ this.entries.clear();
171
+ }
172
+ // Test helpers (not part of interface)
173
+ /**
174
+ * Get all entries as array (for testing).
175
+ */
176
+ getAllEntries() {
177
+ return [...this.entries.entries()];
178
+ }
179
+ }
180
+ exports.InMemoryDedupeIndex = InMemoryDedupeIndex;
181
+ // =============================================================================
182
+ // Factory Functions
183
+ // =============================================================================
184
+ /**
185
+ * Create an in-memory spool store.
186
+ */
187
+ function createInMemorySpoolStore() {
188
+ return new InMemorySpoolStore();
189
+ }
190
+ /**
191
+ * Create an in-memory dedupe index.
192
+ */
193
+ function createInMemoryDedupeIndex() {
194
+ return new InMemoryDedupeIndex();
195
+ }
196
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * @peac/capture-core - Capture Session
3
+ *
4
+ * Stateful capture pipeline that orchestrates hashing, deduplication,
5
+ * and spool storage.
6
+ */
7
+ import type { CaptureSession, CaptureSessionConfig, CapturedAction, CaptureResult } from './types';
8
+ /**
9
+ * Default capture session implementation.
10
+ *
11
+ * Orchestrates:
12
+ * 1. Deduplication check
13
+ * 2. Payload hashing (input/output)
14
+ * 3. Entry creation with chain linking
15
+ * 4. Spool storage
16
+ * 5. Dedupe index update
17
+ */
18
+ export declare class DefaultCaptureSession implements CaptureSession {
19
+ private readonly store;
20
+ private readonly dedupe;
21
+ private readonly hasher;
22
+ private closed;
23
+ private captureQueue;
24
+ constructor(config: CaptureSessionConfig);
25
+ /**
26
+ * Capture an action.
27
+ *
28
+ * Process:
29
+ * 1. Validate action
30
+ * 2. Serialize via queue (prevents race conditions)
31
+ * 3. Check for duplicate (by action.id)
32
+ * 4. Hash input/output payloads
33
+ * 5. Create spool entry with chain link
34
+ * 6. Append to spool
35
+ * 7. Update dedupe index
36
+ *
37
+ * Concurrency: Capture calls are serialized to prevent race conditions
38
+ * on sequence numbers and chain linkage.
39
+ *
40
+ * GUARANTEE: This method NEVER throws. All failures are returned as
41
+ * CaptureResult with success=false. This ensures the capture queue
42
+ * remains healthy and subsequent captures can proceed.
43
+ */
44
+ capture(action: CapturedAction): Promise<CaptureResult>;
45
+ /**
46
+ * Internal capture logic (runs serialized).
47
+ *
48
+ * IMPORTANT: This method must NEVER throw - it always returns CaptureResult.
49
+ * This is critical for queue safety: if this throws, the queue chain would
50
+ * propagate the rejection to the caller while the queue itself stays healthy.
51
+ */
52
+ private captureInternal;
53
+ /**
54
+ * Commit pending writes to durable storage.
55
+ */
56
+ commit(): Promise<void>;
57
+ /**
58
+ * Get the current spool head digest.
59
+ */
60
+ getHeadDigest(): Promise<string>;
61
+ /**
62
+ * Close the session and release resources.
63
+ */
64
+ close(): Promise<void>;
65
+ /**
66
+ * Validate action has required fields.
67
+ */
68
+ private validateAction;
69
+ /**
70
+ * Strip payload bytes from action for storage.
71
+ */
72
+ private stripPayloadBytes;
73
+ /**
74
+ * Assert session is not closed.
75
+ */
76
+ private assertNotClosed;
77
+ }
78
+ /**
79
+ * Create a capture session.
80
+ */
81
+ export declare function createCaptureSession(config: CaptureSessionConfig): CaptureSession;
82
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACpB,cAAc,EACd,aAAa,EAKd,MAAM,SAAS,CAAC;AAMjB;;;;;;;;;GASG;AACH,qBAAa,qBAAsB,YAAW,cAAc;IAC1D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,MAAM,CAAkB;IAIhC,OAAO,CAAC,YAAY,CAAoC;gBAE5C,MAAM,EAAE,oBAAoB;IAMxC;;;;;;;;;;;;;;;;;;OAkBG;IACG,OAAO,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAgD7D;;;;;;OAMG;YACW,eAAe;IA6E7B;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAK7B;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAKtC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B;;OAEG;IACH,OAAO,CAAC,cAAc;IAoBtB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAQzB;;OAEG;IACH,OAAO,CAAC,eAAe;CAKxB;AAMD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,GAAG,cAAc,CAEjF"}