mcp-resend 1.0.0-1

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.
Files changed (56) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +257 -0
  3. package/data/embeddings.json +245241 -0
  4. package/dist/config/environment.d.ts +152 -0
  5. package/dist/config/environment.d.ts.map +1 -0
  6. package/dist/config/environment.js +217 -0
  7. package/dist/config/environment.js.map +1 -0
  8. package/dist/index.d.ts +13 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +119 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/services/rate-limiter.d.ts +90 -0
  13. package/dist/services/rate-limiter.d.ts.map +1 -0
  14. package/dist/services/rate-limiter.js +267 -0
  15. package/dist/services/rate-limiter.js.map +1 -0
  16. package/dist/services/tool-registry.d.ts +219 -0
  17. package/dist/services/tool-registry.d.ts.map +1 -0
  18. package/dist/services/tool-registry.js +459 -0
  19. package/dist/services/tool-registry.js.map +1 -0
  20. package/dist/tools/docs/embeddings-loader.d.ts +69 -0
  21. package/dist/tools/docs/embeddings-loader.d.ts.map +1 -0
  22. package/dist/tools/docs/embeddings-loader.js +218 -0
  23. package/dist/tools/docs/embeddings-loader.js.map +1 -0
  24. package/dist/tools/docs/errors.d.ts +75 -0
  25. package/dist/tools/docs/errors.d.ts.map +1 -0
  26. package/dist/tools/docs/errors.js +145 -0
  27. package/dist/tools/docs/errors.js.map +1 -0
  28. package/dist/tools/docs/index.d.ts +11 -0
  29. package/dist/tools/docs/index.d.ts.map +1 -0
  30. package/dist/tools/docs/index.js +14 -0
  31. package/dist/tools/docs/index.js.map +1 -0
  32. package/dist/tools/docs/metrics.d.ts +94 -0
  33. package/dist/tools/docs/metrics.d.ts.map +1 -0
  34. package/dist/tools/docs/metrics.js +174 -0
  35. package/dist/tools/docs/metrics.js.map +1 -0
  36. package/dist/tools/docs/search-docs-tool.d.ts +54 -0
  37. package/dist/tools/docs/search-docs-tool.d.ts.map +1 -0
  38. package/dist/tools/docs/search-docs-tool.js +231 -0
  39. package/dist/tools/docs/search-docs-tool.js.map +1 -0
  40. package/dist/tools/docs/types.d.ts +70 -0
  41. package/dist/tools/docs/types.d.ts.map +1 -0
  42. package/dist/tools/docs/types.js +7 -0
  43. package/dist/tools/docs/types.js.map +1 -0
  44. package/dist/tools/docs/vector-search.d.ts +80 -0
  45. package/dist/tools/docs/vector-search.d.ts.map +1 -0
  46. package/dist/tools/docs/vector-search.js +297 -0
  47. package/dist/tools/docs/vector-search.js.map +1 -0
  48. package/dist/tools/index.d.ts +27 -0
  49. package/dist/tools/index.d.ts.map +1 -0
  50. package/dist/tools/index.js +3413 -0
  51. package/dist/tools/index.js.map +1 -0
  52. package/dist/utils/mcp-errors.d.ts +109 -0
  53. package/dist/utils/mcp-errors.d.ts.map +1 -0
  54. package/dist/utils/mcp-errors.js +306 -0
  55. package/dist/utils/mcp-errors.js.map +1 -0
  56. package/package.json +77 -0
@@ -0,0 +1,267 @@
1
+ /**
2
+ * Rate Limiter for Resend API
3
+ *
4
+ * Provides rate limiting with queue-based processing and exponential backoff retry
5
+ * to ensure compliance with Resend API rate limits.
6
+ *
7
+ * @module services/rate-limiter
8
+ */
9
+ // NOTE: Use console.error for logging - stdout is reserved for MCP protocol
10
+ const log = (message) => console.error(`[rate-limiter] ${message}`);
11
+ /**
12
+ * Default minimum interval between API calls in milliseconds.
13
+ * Resend free tier allows 2 requests/second, so 500ms provides safety margin.
14
+ */
15
+ export const RATE_LIMIT_INTERVAL_MS = 500;
16
+ /**
17
+ * Default maximum number of retries for rate-limited requests.
18
+ */
19
+ export const DEFAULT_MAX_RETRIES = 3;
20
+ /**
21
+ * Base delay for exponential backoff in milliseconds.
22
+ */
23
+ const BASE_BACKOFF_MS = 1000;
24
+ /**
25
+ * Maximum delay for exponential backoff in milliseconds.
26
+ */
27
+ const MAX_BACKOFF_MS = 32000;
28
+ /**
29
+ * Module-level state for the rate limiter.
30
+ */
31
+ let lastCallTime = 0;
32
+ let rateLimitIntervalMs = RATE_LIMIT_INTERVAL_MS;
33
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
+ const queue = [];
35
+ let isProcessing = false;
36
+ let debugMode = false;
37
+ /**
38
+ * Configure the rate limiter settings.
39
+ *
40
+ * @param options - Configuration options
41
+ */
42
+ export function configureRateLimiter(options) {
43
+ if (options.intervalMs !== undefined) {
44
+ rateLimitIntervalMs = Math.max(0, options.intervalMs);
45
+ log(`Rate limit interval set to ${rateLimitIntervalMs}ms`);
46
+ }
47
+ if (options.debug !== undefined) {
48
+ debugMode = options.debug;
49
+ }
50
+ }
51
+ /**
52
+ * Get the current rate limiter configuration.
53
+ *
54
+ * @returns Current configuration
55
+ */
56
+ export function getRateLimiterConfig() {
57
+ return {
58
+ intervalMs: rateLimitIntervalMs,
59
+ queueLength: queue.length,
60
+ isProcessing,
61
+ };
62
+ }
63
+ /**
64
+ * Sleep for a specified number of milliseconds.
65
+ *
66
+ * @param ms - Milliseconds to sleep
67
+ */
68
+ function sleep(ms) {
69
+ return new Promise((resolve) => setTimeout(resolve, ms));
70
+ }
71
+ /**
72
+ * Process the next item in the queue.
73
+ * Ensures sequential execution with minimum interval between calls.
74
+ */
75
+ async function processQueue() {
76
+ if (isProcessing || queue.length === 0) {
77
+ return;
78
+ }
79
+ isProcessing = true;
80
+ while (queue.length > 0) {
81
+ const item = queue.shift();
82
+ // Calculate time to wait before next call
83
+ const now = Date.now();
84
+ const timeSinceLastCall = now - lastCallTime;
85
+ const waitTime = Math.max(0, rateLimitIntervalMs - timeSinceLastCall);
86
+ if (waitTime > 0) {
87
+ if (debugMode) {
88
+ log(`Waiting ${waitTime}ms before next API call`);
89
+ }
90
+ await sleep(waitTime);
91
+ }
92
+ // Execute the function
93
+ try {
94
+ lastCallTime = Date.now();
95
+ const result = await item.fn();
96
+ item.resolve(result);
97
+ }
98
+ catch (error) {
99
+ item.reject(error instanceof Error ? error : new Error(String(error)));
100
+ }
101
+ }
102
+ isProcessing = false;
103
+ }
104
+ /**
105
+ * Execute a function with rate limiting.
106
+ * Queues the function and processes it when the rate limit allows.
107
+ *
108
+ * @param fn - Async function to execute
109
+ * @returns Promise resolving to the function result
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * const result = await withRateLimit(() => resendClient.emails.send(params));
114
+ * ```
115
+ */
116
+ export function withRateLimit(fn) {
117
+ return new Promise((resolve, reject) => {
118
+ queue.push({ fn, resolve, reject });
119
+ // Start processing if not already running
120
+ // NOTE: Using void to explicitly ignore the promise (fire and forget)
121
+ void processQueue();
122
+ });
123
+ }
124
+ /**
125
+ * Check if an error is a rate limit error (HTTP 429).
126
+ *
127
+ * @param error - Error to check
128
+ * @returns True if the error is a rate limit error
129
+ */
130
+ function isRateLimitError(error) {
131
+ if (error instanceof Error) {
132
+ // Check error message for 429 status
133
+ if (error.message.includes("429") || error.message.includes("rate limit")) {
134
+ return true;
135
+ }
136
+ // Check if error has a status property
137
+ const errorWithStatus = error;
138
+ return errorWithStatus.status === 429 || errorWithStatus.statusCode === 429;
139
+ }
140
+ return false;
141
+ }
142
+ /**
143
+ * Extract Retry-After value from error response.
144
+ * Supports both seconds (integer) and HTTP-date formats.
145
+ *
146
+ * @param error - Error that may contain Retry-After header
147
+ * @returns Delay in milliseconds, or undefined if not present
148
+ */
149
+ function extractRetryAfter(error) {
150
+ if (typeof error !== "object" || error === null) {
151
+ return undefined;
152
+ }
153
+ const errorObj = error;
154
+ // Check for headers object (common in HTTP client errors)
155
+ const headers = errorObj.headers;
156
+ const retryAfterValue = headers?.["retry-after"] ||
157
+ headers?.["Retry-After"] ||
158
+ errorObj.retryAfter;
159
+ if (retryAfterValue === undefined) {
160
+ return undefined;
161
+ }
162
+ // If it's a number, treat as seconds
163
+ if (typeof retryAfterValue === "number") {
164
+ return retryAfterValue * 1000;
165
+ }
166
+ // Try to parse as integer (seconds)
167
+ const seconds = parseInt(retryAfterValue, 10);
168
+ if (!isNaN(seconds)) {
169
+ return seconds * 1000;
170
+ }
171
+ // Try to parse as HTTP-date
172
+ const date = new Date(retryAfterValue);
173
+ if (!isNaN(date.getTime())) {
174
+ const delayMs = date.getTime() - Date.now();
175
+ return delayMs > 0 ? delayMs : undefined;
176
+ }
177
+ return undefined;
178
+ }
179
+ /**
180
+ * Calculate exponential backoff delay.
181
+ *
182
+ * @param attempt - Current attempt number (0-indexed)
183
+ * @returns Delay in milliseconds
184
+ */
185
+ function calculateBackoff(attempt) {
186
+ // Exponential backoff: base * 2^attempt with jitter
187
+ const exponentialDelay = BASE_BACKOFF_MS * Math.pow(2, attempt);
188
+ // Add random jitter (0-25% of delay)
189
+ const jitter = Math.random() * 0.25 * exponentialDelay;
190
+ return Math.min(exponentialDelay + jitter, MAX_BACKOFF_MS);
191
+ }
192
+ /**
193
+ * Execute a function with automatic retry on rate limit errors.
194
+ * Uses exponential backoff with jitter.
195
+ *
196
+ * @param fn - Async function to execute
197
+ * @param maxRetries - Maximum number of retry attempts (default: 3)
198
+ * @returns Promise resolving to the function result
199
+ * @throws Error if all retries are exhausted
200
+ *
201
+ * @example
202
+ * ```typescript
203
+ * const result = await withRetry(
204
+ * () => resendClient.emails.send(params),
205
+ * 3
206
+ * );
207
+ * ```
208
+ */
209
+ export async function withRetry(fn, maxRetries = DEFAULT_MAX_RETRIES) {
210
+ let lastError;
211
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
212
+ try {
213
+ return await fn();
214
+ }
215
+ catch (error) {
216
+ lastError = error instanceof Error ? error : new Error(String(error));
217
+ // Only retry on rate limit errors
218
+ if (!isRateLimitError(error)) {
219
+ throw lastError;
220
+ }
221
+ // Check if we have retries left
222
+ if (attempt < maxRetries) {
223
+ // Prefer Retry-After header if present, otherwise use exponential backoff
224
+ const retryAfterDelay = extractRetryAfter(error);
225
+ const delay = retryAfterDelay ?? calculateBackoff(attempt);
226
+ const delaySource = retryAfterDelay ? "Retry-After header" : "exponential backoff";
227
+ log(`Rate limited (attempt ${attempt + 1}/${maxRetries + 1}), ` +
228
+ `retrying in ${Math.round(delay)}ms (${delaySource})`);
229
+ await sleep(delay);
230
+ }
231
+ }
232
+ }
233
+ // All retries exhausted
234
+ throw new Error(`Rate limit exceeded after ${maxRetries + 1} attempts: ${lastError?.message || "Unknown error"}`);
235
+ }
236
+ /**
237
+ * Execute a function with both rate limiting and retry logic.
238
+ * This is the recommended function for most Resend API calls.
239
+ *
240
+ * @param fn - Async function to execute
241
+ * @param maxRetries - Maximum number of retry attempts (default: 3)
242
+ * @returns Promise resolving to the function result
243
+ *
244
+ * @example
245
+ * ```typescript
246
+ * const result = await withRateLimitAndRetry(
247
+ * () => resendClient.emails.send(params),
248
+ * 3
249
+ * );
250
+ * ```
251
+ */
252
+ export async function withRateLimitAndRetry(fn, maxRetries = DEFAULT_MAX_RETRIES) {
253
+ return withRateLimit(() => withRetry(fn, maxRetries));
254
+ }
255
+ /**
256
+ * Reset the rate limiter state.
257
+ * Useful for testing or reconfiguration.
258
+ */
259
+ export function resetRateLimiter() {
260
+ lastCallTime = 0;
261
+ queue.length = 0;
262
+ isProcessing = false;
263
+ rateLimitIntervalMs = RATE_LIMIT_INTERVAL_MS;
264
+ debugMode = false;
265
+ log("Rate limiter reset");
266
+ }
267
+ //# sourceMappingURL=rate-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/services/rate-limiter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Tool Registry for Dynamic MCP Tool Discovery
3
+ *
4
+ * Manages tool loading/unloading by tier and scope, enabling dynamic tool discovery
5
+ * and permission-based access control.
6
+ *
7
+ * @module services/tool-registry
8
+ */
9
+ import type { Server } from "@modelcontextprotocol/sdk/server/index.js";
10
+ import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
11
+ import type { ToolScope, ToolTier } from "../config/environment.js";
12
+ /**
13
+ * Re-export tier and scope types for convenience.
14
+ */
15
+ export type { ToolTier, ToolScope };
16
+ /**
17
+ * MCP tool input schema (JSON Schema format).
18
+ */
19
+ export interface ToolInputSchema {
20
+ type: "object";
21
+ properties: Record<string, unknown>;
22
+ required?: string[];
23
+ }
24
+ /**
25
+ * Tool annotations for MCP clients.
26
+ */
27
+ export interface ToolAnnotations {
28
+ title?: string;
29
+ readOnlyHint?: boolean;
30
+ destructiveHint?: boolean;
31
+ idempotentHint?: boolean;
32
+ openWorldHint?: boolean;
33
+ }
34
+ /**
35
+ * MCP tool definition returned to clients.
36
+ */
37
+ export interface MCPToolDefinition {
38
+ name: string;
39
+ description: string;
40
+ inputSchema: ToolInputSchema;
41
+ annotations?: ToolAnnotations;
42
+ }
43
+ /**
44
+ * Tool response format from execute function.
45
+ * Re-exports SDK's CallToolResult for proper type compatibility.
46
+ */
47
+ export type ToolResponse = CallToolResult;
48
+ /**
49
+ * Internal tool definition with metadata.
50
+ */
51
+ export interface ToolDefinition {
52
+ /** Unique tool name (e.g., "send_email") */
53
+ name: string;
54
+ /** Human-readable description */
55
+ description: string;
56
+ /** JSON Schema for input validation */
57
+ inputSchema: ToolInputSchema;
58
+ /** Optional MCP annotations */
59
+ annotations?: ToolAnnotations;
60
+ /** Tool tier for loading priority */
61
+ tier: Exclude<ToolTier, "all">;
62
+ /** Required scopes for this tool */
63
+ scopes: ToolScope[];
64
+ /** Execute function for the tool */
65
+ execute: (args: unknown) => Promise<ToolResponse>;
66
+ }
67
+ /**
68
+ * Registry statistics for debugging.
69
+ */
70
+ export interface RegistryStats {
71
+ /** Total registered tools */
72
+ totalRegistered: number;
73
+ /** Currently enabled tools */
74
+ totalEnabled: number;
75
+ /** Tools by tier */
76
+ byTier: {
77
+ core: number;
78
+ secondary: number;
79
+ tertiary: number;
80
+ };
81
+ /** Enabled tools by tier */
82
+ enabledByTier: {
83
+ core: number;
84
+ secondary: number;
85
+ tertiary: number;
86
+ };
87
+ /** List of enabled tool names */
88
+ enabledTools: string[];
89
+ }
90
+ /**
91
+ * Core tools - essential functionality (always available).
92
+ */
93
+ export declare const CORE_TOOLS: string[];
94
+ /**
95
+ * Secondary tools - commonly used features.
96
+ */
97
+ export declare const SECONDARY_TOOLS: string[];
98
+ /**
99
+ * Tertiary tools - advanced/admin features.
100
+ * NOTE: API key operations are EXCLUDED for security reasons.
101
+ */
102
+ export declare const TERTIARY_TOOLS: string[];
103
+ /**
104
+ * Initialize the tool registry with an MCP server instance.
105
+ *
106
+ * @param server - MCP Server instance for notifications
107
+ * @param tools - Initial tools to register
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * const server = new Server({ name: "resend-mcp" }, { capabilities: { tools: {} } });
112
+ * initializeRegistry(server, [sendEmailTool, listDomainsTool]);
113
+ * ```
114
+ */
115
+ export declare function initializeRegistry(server: Server, tools?: ToolDefinition[]): void;
116
+ /**
117
+ * Register a tool in the registry.
118
+ *
119
+ * @param tool - Tool definition to register
120
+ */
121
+ export declare function registerTool(tool: ToolDefinition): void;
122
+ /**
123
+ * Unregister a tool from the registry.
124
+ *
125
+ * @param name - Tool name to unregister
126
+ */
127
+ export declare function unregisterTool(name: string): void;
128
+ /**
129
+ * Load all tools of a specific tier (and lower tiers).
130
+ *
131
+ * @param tier - Tier to load (includes all lower tiers)
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * loadTier("secondary"); // Loads core + secondary tools
136
+ * ```
137
+ */
138
+ export declare function loadTier(tier: Exclude<ToolTier, "all">): Promise<void>;
139
+ /**
140
+ * Unload all tools of a specific tier (keeps lower tiers).
141
+ *
142
+ * @param tier - Tier to unload
143
+ *
144
+ * @example
145
+ * ```typescript
146
+ * unloadTier("tertiary"); // Removes only tertiary tools
147
+ * ```
148
+ */
149
+ export declare function unloadTier(tier: Exclude<ToolTier, "all">): Promise<void>;
150
+ /**
151
+ * Load tools by scope(s).
152
+ *
153
+ * @param scopes - Scopes to enable
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * loadByScope(["read", "write"]); // Enable tools with read or write scope
158
+ * ```
159
+ */
160
+ export declare function loadByScope(scopes: ToolScope[]): Promise<void>;
161
+ /**
162
+ * Unload tools by scope(s).
163
+ *
164
+ * @param scopes - Scopes to disable
165
+ */
166
+ export declare function unloadByScope(scopes: ToolScope[]): Promise<void>;
167
+ /**
168
+ * Get all currently enabled tools as MCP tool definitions.
169
+ *
170
+ * @returns Array of MCP tool definitions
171
+ */
172
+ export declare function getEnabledTools(): MCPToolDefinition[];
173
+ /**
174
+ * Check if a tool is currently enabled.
175
+ *
176
+ * @param name - Tool name to check
177
+ * @returns True if tool is enabled
178
+ */
179
+ export declare function isToolEnabled(name: string): boolean;
180
+ /**
181
+ * Get a tool definition by name.
182
+ *
183
+ * @param name - Tool name
184
+ * @returns Tool definition or undefined
185
+ */
186
+ export declare function getTool(name: string): ToolDefinition | undefined;
187
+ /**
188
+ * Get a tool's execute function if the tool is enabled.
189
+ *
190
+ * @param name - Tool name
191
+ * @returns Execute function or undefined
192
+ */
193
+ export declare function getToolExecutor(name: string): ((args: unknown) => Promise<ToolResponse>) | undefined;
194
+ /**
195
+ * Get registry statistics for debugging.
196
+ *
197
+ * @returns Registry statistics
198
+ */
199
+ export declare function getRegistryStats(): RegistryStats;
200
+ /**
201
+ * Reset the registry to initial state.
202
+ * Useful for testing or reconfiguration.
203
+ */
204
+ export declare function resetRegistry(): void;
205
+ /**
206
+ * Enable a specific tool by name.
207
+ *
208
+ * @param name - Tool name to enable
209
+ * @returns True if tool was enabled
210
+ */
211
+ export declare function enableTool(name: string): Promise<boolean>;
212
+ /**
213
+ * Disable a specific tool by name.
214
+ *
215
+ * @param name - Tool name to disable
216
+ * @returns True if tool was disabled
217
+ */
218
+ export declare function disableTool(name: string): Promise<boolean>;
219
+ //# sourceMappingURL=tool-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-registry.d.ts","sourceRoot":"","sources":["../../src/services/tool-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAKpE;;GAEG;AACH,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AAEpC;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,eAAe,CAAC;IAC7B,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,cAAc,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,WAAW,EAAE,eAAe,CAAC;IAC7B,+BAA+B;IAC/B,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,qCAAqC;IACrC,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC/B,oCAAoC;IACpC,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,oCAAoC;IACpC,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;CACnD;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,6BAA6B;IAC7B,eAAe,EAAE,MAAM,CAAC;IACxB,8BAA8B;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB;IACpB,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,4BAA4B;IAC5B,aAAa,EAAE;QACb,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,iCAAiC;IACjC,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAiCD;;GAEG;AACH,eAAO,MAAM,UAAU,UAMtB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,UA8B3B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,UA4C1B,CAAC;AAMF;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,cAAc,EAAO,GAC3B,IAAI,CASN;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CASvD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAiBjD;AAED;;;;;;;;;GASG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAiC5E;AAED;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CA8B9E;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBpE;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBtE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,iBAAiB,EAAE,CAgBrD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEhE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,GACX,CAAC,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC,GAAG,SAAS,CAKxD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CA2BhD;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAQpC;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAe/D;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUhE"}