catalist-support-agent 1.0.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.
Files changed (140) hide show
  1. package/dist/admin-portal.d.ts +43 -0
  2. package/dist/admin-portal.d.ts.map +1 -0
  3. package/dist/admin-portal.js +166 -0
  4. package/dist/admin-portal.js.map +1 -0
  5. package/dist/analysis/entities.d.ts +73 -0
  6. package/dist/analysis/entities.d.ts.map +1 -0
  7. package/dist/analysis/entities.js +378 -0
  8. package/dist/analysis/entities.js.map +1 -0
  9. package/dist/analysis/index.d.ts +44 -0
  10. package/dist/analysis/index.d.ts.map +1 -0
  11. package/dist/analysis/index.js +243 -0
  12. package/dist/analysis/index.js.map +1 -0
  13. package/dist/analysis/intent.d.ts +49 -0
  14. package/dist/analysis/intent.d.ts.map +1 -0
  15. package/dist/analysis/intent.js +320 -0
  16. package/dist/analysis/intent.js.map +1 -0
  17. package/dist/analysis/sentiment.d.ts +57 -0
  18. package/dist/analysis/sentiment.d.ts.map +1 -0
  19. package/dist/analysis/sentiment.js +351 -0
  20. package/dist/analysis/sentiment.js.map +1 -0
  21. package/dist/brand/compliance.d.ts +122 -0
  22. package/dist/brand/compliance.d.ts.map +1 -0
  23. package/dist/brand/compliance.js +378 -0
  24. package/dist/brand/compliance.js.map +1 -0
  25. package/dist/brand/forbidden-terms.d.ts +99 -0
  26. package/dist/brand/forbidden-terms.d.ts.map +1 -0
  27. package/dist/brand/forbidden-terms.js +265 -0
  28. package/dist/brand/forbidden-terms.js.map +1 -0
  29. package/dist/brand/index.d.ts +10 -0
  30. package/dist/brand/index.d.ts.map +1 -0
  31. package/dist/brand/index.js +12 -0
  32. package/dist/brand/index.js.map +1 -0
  33. package/dist/config.d.ts +325 -0
  34. package/dist/config.d.ts.map +1 -0
  35. package/dist/config.js +492 -0
  36. package/dist/config.js.map +1 -0
  37. package/dist/delivery/index.d.ts +84 -0
  38. package/dist/delivery/index.d.ts.map +1 -0
  39. package/dist/delivery/index.js +435 -0
  40. package/dist/delivery/index.js.map +1 -0
  41. package/dist/embeddings/cache.d.ts +96 -0
  42. package/dist/embeddings/cache.d.ts.map +1 -0
  43. package/dist/embeddings/cache.js +193 -0
  44. package/dist/embeddings/cache.js.map +1 -0
  45. package/dist/embeddings/index.d.ts +152 -0
  46. package/dist/embeddings/index.d.ts.map +1 -0
  47. package/dist/embeddings/index.js +337 -0
  48. package/dist/embeddings/index.js.map +1 -0
  49. package/dist/embeddings/openai-client.d.ts +67 -0
  50. package/dist/embeddings/openai-client.d.ts.map +1 -0
  51. package/dist/embeddings/openai-client.js +190 -0
  52. package/dist/embeddings/openai-client.js.map +1 -0
  53. package/dist/errors.d.ts +302 -0
  54. package/dist/errors.d.ts.map +1 -0
  55. package/dist/errors.js +508 -0
  56. package/dist/errors.js.map +1 -0
  57. package/dist/escalation/index.d.ts +93 -0
  58. package/dist/escalation/index.d.ts.map +1 -0
  59. package/dist/escalation/index.js +436 -0
  60. package/dist/escalation/index.js.map +1 -0
  61. package/dist/extraction/deduplication.d.ts +97 -0
  62. package/dist/extraction/deduplication.d.ts.map +1 -0
  63. package/dist/extraction/deduplication.js +271 -0
  64. package/dist/extraction/deduplication.js.map +1 -0
  65. package/dist/extraction/gmail-extractor.d.ts +160 -0
  66. package/dist/extraction/gmail-extractor.d.ts.map +1 -0
  67. package/dist/extraction/gmail-extractor.js +396 -0
  68. package/dist/extraction/gmail-extractor.js.map +1 -0
  69. package/dist/extraction/gmail-token-manager.d.ts +36 -0
  70. package/dist/extraction/gmail-token-manager.d.ts.map +1 -0
  71. package/dist/extraction/gmail-token-manager.js +146 -0
  72. package/dist/extraction/gmail-token-manager.js.map +1 -0
  73. package/dist/extraction/index.d.ts +13 -0
  74. package/dist/extraction/index.d.ts.map +1 -0
  75. package/dist/extraction/index.js +20 -0
  76. package/dist/extraction/index.js.map +1 -0
  77. package/dist/extraction/pii-handler.d.ts +100 -0
  78. package/dist/extraction/pii-handler.d.ts.map +1 -0
  79. package/dist/extraction/pii-handler.js +295 -0
  80. package/dist/extraction/pii-handler.js.map +1 -0
  81. package/dist/extraction/pipeline.d.ts +94 -0
  82. package/dist/extraction/pipeline.d.ts.map +1 -0
  83. package/dist/extraction/pipeline.js +380 -0
  84. package/dist/extraction/pipeline.js.map +1 -0
  85. package/dist/extraction/quality-filter.d.ts +99 -0
  86. package/dist/extraction/quality-filter.d.ts.map +1 -0
  87. package/dist/extraction/quality-filter.js +370 -0
  88. package/dist/extraction/quality-filter.js.map +1 -0
  89. package/dist/extraction/rate-limiter.d.ts +90 -0
  90. package/dist/extraction/rate-limiter.d.ts.map +1 -0
  91. package/dist/extraction/rate-limiter.js +242 -0
  92. package/dist/extraction/rate-limiter.js.map +1 -0
  93. package/dist/extraction/state-manager.d.ts +126 -0
  94. package/dist/extraction/state-manager.d.ts.map +1 -0
  95. package/dist/extraction/state-manager.js +344 -0
  96. package/dist/extraction/state-manager.js.map +1 -0
  97. package/dist/generation/index.d.ts +75 -0
  98. package/dist/generation/index.d.ts.map +1 -0
  99. package/dist/generation/index.js +641 -0
  100. package/dist/generation/index.js.map +1 -0
  101. package/dist/index.d.ts +96 -0
  102. package/dist/index.d.ts.map +1 -0
  103. package/dist/index.js +233 -0
  104. package/dist/index.js.map +1 -0
  105. package/dist/intake/index.d.ts +15 -0
  106. package/dist/intake/index.d.ts.map +1 -0
  107. package/dist/intake/index.js +19 -0
  108. package/dist/intake/index.js.map +1 -0
  109. package/dist/intake/normalizer.d.ts +163 -0
  110. package/dist/intake/normalizer.d.ts.map +1 -0
  111. package/dist/intake/normalizer.js +309 -0
  112. package/dist/intake/normalizer.js.map +1 -0
  113. package/dist/intake/postmark.d.ts +72 -0
  114. package/dist/intake/postmark.d.ts.map +1 -0
  115. package/dist/intake/postmark.js +276 -0
  116. package/dist/intake/postmark.js.map +1 -0
  117. package/dist/intake/slack.d.ts +106 -0
  118. package/dist/intake/slack.d.ts.map +1 -0
  119. package/dist/intake/slack.js +378 -0
  120. package/dist/intake/slack.js.map +1 -0
  121. package/dist/intake/twilio.d.ts +86 -0
  122. package/dist/intake/twilio.d.ts.map +1 -0
  123. package/dist/intake/twilio.js +283 -0
  124. package/dist/intake/twilio.js.map +1 -0
  125. package/dist/knowledge/index.d.ts +100 -0
  126. package/dist/knowledge/index.d.ts.map +1 -0
  127. package/dist/knowledge/index.js +516 -0
  128. package/dist/knowledge/index.js.map +1 -0
  129. package/dist/knowledge/invoice-resolver.d.ts +62 -0
  130. package/dist/knowledge/invoice-resolver.d.ts.map +1 -0
  131. package/dist/knowledge/invoice-resolver.js +267 -0
  132. package/dist/knowledge/invoice-resolver.js.map +1 -0
  133. package/dist/types.d.ts +535 -0
  134. package/dist/types.d.ts.map +1 -0
  135. package/dist/types.js +48 -0
  136. package/dist/types.js.map +1 -0
  137. package/ga-service-account.json +13 -0
  138. package/gmail-knowledge-migration.sql +149 -0
  139. package/nul +1 -0
  140. package/package.json +55 -0
@@ -0,0 +1,320 @@
1
+ /**
2
+ * Intent Classification Service
3
+ *
4
+ * Categorizes support messages into intent categories using Claude.
5
+ * Determines what the customer is asking about or trying to accomplish.
6
+ */
7
+ import Anthropic from '@anthropic-ai/sdk';
8
+ import { config } from '../config.js';
9
+ import { AnalysisError, IntentClassificationError } from '../errors.js';
10
+ // =============================================================================
11
+ // Intent Categories and Descriptions
12
+ // =============================================================================
13
+ const INTENT_DESCRIPTIONS = {
14
+ order_status: 'Inquiries about order status, tracking, delivery, or shipment updates',
15
+ pricing_inquiry: 'Questions about product pricing, discounts, MOQ, or price quotes',
16
+ availability_check: 'Questions about product availability, stock levels, or restocking dates',
17
+ documentation_request: 'Requests for invoices, receipts, certificates, or other documentation',
18
+ returns_damages: 'Issues with damaged products, returns, refunds, or exchanges',
19
+ account_inquiry: 'Questions about account settings, login issues, or account status',
20
+ product_sourcing: 'Requests to find specific products, brands, or alternatives',
21
+ onboarding_help: 'New customer setup, getting started questions, or platform guidance',
22
+ complaint: 'Explicit complaints, frustrations, or negative feedback about service',
23
+ feedback: 'General feedback, suggestions, or positive comments',
24
+ general_question: 'General questions about Catalist, policies, or how things work',
25
+ other: 'Messages that do not fit into any other category',
26
+ };
27
+ // =============================================================================
28
+ // Intent Classification Prompt
29
+ // =============================================================================
30
+ const INTENT_CLASSIFICATION_PROMPT = `You are an intent classification system for Catalist, a B2B marketplace platform.
31
+
32
+ Your task is to classify customer support messages into one of the following intent categories:
33
+
34
+ ${Object.entries(INTENT_DESCRIPTIONS)
35
+ .map(([category, description]) => `- **${category}**: ${description}`)
36
+ .join('\n')}
37
+
38
+ ## Instructions
39
+
40
+ 1. Read the customer message carefully
41
+ 2. Consider the primary intent (what they MOST want)
42
+ 3. Consider if there's a secondary intent
43
+ 4. Provide a confidence score from 0.0 to 1.0
44
+ 5. Briefly explain your reasoning
45
+
46
+ ## Response Format
47
+
48
+ Respond with a JSON object in this exact format:
49
+ {
50
+ "primary": "intent_category",
51
+ "secondary": "intent_category or null",
52
+ "confidence": 0.85,
53
+ "reasoning": "Brief explanation of classification"
54
+ }
55
+
56
+ ## Important Notes
57
+
58
+ - Be conservative with confidence scores. Use 0.9+ only when intent is unmistakable.
59
+ - If message mentions multiple topics, choose the most actionable as primary.
60
+ - "complaint" takes precedence if there's explicit frustration, even with another intent.
61
+ - "other" is a last resort when no category fits reasonably.
62
+ `;
63
+ // =============================================================================
64
+ // Intent Classification Service
65
+ // =============================================================================
66
+ export class IntentClassificationService {
67
+ client = null;
68
+ getClient() {
69
+ if (!this.client) {
70
+ // Use API key if available
71
+ if (config.claude.apiKey) {
72
+ this.client = new Anthropic({
73
+ apiKey: config.claude.apiKey,
74
+ });
75
+ }
76
+ else {
77
+ throw new AnalysisError('Claude API key not configured', 'intent', {
78
+ context: { reason: 'Missing ANTHROPIC_API_KEY' },
79
+ });
80
+ }
81
+ }
82
+ return this.client;
83
+ }
84
+ /**
85
+ * Classify the intent of a message
86
+ */
87
+ async classify(message, conversationContext) {
88
+ const startTime = Date.now();
89
+ try {
90
+ const client = this.getClient();
91
+ // Build the message content
92
+ let content = message.content.text;
93
+ if (message.content.subject) {
94
+ content = `Subject: ${message.content.subject}\n\n${content}`;
95
+ }
96
+ // Add conversation context if available
97
+ let systemPrompt = INTENT_CLASSIFICATION_PROMPT;
98
+ if (conversationContext) {
99
+ systemPrompt += `\n\n## Previous Conversation Context\n${conversationContext}`;
100
+ }
101
+ const response = await client.messages.create({
102
+ model: config.claude.model,
103
+ max_tokens: 256,
104
+ system: systemPrompt,
105
+ messages: [
106
+ {
107
+ role: 'user',
108
+ content: `Classify the intent of this customer message:\n\n${content}`,
109
+ },
110
+ ],
111
+ });
112
+ // Extract the text response
113
+ const textContent = response.content.find((c) => c.type === 'text');
114
+ if (!textContent || textContent.type !== 'text') {
115
+ throw new AnalysisError('No text response from Claude', 'intent');
116
+ }
117
+ // Parse the JSON response
118
+ const result = this.parseClassificationResponse(textContent.text);
119
+ // Validate the classification
120
+ if (!this.isValidIntentCategory(result.primary)) {
121
+ throw new IntentClassificationError(`Invalid primary intent: ${result.primary}`, result.confidence, {
122
+ messageId: message.id,
123
+ });
124
+ }
125
+ return {
126
+ primary: result.primary,
127
+ secondary: result.secondary,
128
+ confidence: result.confidence,
129
+ reasoning: result.reasoning,
130
+ };
131
+ }
132
+ catch (error) {
133
+ if (error instanceof AnalysisError || error instanceof IntentClassificationError) {
134
+ throw error;
135
+ }
136
+ throw new AnalysisError(`Intent classification failed: ${error instanceof Error ? error.message : 'Unknown error'}`, 'intent', {
137
+ cause: error instanceof Error ? error : undefined,
138
+ messageId: message.id,
139
+ });
140
+ }
141
+ }
142
+ /**
143
+ * Parse the classification response from Claude
144
+ */
145
+ parseClassificationResponse(text) {
146
+ // Try to extract JSON from the response
147
+ const jsonMatch = text.match(/\{[\s\S]*\}/);
148
+ if (!jsonMatch) {
149
+ throw new AnalysisError('Could not parse intent classification JSON', 'intent', {
150
+ context: { response: text.substring(0, 200) },
151
+ });
152
+ }
153
+ try {
154
+ const parsed = JSON.parse(jsonMatch[0]);
155
+ return {
156
+ primary: parsed.primary ?? 'other',
157
+ secondary: parsed.secondary ?? null,
158
+ confidence: Math.min(1, Math.max(0, parsed.confidence ?? 0.5)),
159
+ reasoning: parsed.reasoning ?? '',
160
+ };
161
+ }
162
+ catch {
163
+ throw new AnalysisError('Invalid JSON in intent classification response', 'intent', {
164
+ context: { response: text.substring(0, 200) },
165
+ });
166
+ }
167
+ }
168
+ /**
169
+ * Validate that a string is a valid intent category
170
+ */
171
+ isValidIntentCategory(category) {
172
+ return Object.keys(INTENT_DESCRIPTIONS).includes(category);
173
+ }
174
+ /**
175
+ * Classify intent using heuristics (fallback when Claude is unavailable)
176
+ */
177
+ classifyWithHeuristics(message) {
178
+ const text = (message.content.text + ' ' + (message.content.subject ?? '')).toLowerCase();
179
+ // Define keyword patterns for each intent
180
+ const patterns = [
181
+ {
182
+ intent: 'order_status',
183
+ keywords: ['order', 'tracking', 'shipment', 'delivery', 'shipped', 'status', 'where is'],
184
+ weight: 1.0,
185
+ },
186
+ {
187
+ intent: 'pricing_inquiry',
188
+ keywords: ['price', 'pricing', 'cost', 'discount', 'moq', 'quote', 'how much'],
189
+ weight: 1.0,
190
+ },
191
+ {
192
+ intent: 'availability_check',
193
+ keywords: ['available', 'in stock', 'stock', 'inventory', 'restock', 'when will'],
194
+ weight: 1.0,
195
+ },
196
+ {
197
+ intent: 'documentation_request',
198
+ keywords: ['invoice', 'receipt', 'certificate', 'documentation', 'document', 'coa', 'coc'],
199
+ weight: 1.0,
200
+ },
201
+ {
202
+ intent: 'returns_damages',
203
+ keywords: ['return', 'refund', 'damaged', 'broken', 'exchange', 'wrong item', 'defective'],
204
+ weight: 1.2,
205
+ },
206
+ {
207
+ intent: 'account_inquiry',
208
+ keywords: ['account', 'login', 'password', 'sign in', 'access', 'profile'],
209
+ weight: 1.0,
210
+ },
211
+ {
212
+ intent: 'product_sourcing',
213
+ keywords: ['looking for', 'source', 'find', 'alternative', 'do you have', 'can you get'],
214
+ weight: 0.9,
215
+ },
216
+ {
217
+ intent: 'onboarding_help',
218
+ keywords: ['get started', 'new account', 'how do i', 'first order', 'setup', 'register'],
219
+ weight: 1.0,
220
+ },
221
+ {
222
+ intent: 'complaint',
223
+ keywords: [
224
+ 'disappointed',
225
+ 'frustrated',
226
+ 'unacceptable',
227
+ 'terrible',
228
+ 'worst',
229
+ 'complaint',
230
+ 'upset',
231
+ ],
232
+ weight: 1.5,
233
+ },
234
+ {
235
+ intent: 'feedback',
236
+ keywords: ['suggestion', 'feedback', 'love', 'great', 'awesome', 'recommend'],
237
+ weight: 0.8,
238
+ },
239
+ ];
240
+ // Score each intent
241
+ let bestMatch = {
242
+ intent: 'general_question',
243
+ score: 0,
244
+ };
245
+ let secondBest = null;
246
+ for (const pattern of patterns) {
247
+ let score = 0;
248
+ for (const keyword of pattern.keywords) {
249
+ if (text.includes(keyword)) {
250
+ score += pattern.weight;
251
+ }
252
+ }
253
+ if (score > bestMatch.score) {
254
+ secondBest = { ...bestMatch };
255
+ bestMatch = { intent: pattern.intent, score };
256
+ }
257
+ else if (!secondBest || score > secondBest.score) {
258
+ secondBest = { intent: pattern.intent, score };
259
+ }
260
+ }
261
+ // Calculate confidence based on match strength
262
+ const confidence = Math.min(0.75, bestMatch.score * 0.15);
263
+ return {
264
+ primary: bestMatch.intent,
265
+ secondary: secondBest && secondBest.score > 0.5 ? secondBest.intent : undefined,
266
+ confidence,
267
+ reasoning: 'Classified using keyword heuristics (Claude unavailable)',
268
+ };
269
+ }
270
+ }
271
+ // =============================================================================
272
+ // Singleton and Utility Functions
273
+ // =============================================================================
274
+ let intentService = null;
275
+ export function getIntentClassificationService() {
276
+ if (!intentService) {
277
+ intentService = new IntentClassificationService();
278
+ }
279
+ return intentService;
280
+ }
281
+ /**
282
+ * Classify message intent
283
+ */
284
+ export async function classifyIntent(message, conversationContext) {
285
+ return getIntentClassificationService().classify(message, conversationContext);
286
+ }
287
+ /**
288
+ * Classify intent using heuristics (fallback)
289
+ */
290
+ export function classifyIntentHeuristic(message) {
291
+ return getIntentClassificationService().classifyWithHeuristics(message);
292
+ }
293
+ /**
294
+ * Get intent description
295
+ */
296
+ export function getIntentDescription(intent) {
297
+ return INTENT_DESCRIPTIONS[intent];
298
+ }
299
+ /**
300
+ * Check if intent requires immediate attention
301
+ */
302
+ export function isHighPriorityIntent(intent) {
303
+ const highPriority = ['complaint', 'returns_damages'];
304
+ return highPriority.includes(intent);
305
+ }
306
+ /**
307
+ * Check if intent can likely be handled autonomously
308
+ */
309
+ export function isAutonomouslyHandleableIntent(intent) {
310
+ const autonomous = [
311
+ 'order_status',
312
+ 'pricing_inquiry',
313
+ 'availability_check',
314
+ 'documentation_request',
315
+ 'general_question',
316
+ 'onboarding_help',
317
+ ];
318
+ return autonomous.includes(intent);
319
+ }
320
+ //# sourceMappingURL=intent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent.js","sourceRoot":"","sources":["../../src/analysis/intent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Sentiment Analysis Service
3
+ *
4
+ * Analyzes message sentiment and urgency using Claude.
5
+ * Determines customer emotional state and time-sensitivity of request.
6
+ */
7
+ import type { SentimentAnalysis, UrgencyLevel, InboundMessage } from '../types.js';
8
+ export declare class SentimentAnalysisService {
9
+ private client;
10
+ private getClient;
11
+ /**
12
+ * Analyze sentiment and urgency of a message
13
+ */
14
+ analyze(message: InboundMessage): Promise<SentimentAnalysis>;
15
+ /**
16
+ * Parse the sentiment response from Claude
17
+ */
18
+ private parseSentimentResponse;
19
+ /**
20
+ * Validate sentiment category
21
+ */
22
+ private validateSentimentCategory;
23
+ /**
24
+ * Validate urgency level
25
+ */
26
+ private validateUrgencyLevel;
27
+ /**
28
+ * Normalize score to expected range
29
+ */
30
+ private normalizeScore;
31
+ /**
32
+ * Analyze sentiment using heuristics (fallback)
33
+ */
34
+ analyzeWithHeuristics(message: InboundMessage): SentimentAnalysis;
35
+ }
36
+ export declare function getSentimentAnalysisService(): SentimentAnalysisService;
37
+ /**
38
+ * Analyze message sentiment
39
+ */
40
+ export declare function analyzeSentiment(message: InboundMessage): Promise<SentimentAnalysis>;
41
+ /**
42
+ * Analyze sentiment using heuristics (fallback)
43
+ */
44
+ export declare function analyzeSentimentHeuristic(message: InboundMessage): SentimentAnalysis;
45
+ /**
46
+ * Check if sentiment indicates escalation should be considered
47
+ */
48
+ export declare function shouldConsiderEscalationBySentiment(sentiment: SentimentAnalysis): boolean;
49
+ /**
50
+ * Get urgency score (0-1) for ranking
51
+ */
52
+ export declare function getUrgencyScore(urgency: UrgencyLevel): number;
53
+ /**
54
+ * Combine urgency from multiple sources
55
+ */
56
+ export declare function combineUrgency(levels: UrgencyLevel[]): UrgencyLevel;
57
+ //# sourceMappingURL=sentiment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sentiment.d.ts","sourceRoot":"","sources":["../../src/analysis/sentiment.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAEV,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACf,MAAM,aAAa,CAAC;AA2ErB,qBAAa,wBAAwB;IACnC,OAAO,CAAC,MAAM,CAA0B;IAExC,OAAO,CAAC,SAAS;IAejB;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAwClE;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAkC9B;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAOjC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAY5B;;OAEG;IACH,OAAO,CAAC,cAAc;IAetB;;OAEG;IACH,qBAAqB,CAAC,OAAO,EAAE,cAAc,GAAG,iBAAiB;CA8FlE;AAQD,wBAAgB,2BAA2B,IAAI,wBAAwB,CAKtE;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAE1F;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,cAAc,GAAG,iBAAiB,CAEpF;AAED;;GAEG;AACH,wBAAgB,mCAAmC,CAAC,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAmBzF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAa7D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,YAAY,CAKnE"}