@kernel.chat/kbot 3.39.0 → 3.41.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.
@@ -0,0 +1,90 @@
1
+ /** Button style options */
2
+ export type ButtonStyle = 'primary' | 'secondary' | 'success' | 'danger' | 'link';
3
+ /** A single button action definition */
4
+ export interface ButtonAction {
5
+ label: string;
6
+ action: string;
7
+ style?: ButtonStyle;
8
+ }
9
+ /** A registered pending action */
10
+ export interface PendingAction {
11
+ token: string;
12
+ action: string;
13
+ callback_description: string;
14
+ created_at: string;
15
+ expires_at: string;
16
+ executed: boolean;
17
+ executed_at: string | null;
18
+ }
19
+ /** Discord button component (webhook format) */
20
+ interface DiscordButton {
21
+ type: 2;
22
+ style: number;
23
+ label: string;
24
+ custom_id?: string;
25
+ url?: string;
26
+ }
27
+ /** Discord action row */
28
+ interface DiscordActionRow {
29
+ type: 1;
30
+ components: DiscordButton[];
31
+ }
32
+ /** Discord embed */
33
+ export interface DiscordEmbed {
34
+ title?: string;
35
+ description?: string;
36
+ color?: number;
37
+ fields?: Array<{
38
+ name: string;
39
+ value: string;
40
+ inline?: boolean;
41
+ }>;
42
+ footer?: {
43
+ text: string;
44
+ };
45
+ timestamp?: string;
46
+ }
47
+ /** Button set result for different platforms */
48
+ export interface ButtonSet {
49
+ discord: DiscordActionRow;
50
+ email_html: string;
51
+ slack_blocks: unknown[];
52
+ }
53
+ /**
54
+ * Create a formatted button set for different platforms.
55
+ * Registers each action and generates platform-specific markup.
56
+ */
57
+ export declare function createButtonSet(actions: ButtonAction[]): ButtonSet;
58
+ /**
59
+ * Send an email via Resend with clickable action buttons at the bottom.
60
+ * Requires RESEND_API_KEY in environment.
61
+ */
62
+ export declare function createEmailWithButtons(to: string, subject: string, body: string, buttons: ButtonAction[]): Promise<{
63
+ sent: boolean;
64
+ message_id: string | null;
65
+ error: string | null;
66
+ }>;
67
+ /**
68
+ * Send a Discord message with interactive button components.
69
+ */
70
+ export declare function createDiscordWithButtons(webhookUrl: string, embed: DiscordEmbed, buttons: ButtonAction[]): Promise<{
71
+ sent: boolean;
72
+ error: string | null;
73
+ }>;
74
+ /**
75
+ * Process a button click action.
76
+ * Reads the action from pending-actions, marks it as executed.
77
+ */
78
+ export declare function handleButtonAction(token: string, action: string): {
79
+ handled: boolean;
80
+ action: string;
81
+ callback_description: string;
82
+ error: string | null;
83
+ };
84
+ /**
85
+ * Register an action with a unique token.
86
+ * Saves to ~/.kbot/pending-actions/. Expires after 72 hours.
87
+ */
88
+ export declare function registerAction(action: string, callback_description: string): string;
89
+ export {};
90
+ //# sourceMappingURL=interactive-buttons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactive-buttons.d.ts","sourceRoot":"","sources":["../src/interactive-buttons.ts"],"names":[],"mappings":"AAqBA,2BAA2B;AAC3B,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAA;AAEjF,wCAAwC;AACxC,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,WAAW,CAAA;CACpB;AAED,kCAAkC;AAClC,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,oBAAoB,EAAE,MAAM,CAAA;IAC5B,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAED,gDAAgD;AAChD,UAAU,aAAa;IACrB,IAAI,EAAE,CAAC,CAAA;IACP,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,yBAAyB;AACzB,UAAU,gBAAgB;IACxB,IAAI,EAAE,CAAC,CAAA;IACP,UAAU,EAAE,aAAa,EAAE,CAAA;CAC5B;AAED,oBAAoB;AACpB,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;IACjE,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,gDAAgD;AAChD,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,gBAAgB,CAAA;IACzB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,OAAO,EAAE,CAAA;CACxB;AAkCD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,SAAS,CAoDlE;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,YAAY,EAAE,GACtB,OAAO,CAAC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAiD7E;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,YAAY,EAAE,GACtB,OAAO,CAAC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CA6ClD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,oBAAoB,EAAE,MAAM,CAAA;IAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB,CA0CA;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,GAAG,MAAM,CAuBnF"}
@@ -0,0 +1,286 @@
1
+ // kbot Interactive Response Buttons
2
+ //
3
+ // When kbot sends emails or Discord messages, include action buttons.
4
+ // Buttons link to response endpoints that trigger follow-up actions.
5
+ //
6
+ // Supports: Discord (webhook), Email (Resend), Slack (Block Kit, future)
7
+ //
8
+ // Pending actions stored at: ~/.kbot/pending-actions/
9
+ import { homedir } from 'node:os';
10
+ import { join } from 'node:path';
11
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, rmSync, } from 'node:fs';
12
+ import { randomUUID } from 'node:crypto';
13
+ const PENDING_DIR = join(homedir(), '.kbot', 'pending-actions');
14
+ const ACTION_EXPIRY_MS = 72 * 60 * 60 * 1000; // 72 hours
15
+ const ACTION_BASE_URL = 'https://kernel.chat/api/action';
16
+ function ensureDir() {
17
+ if (!existsSync(PENDING_DIR))
18
+ mkdirSync(PENDING_DIR, { recursive: true });
19
+ }
20
+ function actionPath(token) {
21
+ return join(PENDING_DIR, `${token}.json`);
22
+ }
23
+ /** Map ButtonStyle to Discord button style number */
24
+ function discordStyleNumber(style) {
25
+ const map = {
26
+ primary: 1,
27
+ secondary: 2,
28
+ success: 3,
29
+ danger: 4,
30
+ link: 5,
31
+ };
32
+ return map[style] || 2;
33
+ }
34
+ /** Map ButtonStyle to email button color */
35
+ function emailButtonColor(style) {
36
+ const map = {
37
+ primary: '#6B5B95',
38
+ secondary: '#6c757d',
39
+ success: '#28a745',
40
+ danger: '#dc3545',
41
+ link: '#007bff',
42
+ };
43
+ return map[style] || '#6B5B95';
44
+ }
45
+ /**
46
+ * Create a formatted button set for different platforms.
47
+ * Registers each action and generates platform-specific markup.
48
+ */
49
+ export function createButtonSet(actions) {
50
+ // Register actions and get tokens
51
+ const registeredActions = actions.map(a => ({
52
+ ...a,
53
+ token: registerAction(a.action, `Button: ${a.label}`),
54
+ }));
55
+ // Discord: action row with buttons
56
+ const discordButtons = registeredActions.map(a => ({
57
+ type: 2,
58
+ style: discordStyleNumber(a.style || 'primary'),
59
+ label: a.label,
60
+ // For link style, use URL; otherwise use custom_id
61
+ ...(a.style === 'link'
62
+ ? { url: `${ACTION_BASE_URL}?token=${a.token}&action=${encodeURIComponent(a.action)}` }
63
+ : { custom_id: `kbot_action_${a.token}` }),
64
+ }));
65
+ const discord = {
66
+ type: 1,
67
+ components: discordButtons,
68
+ };
69
+ // Email: HTML buttons
70
+ const emailButtons = registeredActions.map(a => {
71
+ const color = emailButtonColor(a.style || 'primary');
72
+ const url = `${ACTION_BASE_URL}?token=${a.token}&action=${encodeURIComponent(a.action)}`;
73
+ return `<a href="${url}" style="display:inline-block;padding:10px 24px;margin:4px 8px 4px 0;background-color:${color};color:#ffffff;text-decoration:none;border-radius:6px;font-family:'Courier Prime',monospace;font-size:14px;font-weight:bold;">${escapeHtml(a.label)}</a>`;
74
+ });
75
+ const email_html = `<div style="margin-top:24px;padding-top:16px;border-top:1px solid #e5e5e5;">${emailButtons.join('\n')}</div>`;
76
+ // Slack: Block Kit buttons (future use)
77
+ const slack_blocks = [
78
+ {
79
+ type: 'actions',
80
+ elements: registeredActions.map(a => ({
81
+ type: 'button',
82
+ text: {
83
+ type: 'plain_text',
84
+ text: a.label,
85
+ emoji: true,
86
+ },
87
+ action_id: `kbot_${a.action}`,
88
+ value: a.token,
89
+ ...(a.style === 'danger' ? { style: 'danger' } : {}),
90
+ ...(a.style === 'primary' ? { style: 'primary' } : {}),
91
+ })),
92
+ },
93
+ ];
94
+ return { discord, email_html, slack_blocks };
95
+ }
96
+ /**
97
+ * Send an email via Resend with clickable action buttons at the bottom.
98
+ * Requires RESEND_API_KEY in environment.
99
+ */
100
+ export async function createEmailWithButtons(to, subject, body, buttons) {
101
+ const apiKey = process.env.RESEND_API_KEY;
102
+ if (!apiKey) {
103
+ return { sent: false, message_id: null, error: 'RESEND_API_KEY not configured' };
104
+ }
105
+ const buttonSet = createButtonSet(buttons);
106
+ const htmlBody = `
107
+ <!DOCTYPE html>
108
+ <html>
109
+ <head><meta charset="utf-8"></head>
110
+ <body style="font-family:'EB Garamond','Georgia',serif;color:#1a1a1a;background-color:#FFFFF0;padding:32px;max-width:600px;margin:0 auto;">
111
+ <div style="font-family:'Courier Prime',monospace;font-size:12px;color:#6B5B95;text-transform:uppercase;letter-spacing:2px;margin-bottom:16px;">kernel.chat</div>
112
+ <h2 style="font-family:'EB Garamond','Georgia',serif;margin:0 0 16px 0;">${escapeHtml(subject)}</h2>
113
+ <div style="line-height:1.6;">${body}</div>
114
+ ${buttonSet.email_html}
115
+ <div style="margin-top:32px;padding-top:16px;border-top:1px solid #e5e5e5;font-size:12px;color:#999;">
116
+ Sent by kbot &mdash; <a href="https://kernel.chat" style="color:#6B5B95;">kernel.chat</a>
117
+ </div>
118
+ </body>
119
+ </html>`;
120
+ try {
121
+ const res = await fetch('https://api.resend.com/emails', {
122
+ method: 'POST',
123
+ headers: {
124
+ 'Content-Type': 'application/json',
125
+ 'Authorization': `Bearer ${apiKey}`,
126
+ },
127
+ body: JSON.stringify({
128
+ from: 'kbot <noreply@kernel.chat>',
129
+ to: [to],
130
+ subject,
131
+ html: htmlBody,
132
+ }),
133
+ signal: AbortSignal.timeout(15_000),
134
+ });
135
+ if (!res.ok) {
136
+ const errText = await res.text();
137
+ return { sent: false, message_id: null, error: `Resend API error: ${res.status} ${errText}` };
138
+ }
139
+ const result = await res.json();
140
+ return { sent: true, message_id: result.id || null, error: null };
141
+ }
142
+ catch (err) {
143
+ return { sent: false, message_id: null, error: err.message };
144
+ }
145
+ }
146
+ /**
147
+ * Send a Discord message with interactive button components.
148
+ */
149
+ export async function createDiscordWithButtons(webhookUrl, embed, buttons) {
150
+ const buttonSet = createButtonSet(buttons);
151
+ // For webhook-based messages, buttons must use link style (URL buttons)
152
+ // since webhooks can't receive interaction callbacks
153
+ const linkButtons = buttons.map(b => {
154
+ const token = registerAction(b.action, `Discord button: ${b.label}`);
155
+ return {
156
+ type: 2,
157
+ style: 5, // Link style for webhook messages
158
+ label: b.label,
159
+ url: `${ACTION_BASE_URL}?token=${token}&action=${encodeURIComponent(b.action)}`,
160
+ };
161
+ });
162
+ const actionRow = {
163
+ type: 1,
164
+ components: linkButtons,
165
+ };
166
+ const payload = {
167
+ embeds: [embed],
168
+ components: [actionRow],
169
+ };
170
+ // Use buttonSet to suppress unused variable — Slack blocks stored for future
171
+ void buttonSet.slack_blocks;
172
+ try {
173
+ const res = await fetch(webhookUrl, {
174
+ method: 'POST',
175
+ headers: { 'Content-Type': 'application/json' },
176
+ body: JSON.stringify(payload),
177
+ signal: AbortSignal.timeout(15_000),
178
+ });
179
+ if (!res.ok) {
180
+ const errText = await res.text();
181
+ return { sent: false, error: `Discord webhook error: ${res.status} ${errText}` };
182
+ }
183
+ return { sent: true, error: null };
184
+ }
185
+ catch (err) {
186
+ return { sent: false, error: err.message };
187
+ }
188
+ }
189
+ /**
190
+ * Process a button click action.
191
+ * Reads the action from pending-actions, marks it as executed.
192
+ */
193
+ export function handleButtonAction(token, action) {
194
+ ensureDir();
195
+ const path = actionPath(token);
196
+ if (!existsSync(path)) {
197
+ return { handled: false, action, callback_description: '', error: 'Action token not found' };
198
+ }
199
+ let pending;
200
+ try {
201
+ pending = JSON.parse(readFileSync(path, 'utf-8'));
202
+ }
203
+ catch {
204
+ return { handled: false, action, callback_description: '', error: 'Failed to read action' };
205
+ }
206
+ // Check if expired
207
+ if (new Date(pending.expires_at).getTime() < Date.now()) {
208
+ rmSync(path);
209
+ return { handled: false, action, callback_description: pending.callback_description, error: 'Action expired' };
210
+ }
211
+ // Check if already executed
212
+ if (pending.executed) {
213
+ return { handled: false, action, callback_description: pending.callback_description, error: 'Action already executed' };
214
+ }
215
+ // Verify action matches
216
+ if (pending.action !== action) {
217
+ return { handled: false, action, callback_description: pending.callback_description, error: 'Action mismatch' };
218
+ }
219
+ // Mark as executed
220
+ pending.executed = true;
221
+ pending.executed_at = new Date().toISOString();
222
+ writeFileSync(path, JSON.stringify(pending, null, 2));
223
+ return {
224
+ handled: true,
225
+ action: pending.action,
226
+ callback_description: pending.callback_description,
227
+ error: null,
228
+ };
229
+ }
230
+ /**
231
+ * Register an action with a unique token.
232
+ * Saves to ~/.kbot/pending-actions/. Expires after 72 hours.
233
+ */
234
+ export function registerAction(action, callback_description) {
235
+ ensureDir();
236
+ const token = randomUUID();
237
+ const now = new Date();
238
+ const expires = new Date(now.getTime() + ACTION_EXPIRY_MS);
239
+ const pending = {
240
+ token,
241
+ action,
242
+ callback_description,
243
+ created_at: now.toISOString(),
244
+ expires_at: expires.toISOString(),
245
+ executed: false,
246
+ executed_at: null,
247
+ };
248
+ writeFileSync(actionPath(token), JSON.stringify(pending, null, 2));
249
+ // Prune expired actions in the background
250
+ pruneExpiredActions();
251
+ return token;
252
+ }
253
+ /** Remove expired pending actions */
254
+ function pruneExpiredActions() {
255
+ ensureDir();
256
+ try {
257
+ const files = readdirSync(PENDING_DIR).filter(f => f.endsWith('.json'));
258
+ const now = Date.now();
259
+ for (const file of files) {
260
+ const path = join(PENDING_DIR, file);
261
+ try {
262
+ const pending = JSON.parse(readFileSync(path, 'utf-8'));
263
+ if (new Date(pending.expires_at).getTime() < now) {
264
+ rmSync(path);
265
+ }
266
+ }
267
+ catch {
268
+ // Corrupt file — remove it
269
+ rmSync(path, { force: true });
270
+ }
271
+ }
272
+ }
273
+ catch {
274
+ // Non-critical — pruning can fail silently
275
+ }
276
+ }
277
+ /** Escape HTML special characters */
278
+ function escapeHtml(text) {
279
+ return text
280
+ .replace(/&/g, '&amp;')
281
+ .replace(/</g, '&lt;')
282
+ .replace(/>/g, '&gt;')
283
+ .replace(/"/g, '&quot;')
284
+ .replace(/'/g, '&#39;');
285
+ }
286
+ //# sourceMappingURL=interactive-buttons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactive-buttons.js","sourceRoot":"","sources":["../src/interactive-buttons.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ export type KnowledgeSource = 'conversation' | 'forge' | 'pattern' | 'web_search' | 'user_question' | 'email' | 'manual';
2
+ export interface KnowledgeEntry {
3
+ /** Unique ID (SHA-256 hash of content + source) */
4
+ id: string;
5
+ /** Primary topic this entry belongs to */
6
+ topic: string;
7
+ /** The actual knowledge content */
8
+ content: string;
9
+ /** Where this knowledge came from */
10
+ source: KnowledgeSource;
11
+ /** Source detail (e.g., tool name, email subject, URL) */
12
+ sourceDetail: string;
13
+ /** Confidence in this knowledge (0-1) */
14
+ confidence: number;
15
+ /** Tags for cross-referencing */
16
+ tags: string[];
17
+ /** When this entry was created */
18
+ createdAt: string;
19
+ /** When this entry was last verified/updated */
20
+ updatedAt: string;
21
+ }
22
+ export interface KnowledgeIndex {
23
+ /** Total number of entries across all topics */
24
+ totalEntries: number;
25
+ /** Map of topic slug -> entry count */
26
+ topics: Record<string, number>;
27
+ /** Map of source type -> entry count */
28
+ sources: Record<string, number>;
29
+ /** Last time the index was updated */
30
+ lastUpdated: string;
31
+ }
32
+ export interface KnowledgeQueryResult {
33
+ /** The matching entry */
34
+ entry: KnowledgeEntry;
35
+ /** Relevance score (higher = more relevant) */
36
+ relevance: number;
37
+ }
38
+ export interface KnowledgeStats {
39
+ total_entries: number;
40
+ topics: string[];
41
+ sources: Record<string, number>;
42
+ last_updated: string;
43
+ }
44
+ export declare class KnowledgeBase {
45
+ private indexCache;
46
+ constructor();
47
+ /**
48
+ * Add knowledge from any source.
49
+ * Deduplicates by content hash.
50
+ * Tags with source, confidence, timestamp.
51
+ */
52
+ ingest(source: KnowledgeSource, content: string, metadata?: {
53
+ topic?: string;
54
+ sourceDetail?: string;
55
+ confidence?: number;
56
+ tags?: string[];
57
+ }): KnowledgeEntry;
58
+ /**
59
+ * Search the knowledge base for relevant entries.
60
+ * Uses keyword matching + cosine similarity on TF-IDF vectors.
61
+ * Returns ranked results with sources.
62
+ */
63
+ query(question: string): KnowledgeQueryResult[];
64
+ /**
65
+ * Get everything kbot knows about a topic, synthesized into a readable summary.
66
+ * Pulls from all sources and organizes by type.
67
+ */
68
+ getTopicSummary(topic: string): string;
69
+ /**
70
+ * Extract knowledge from an email/conversation thread.
71
+ * Pulls out facts, decisions, recommendations.
72
+ */
73
+ addFromConversation(userEmail: string, messages: Array<{
74
+ role: string;
75
+ content: string;
76
+ }>): KnowledgeEntry[];
77
+ /**
78
+ * When a tool is forged, extract what problem it solves and add to KB.
79
+ */
80
+ addFromForge(tool: {
81
+ name: string;
82
+ description: string;
83
+ tags?: string[];
84
+ code?: string;
85
+ }): KnowledgeEntry;
86
+ /**
87
+ * Get knowledge base statistics.
88
+ */
89
+ getStats(): KnowledgeStats;
90
+ /** Load or rebuild the index */
91
+ private loadIndex;
92
+ /** Rebuild the index from all topic files */
93
+ private rebuildIndex;
94
+ }
95
+ //# sourceMappingURL=knowledge-base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"knowledge-base.d.ts","sourceRoot":"","sources":["../src/knowledge-base.ts"],"names":[],"mappings":"AAyBA,MAAM,MAAM,eAAe,GACvB,cAAc,GACd,OAAO,GACP,SAAS,GACT,YAAY,GACZ,eAAe,GACf,OAAO,GACP,QAAQ,CAAA;AAEZ,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,EAAE,EAAE,MAAM,CAAA;IACV,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAA;IACb,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,qCAAqC;IACrC,MAAM,EAAE,eAAe,CAAA;IACvB,0DAA0D;IAC1D,YAAY,EAAE,MAAM,CAAA;IACpB,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAA;IAClB,iCAAiC;IACjC,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAA;IACjB,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,YAAY,EAAE,MAAM,CAAA;IACpB,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,yBAAyB;IACzB,KAAK,EAAE,cAAc,CAAA;IACrB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,YAAY,EAAE,MAAM,CAAA;CACrB;AA+MD,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAA8B;;IAMhD;;;;OAIG;IACH,MAAM,CACJ,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE;QACT,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,YAAY,CAAC,EAAE,MAAM,CAAA;QACrB,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAChB,GACA,cAAc;IA8CjB;;;;OAIG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,oBAAoB,EAAE;IAkD/C;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAsFtC;;;OAGG;IACH,mBAAmB,CACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,GACjD,cAAc,EAAE;IAuBnB;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE;QACjB,IAAI,EAAE,MAAM,CAAA;QACZ,WAAW,EAAE,MAAM,CAAA;QACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;QACf,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,GAAG,cAAc;IAgBlB;;OAEG;IACH,QAAQ,IAAI,cAAc;IAa1B,gCAAgC;IAChC,OAAO,CAAC,SAAS;IAWjB,6CAA6C;IAC7C,OAAO,CAAC,YAAY;CAuCrB"}