@udondan/duolingo 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.
@@ -0,0 +1,611 @@
1
+ /**
2
+ * Language-level Duolingo MCP tools.
3
+ *
4
+ * Tools: get_language_details, get_language_progress, get_known_topics,
5
+ * get_unknown_topics, get_golden_topics, get_reviewable_topics,
6
+ * get_known_words, get_learned_skills,
7
+ * get_language_voices, get_audio_url
8
+ */
9
+ import { z } from 'zod';
10
+ import { getClient } from '../client/duolingo.js';
11
+ import { handleError, ResponseFormatSchema, UsernameFieldSchema, computeDependencyOrder, } from './helpers.js';
12
+ const LanguageAbbrSchema = z
13
+ .string()
14
+ .min(2)
15
+ .max(5)
16
+ .describe("Language abbreviation (e.g. 'fr' for French, 'es' for Spanish).");
17
+ const OptionalLanguageAbbrSchema = z
18
+ .string()
19
+ .min(2)
20
+ .max(5)
21
+ .optional()
22
+ .describe("Language abbreviation (e.g. 'fr'). Defaults to current language.");
23
+ export function registerLanguageTools(server) {
24
+ // -------------------------------------------------------------------------
25
+ // Get Language Details
26
+ // -------------------------------------------------------------------------
27
+ server.registerTool('duolingo_get_language_details', {
28
+ title: 'Get Duolingo Language Details',
29
+ description: "Get a user's status and details for a specific language. " +
30
+ 'Returns level, points, streak, and learning status for the given language.',
31
+ inputSchema: {
32
+ language_name: z
33
+ .string()
34
+ .min(1)
35
+ .describe("Full name of the language (e.g. 'French', 'Spanish')."),
36
+ username: UsernameFieldSchema,
37
+ response_format: ResponseFormatSchema,
38
+ },
39
+ annotations: {
40
+ readOnlyHint: true,
41
+ destructiveHint: false,
42
+ idempotentHint: true,
43
+ openWorldHint: true,
44
+ },
45
+ }, async ({ language_name, username, response_format }) => {
46
+ try {
47
+ const userData = await getClient().getUserData(username);
48
+ const lang = userData.languages.find((l) => l.language_string === language_name);
49
+ if (!lang) {
50
+ return {
51
+ content: [
52
+ {
53
+ type: 'text',
54
+ text: `No details found for language '${language_name}'. Check the language name.`,
55
+ },
56
+ ],
57
+ };
58
+ }
59
+ const details = {
60
+ language: lang.language,
61
+ language_string: lang.language_string,
62
+ level: lang.level,
63
+ points: lang.points,
64
+ streak: lang.streak,
65
+ current_learning: lang.current_learning,
66
+ learning: lang.learning,
67
+ };
68
+ if (response_format === 'json') {
69
+ return {
70
+ content: [{ type: 'text', text: JSON.stringify(details, null, 2) }],
71
+ };
72
+ }
73
+ const lines = [`# ${language_name} Details`, ''];
74
+ lines.push(`- **Level**: ${details.level}`);
75
+ lines.push(`- **Points**: ${details.points}`);
76
+ lines.push(`- **Streak**: ${details.streak} days`);
77
+ lines.push(`- **Currently Learning**: ${details.current_learning}`);
78
+ return { content: [{ type: 'text', text: lines.join('\n') }] };
79
+ }
80
+ catch (err) {
81
+ return { content: [{ type: 'text', text: handleError(err) }] };
82
+ }
83
+ });
84
+ // -------------------------------------------------------------------------
85
+ // Get Language Progress
86
+ // -------------------------------------------------------------------------
87
+ server.registerTool('duolingo_get_language_progress', {
88
+ title: 'Get Duolingo Language Progress',
89
+ description: 'Get detailed progress metrics for a specific language. ' +
90
+ 'Returns level, percent to next level, points rank, fluency score, skills learned, and more.',
91
+ inputSchema: {
92
+ language_abbr: LanguageAbbrSchema,
93
+ response_format: ResponseFormatSchema,
94
+ },
95
+ annotations: {
96
+ readOnlyHint: true,
97
+ destructiveHint: false,
98
+ idempotentHint: true,
99
+ openWorldHint: true,
100
+ },
101
+ }, async ({ language_abbr, response_format }) => {
102
+ try {
103
+ const userData = await getClient().getUserData();
104
+ const langData = userData.language_data[language_abbr];
105
+ if (!langData) {
106
+ return {
107
+ content: [
108
+ {
109
+ type: 'text',
110
+ text: `Language '${language_abbr}' not found. Make sure you are learning this language.`,
111
+ },
112
+ ],
113
+ };
114
+ }
115
+ const progress = {
116
+ language: langData.language,
117
+ language_string: langData.language_string,
118
+ level: langData.level,
119
+ level_percent: langData.level_percent,
120
+ level_points: langData.level_points,
121
+ level_progress: langData.level_progress,
122
+ level_left: langData.level_left,
123
+ next_level: langData.next_level,
124
+ points: langData.points,
125
+ // points_rank is absent in the current API response
126
+ points_rank: langData.points_rank,
127
+ streak: langData.streak,
128
+ num_skills_learned: langData.num_skills_learned,
129
+ fluency_score: langData.fluency_score,
130
+ };
131
+ if (response_format === 'json') {
132
+ return {
133
+ content: [
134
+ { type: 'text', text: JSON.stringify(progress, null, 2) },
135
+ ],
136
+ };
137
+ }
138
+ const lang = progress.language_string || language_abbr;
139
+ const lines = [`# ${lang} Progress`, ''];
140
+ lines.push(`- **Level**: ${progress.level}`);
141
+ lines.push(`- **Level Progress**: ${progress.level_percent}%`);
142
+ lines.push(`- **Points to Next Level**: ${progress.level_left}`);
143
+ lines.push(`- **Total Points**: ${progress.points}`);
144
+ if (typeof progress.points_rank === 'number')
145
+ lines.push(`- **Points Rank**: #${progress.points_rank}`);
146
+ lines.push(`- **Streak**: ${progress.streak} days`);
147
+ lines.push(`- **Skills Learned**: ${progress.num_skills_learned}`);
148
+ if (progress.fluency_score !== null) {
149
+ lines.push(`- **Fluency Score**: ${progress.fluency_score}`);
150
+ }
151
+ return { content: [{ type: 'text', text: lines.join('\n') }] };
152
+ }
153
+ catch (err) {
154
+ return { content: [{ type: 'text', text: handleError(err) }] };
155
+ }
156
+ });
157
+ // -------------------------------------------------------------------------
158
+ // Shared topic/word tool schema
159
+ // -------------------------------------------------------------------------
160
+ const topicInputSchema = {
161
+ language_abbr: LanguageAbbrSchema,
162
+ username: UsernameFieldSchema,
163
+ response_format: ResponseFormatSchema,
164
+ };
165
+ function formatTopicList(title, topics, fmt) {
166
+ if (fmt === 'json')
167
+ return JSON.stringify([...topics].sort(), null, 2);
168
+ if (topics.length === 0)
169
+ return `No ${title.toLowerCase()} found.`;
170
+ const lines = [`# ${title}`, ''];
171
+ for (const topic of [...topics].sort()) {
172
+ lines.push(`- ${topic}`);
173
+ }
174
+ return lines.join('\n');
175
+ }
176
+ // -------------------------------------------------------------------------
177
+ // Get Known Topics
178
+ // -------------------------------------------------------------------------
179
+ server.registerTool('duolingo_get_known_topics', {
180
+ title: 'Get Duolingo Known Topics',
181
+ description: 'Get the list of learned topic/skill names for a language.',
182
+ inputSchema: topicInputSchema,
183
+ annotations: {
184
+ readOnlyHint: true,
185
+ destructiveHint: false,
186
+ idempotentHint: true,
187
+ openWorldHint: true,
188
+ },
189
+ }, async ({ language_abbr, username, response_format }) => {
190
+ try {
191
+ const userData = await getClient().getUserData(username);
192
+ const langData = userData.language_data[language_abbr];
193
+ if (!langData) {
194
+ return {
195
+ content: [
196
+ {
197
+ type: 'text',
198
+ text: `Language '${language_abbr}' not found. Make sure the user is learning this language.`,
199
+ },
200
+ ],
201
+ };
202
+ }
203
+ const topics = langData.skills
204
+ .filter((s) => s.learned)
205
+ .map((s) => s.title);
206
+ return {
207
+ content: [
208
+ {
209
+ type: 'text',
210
+ text: formatTopicList('Known Topics', topics, response_format),
211
+ },
212
+ ],
213
+ };
214
+ }
215
+ catch (err) {
216
+ return { content: [{ type: 'text', text: handleError(err) }] };
217
+ }
218
+ });
219
+ // -------------------------------------------------------------------------
220
+ // Get Unknown Topics
221
+ // -------------------------------------------------------------------------
222
+ server.registerTool('duolingo_get_unknown_topics', {
223
+ title: 'Get Duolingo Unknown Topics',
224
+ description: 'Get the list of not-yet-learned topics/skills for a language.',
225
+ inputSchema: topicInputSchema,
226
+ annotations: {
227
+ readOnlyHint: true,
228
+ destructiveHint: false,
229
+ idempotentHint: true,
230
+ openWorldHint: true,
231
+ },
232
+ }, async ({ language_abbr, username, response_format }) => {
233
+ try {
234
+ const userData = await getClient().getUserData(username);
235
+ const langData = userData.language_data[language_abbr];
236
+ if (!langData) {
237
+ return {
238
+ content: [
239
+ {
240
+ type: 'text',
241
+ text: `Language '${language_abbr}' not found. Make sure the user is learning this language.`,
242
+ },
243
+ ],
244
+ };
245
+ }
246
+ const topics = langData.skills
247
+ .filter((s) => !s.learned)
248
+ .map((s) => s.title);
249
+ return {
250
+ content: [
251
+ {
252
+ type: 'text',
253
+ text: formatTopicList('Unknown Topics', topics, response_format),
254
+ },
255
+ ],
256
+ };
257
+ }
258
+ catch (err) {
259
+ return { content: [{ type: 'text', text: handleError(err) }] };
260
+ }
261
+ });
262
+ // -------------------------------------------------------------------------
263
+ // Get Golden Topics
264
+ // -------------------------------------------------------------------------
265
+ server.registerTool('duolingo_get_golden_topics', {
266
+ title: 'Get Duolingo Golden (Mastered) Topics',
267
+ description: 'Get the list of fully mastered ("golden") topics for a language. ' +
268
+ 'A golden topic has a strength of 1.0 (fully reviewed).',
269
+ inputSchema: topicInputSchema,
270
+ annotations: {
271
+ readOnlyHint: true,
272
+ destructiveHint: false,
273
+ idempotentHint: true,
274
+ openWorldHint: true,
275
+ },
276
+ }, async ({ language_abbr, username, response_format }) => {
277
+ try {
278
+ const userData = await getClient().getUserData(username);
279
+ const langData = userData.language_data[language_abbr];
280
+ if (!langData) {
281
+ return {
282
+ content: [
283
+ {
284
+ type: 'text',
285
+ text: `Language '${language_abbr}' not found. Make sure the user is learning this language.`,
286
+ },
287
+ ],
288
+ };
289
+ }
290
+ const topics = langData.skills
291
+ .filter((s) => s.learned && s.strength === 1.0)
292
+ .map((s) => s.title);
293
+ return {
294
+ content: [
295
+ {
296
+ type: 'text',
297
+ text: formatTopicList('Golden (Mastered) Topics', topics, response_format),
298
+ },
299
+ ],
300
+ };
301
+ }
302
+ catch (err) {
303
+ return { content: [{ type: 'text', text: handleError(err) }] };
304
+ }
305
+ });
306
+ // -------------------------------------------------------------------------
307
+ // Get Reviewable Topics
308
+ // -------------------------------------------------------------------------
309
+ server.registerTool('duolingo_get_reviewable_topics', {
310
+ title: 'Get Duolingo Reviewable Topics',
311
+ description: 'Get the list of learned but not fully mastered topics for a language. ' +
312
+ 'These are topics that have been started but whose strength is below 1.0, meaning they need review.',
313
+ inputSchema: topicInputSchema,
314
+ annotations: {
315
+ readOnlyHint: true,
316
+ destructiveHint: false,
317
+ idempotentHint: true,
318
+ openWorldHint: true,
319
+ },
320
+ }, async ({ language_abbr, username, response_format }) => {
321
+ try {
322
+ const userData = await getClient().getUserData(username);
323
+ const langData = userData.language_data[language_abbr];
324
+ if (!langData) {
325
+ return {
326
+ content: [
327
+ {
328
+ type: 'text',
329
+ text: `Language '${language_abbr}' not found. Make sure the user is learning this language.`,
330
+ },
331
+ ],
332
+ };
333
+ }
334
+ const topics = langData.skills
335
+ .filter((s) => s.learned && s.strength < 1.0)
336
+ .map((s) => s.title);
337
+ return {
338
+ content: [
339
+ {
340
+ type: 'text',
341
+ text: formatTopicList('Reviewable Topics', topics, response_format),
342
+ },
343
+ ],
344
+ };
345
+ }
346
+ catch (err) {
347
+ return { content: [{ type: 'text', text: handleError(err) }] };
348
+ }
349
+ });
350
+ // -------------------------------------------------------------------------
351
+ // Get Known Words
352
+ // -------------------------------------------------------------------------
353
+ server.registerTool('duolingo_get_known_words', {
354
+ title: 'Get Duolingo Known Words',
355
+ description: 'Get the set of words a user has learned in a language.',
356
+ inputSchema: topicInputSchema,
357
+ annotations: {
358
+ readOnlyHint: true,
359
+ destructiveHint: false,
360
+ idempotentHint: true,
361
+ openWorldHint: true,
362
+ },
363
+ }, async ({ language_abbr, username, response_format }) => {
364
+ try {
365
+ const userData = await getClient().getUserData(username);
366
+ const langData = userData.language_data[language_abbr];
367
+ if (!langData) {
368
+ return {
369
+ content: [
370
+ {
371
+ type: 'text',
372
+ text: `Language '${language_abbr}' not found. Make sure the user is learning this language.`,
373
+ },
374
+ ],
375
+ };
376
+ }
377
+ const wordSet = new Set();
378
+ for (const skill of langData.skills) {
379
+ if (skill.learned) {
380
+ for (const word of skill.words) {
381
+ wordSet.add(word);
382
+ }
383
+ }
384
+ }
385
+ const words = [...wordSet].sort();
386
+ if (response_format === 'json') {
387
+ return {
388
+ content: [{ type: 'text', text: JSON.stringify(words, null, 2) }],
389
+ };
390
+ }
391
+ if (words.length === 0) {
392
+ return {
393
+ content: [
394
+ {
395
+ type: 'text',
396
+ text: `No known words found for language '${language_abbr}'.`,
397
+ },
398
+ ],
399
+ };
400
+ }
401
+ const lines = [
402
+ `# Known Words (${language_abbr.toUpperCase()}) — ${words.length} words`,
403
+ '',
404
+ words.join(', '),
405
+ ];
406
+ return { content: [{ type: 'text', text: lines.join('\n') }] };
407
+ }
408
+ catch (err) {
409
+ return { content: [{ type: 'text', text: handleError(err) }] };
410
+ }
411
+ });
412
+ // -------------------------------------------------------------------------
413
+ // Get Learned Skills
414
+ // -------------------------------------------------------------------------
415
+ server.registerTool('duolingo_get_learned_skills', {
416
+ title: 'Get Duolingo Learned Skills',
417
+ description: 'Get full skill objects for all learned skills, sorted by learning order. ' +
418
+ 'Returns detailed skill data including title, strength, progress, words, and more.',
419
+ inputSchema: topicInputSchema,
420
+ annotations: {
421
+ readOnlyHint: true,
422
+ destructiveHint: false,
423
+ idempotentHint: true,
424
+ openWorldHint: true,
425
+ },
426
+ }, async ({ language_abbr, username, response_format }) => {
427
+ try {
428
+ const userData = await getClient().getUserData(username);
429
+ const langData = userData.language_data[language_abbr];
430
+ if (!langData) {
431
+ return {
432
+ content: [
433
+ {
434
+ type: 'text',
435
+ text: `Language '${language_abbr}' not found. Make sure the user is learning this language.`,
436
+ },
437
+ ],
438
+ };
439
+ }
440
+ const allSkills = [...langData.skills];
441
+ computeDependencyOrder(allSkills);
442
+ const learnedSkills = allSkills
443
+ .filter((s) => s.learned)
444
+ .sort((a, b) => (a.dependency_order ?? 0) - (b.dependency_order ?? 0));
445
+ if (response_format === 'json') {
446
+ return {
447
+ content: [
448
+ { type: 'text', text: JSON.stringify(learnedSkills, null, 2) },
449
+ ],
450
+ };
451
+ }
452
+ if (learnedSkills.length === 0) {
453
+ return {
454
+ content: [
455
+ {
456
+ type: 'text',
457
+ text: `No learned skills found for language '${language_abbr}'.`,
458
+ },
459
+ ],
460
+ };
461
+ }
462
+ const lines = [`# Learned Skills (${language_abbr.toUpperCase()})`, ''];
463
+ for (const skill of learnedSkills) {
464
+ const strengthPct = Math.round(skill.strength * 100);
465
+ lines.push(`- **${skill.title}** — Strength: ${strengthPct}% | Progress: ${Math.round(skill.progress_percent)}%`);
466
+ }
467
+ return { content: [{ type: 'text', text: lines.join('\n') }] };
468
+ }
469
+ catch (err) {
470
+ return { content: [{ type: 'text', text: handleError(err) }] };
471
+ }
472
+ });
473
+ // -------------------------------------------------------------------------
474
+ // Get Language Voices
475
+ // -------------------------------------------------------------------------
476
+ server.registerTool('duolingo_get_language_voices', {
477
+ title: 'Get Duolingo Language TTS Voices',
478
+ description: 'Get the available text-to-speech (TTS) voices for a language. ' +
479
+ 'Returns a list of voice names.',
480
+ inputSchema: {
481
+ language_abbr: OptionalLanguageAbbrSchema,
482
+ response_format: ResponseFormatSchema,
483
+ },
484
+ annotations: {
485
+ readOnlyHint: true,
486
+ destructiveHint: false,
487
+ idempotentHint: true,
488
+ openWorldHint: true,
489
+ },
490
+ }, async ({ language_abbr, response_format }) => {
491
+ try {
492
+ const client = getClient();
493
+ // Resolve language abbreviation
494
+ let langAbbr = language_abbr;
495
+ if (!langAbbr) {
496
+ const userData = await client.getUserData();
497
+ const langKeys = Object.keys(userData.language_data);
498
+ langAbbr = langKeys[0];
499
+ }
500
+ if (!langAbbr) {
501
+ return {
502
+ content: [
503
+ {
504
+ type: 'text',
505
+ text: 'No language found. Make sure you are learning a language.',
506
+ },
507
+ ],
508
+ };
509
+ }
510
+ // Discover voices via the session API (duo.tts_multi_voices is no longer
511
+ // embedded in the homepage — voices are now discovered from session TTS URLs)
512
+ const voices = await client.getLanguageVoices(langAbbr);
513
+ if (voices.length === 0) {
514
+ return {
515
+ content: [
516
+ {
517
+ type: 'text',
518
+ text: `No voices found for language '${langAbbr}'.`,
519
+ },
520
+ ],
521
+ };
522
+ }
523
+ if (response_format === 'json') {
524
+ return {
525
+ content: [{ type: 'text', text: JSON.stringify(voices, null, 2) }],
526
+ };
527
+ }
528
+ const lines = [
529
+ `# TTS Voices (${langAbbr})`,
530
+ '',
531
+ ...voices.map((v) => `- ${v}`),
532
+ ];
533
+ return { content: [{ type: 'text', text: lines.join('\n') }] };
534
+ }
535
+ catch (err) {
536
+ return { content: [{ type: 'text', text: handleError(err) }] };
537
+ }
538
+ });
539
+ // -------------------------------------------------------------------------
540
+ // Get Audio URL
541
+ // -------------------------------------------------------------------------
542
+ server.registerTool('duolingo_get_audio_url', {
543
+ title: 'Get Duolingo Word Audio URL',
544
+ description: 'Get the URL of a pronunciation audio file for a word. ' +
545
+ 'Returns a CloudFront CDN URL pointing to the TTS audio file.',
546
+ inputSchema: {
547
+ word: z
548
+ .string()
549
+ .min(1)
550
+ .describe("The word to get pronunciation audio for (e.g. 'bonjour')."),
551
+ language_abbr: OptionalLanguageAbbrSchema,
552
+ voice: z
553
+ .string()
554
+ .optional()
555
+ .describe("Specific voice name to use (e.g. 'mathieu'). Defaults to random."),
556
+ random: z
557
+ .boolean()
558
+ .default(true)
559
+ .describe("If true, select a random voice. Ignored if 'voice' is specified."),
560
+ },
561
+ annotations: {
562
+ readOnlyHint: true,
563
+ destructiveHint: false,
564
+ idempotentHint: false,
565
+ openWorldHint: true,
566
+ },
567
+ }, async ({ word, language_abbr, voice, random }) => {
568
+ try {
569
+ const client = getClient();
570
+ // Resolve language abbreviation
571
+ let langAbbr = language_abbr;
572
+ if (!langAbbr) {
573
+ const userData = await client.getUserData();
574
+ const langKeys = Object.keys(userData.language_data);
575
+ langAbbr = langKeys[0];
576
+ }
577
+ if (!langAbbr) {
578
+ return {
579
+ content: [
580
+ {
581
+ type: 'text',
582
+ text: 'No language found. Make sure you are learning a language.',
583
+ },
584
+ ],
585
+ };
586
+ }
587
+ // If a specific voice is requested, build the URL directly.
588
+ // URL format: {ttsBaseUrl}tts/{lang}/{voice}/token/{word}
589
+ if (voice) {
590
+ const url = await client.buildAudioUrl(word, langAbbr, voice);
591
+ return { content: [{ type: 'text', text: url }] };
592
+ }
593
+ // If random voice is requested, discover available voices first.
594
+ if (random) {
595
+ const voices = await client.getLanguageVoices(langAbbr);
596
+ if (voices.length > 0) {
597
+ const selectedVoice = voices[Math.floor(Math.random() * voices.length)] ?? voices[0];
598
+ const url = await client.buildAudioUrl(word, langAbbr, selectedVoice);
599
+ return { content: [{ type: 'text', text: url }] };
600
+ }
601
+ }
602
+ // Fall back to the default (no-voice) URL
603
+ const url = await client.buildAudioUrl(word, langAbbr);
604
+ return { content: [{ type: 'text', text: url }] };
605
+ }
606
+ catch (err) {
607
+ return { content: [{ type: 'text', text: handleError(err) }] };
608
+ }
609
+ });
610
+ }
611
+ //# sourceMappingURL=language.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"language.js","sourceRoot":"","sources":["../../src/tools/language.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,cAAc,CAAC;AAEtB,MAAM,kBAAkB,GAAG,CAAC;KACzB,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,CAAC;KACN,GAAG,CAAC,CAAC,CAAC;KACN,QAAQ,CAAC,iEAAiE,CAAC,CAAC;AAE/E,MAAM,0BAA0B,GAAG,CAAC;KACjC,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,CAAC;KACN,GAAG,CAAC,CAAC,CAAC;KACN,QAAQ,EAAE;KACV,QAAQ,CAAC,kEAAkE,CAAC,CAAC;AAEhF,MAAM,UAAU,qBAAqB,CAAC,MAAiB;IACrD,4EAA4E;IAC5E,uBAAuB;IACvB,4EAA4E;IAC5E,MAAM,CAAC,YAAY,CACjB,+BAA+B,EAC/B;QACE,KAAK,EAAE,+BAA+B;QACtC,WAAW,EACT,2DAA2D;YAC3D,4EAA4E;QAC9E,WAAW,EAAE;YACX,aAAa,EAAE,CAAC;iBACb,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,CAAC,uDAAuD,CAAC;YACpE,QAAQ,EAAE,mBAAmB;YAC7B,eAAe,EAAE,oBAAoB;SACtC;QACD,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,IAAI;SACpB;KACF,EACD,KAAK,EAAE,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,EAAE;QACrD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,SAAS,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YACzD,MAAM,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC,IAAI,CAClC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,KAAK,aAAa,CAC3C,CAAC;YAEF,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,kCAAkC,aAAa,6BAA6B;yBACnF;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,MAAM,OAAO,GAAG;gBACd,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,eAAe,EAAE,IAAI,CAAC,eAAe;gBACrC,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;gBACvC,QAAQ,EAAE,IAAI,CAAC,QAAQ;aACxB,CAAC;YAEF,IAAI,eAAe,KAAK,MAAM,EAAE,CAAC;gBAC/B,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;iBACpE,CAAC;YACJ,CAAC;YAED,MAAM,KAAK,GAAG,CAAC,KAAK,aAAa,UAAU,EAAE,EAAE,CAAC,CAAC;YACjD,KAAK,CAAC,IAAI,CAAC,gBAAgB,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;YAC5C,KAAK,CAAC,IAAI,CAAC,iBAAiB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YAC9C,KAAK,CAAC,IAAI,CAAC,iBAAiB,OAAO,CAAC,MAAM,OAAO,CAAC,CAAC;YACnD,KAAK,CAAC,IAAI,CAAC,6BAA6B,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;YACpE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QACjE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QACjE,CAAC;IACH,CAAC,CACF,CAAC;IAEF,4EAA4E;IAC5E,wBAAwB;IACxB,4EAA4E;IAC5E,MAAM,CAAC,YAAY,CACjB,gCAAgC,EAChC;QACE,KAAK,EAAE,gCAAgC;QACvC,WAAW,EACT,yDAAyD;YACzD,6FAA6F;QAC/F,WAAW,EAAE;YACX,aAAa,EAAE,kBAAkB;YACjC,eAAe,EAAE,oBAAoB;SACtC;QACD,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,IAAI;SACpB;KACF,EACD,KAAK,EAAE,EAAE,aAAa,EAAE,eAAe,EAAE,EAAE,EAAE;QAC3C,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,SAAS,EAAE,CAAC,WAAW,EAAE,CAAC;YACjD,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;YACvD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,aAAa,aAAa,wDAAwD;yBACzF;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,MAAM,QAAQ,GAAG;gBACf,QAAQ,EAAE,QAAQ,CAAC,QAAQ;gBAC3B,eAAe,EAAE,QAAQ,CAAC,eAAe;gBACzC,KAAK,EAAE,QAAQ,CAAC,KAAK;gBACrB,aAAa,EAAE,QAAQ,CAAC,aAAa;gBACrC,YAAY,EAAE,QAAQ,CAAC,YAAY;gBACnC,cAAc,EAAE,QAAQ,CAAC,cAAc;gBACvC,UAAU,EAAE,QAAQ,CAAC,UAAU;gBAC/B,UAAU,EAAE,QAAQ,CAAC,UAAU;gBAC/B,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,oDAAoD;gBACpD,WAAW,EAAE,QAAQ,CAAC,WAAW;gBACjC,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,kBAAkB,EAAE,QAAQ,CAAC,kBAAkB;gBAC/C,aAAa,EAAE,QAAQ,CAAC,aAAa;aACtC,CAAC;YAEF,IAAI,eAAe,KAAK,MAAM,EAAE,CAAC;gBAC/B,OAAO;oBACL,OAAO,EAAE;wBACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;qBAC1D;iBACF,CAAC;YACJ,CAAC;YAED,MAAM,IAAI,GAAG,QAAQ,CAAC,eAAe,IAAI,aAAa,CAAC;YACvD,MAAM,KAAK,GAAG,CAAC,KAAK,IAAI,WAAW,EAAE,EAAE,CAAC,CAAC;YACzC,KAAK,CAAC,IAAI,CAAC,gBAAgB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;YAC7C,KAAK,CAAC,IAAI,CAAC,yBAAyB,QAAQ,CAAC,aAAa,GAAG,CAAC,CAAC;YAC/D,KAAK,CAAC,IAAI,CAAC,+BAA+B,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;YACjE,KAAK,CAAC,IAAI,CAAC,uBAAuB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YACrD,IAAI,OAAO,QAAQ,CAAC,WAAW,KAAK,QAAQ;gBAC1C,KAAK,CAAC,IAAI,CAAC,uBAAuB,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;YAC5D,KAAK,CAAC,IAAI,CAAC,iBAAiB,QAAQ,CAAC,MAAM,OAAO,CAAC,CAAC;YACpD,KAAK,CAAC,IAAI,CAAC,yBAAyB,QAAQ,CAAC,kBAAkB,EAAE,CAAC,CAAC;YACnE,IAAI,QAAQ,CAAC,aAAa,KAAK,IAAI,EAAE,CAAC;gBACpC,KAAK,CAAC,IAAI,CAAC,wBAAwB,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;YAC/D,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QACjE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QACjE,CAAC;IACH,CAAC,CACF,CAAC;IAEF,4EAA4E;IAC5E,gCAAgC;IAChC,4EAA4E;IAC5E,MAAM,gBAAgB,GAAG;QACvB,aAAa,EAAE,kBAAkB;QACjC,QAAQ,EAAE,mBAAmB;QAC7B,eAAe,EAAE,oBAAoB;KACtC,CAAC;IAEF,SAAS,eAAe,CACtB,KAAa,EACb,MAAgB,EAChB,GAAW;QAEX,IAAI,GAAG,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACvE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,MAAM,KAAK,CAAC,WAAW,EAAE,SAAS,CAAC;QACnE,MAAM,KAAK,GAAG,CAAC,KAAK,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QACjC,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;QAC3B,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,4EAA4E;IAC5E,mBAAmB;IACnB,4EAA4E;IAC5E,MAAM,CAAC,YAAY,CACjB,2BAA2B,EAC3B;QACE,KAAK,EAAE,2BAA2B;QAClC,WAAW,EAAE,2DAA2D;QACxE,WAAW,EAAE,gBAAgB;QAC7B,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,IAAI;SACpB;KACF,EACD,KAAK,EAAE,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,EAAE;QACrD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,SAAS,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YACzD,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;YACvD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,aAAa,aAAa,4DAA4D;yBAC7F;qBACF;iBACF,CAAC;YACJ,CAAC;YACD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM;iBAC3B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;iBACxB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACvB,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,eAAe,CAAC,cAAc,EAAE,MAAM,EAAE,eAAe,CAAC;qBAC/D;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QACjE,CAAC;IACH,CAAC,CACF,CAAC;IAEF,4EAA4E;IAC5E,qBAAqB;IACrB,4EAA4E;IAC5E,MAAM,CAAC,YAAY,CACjB,6BAA6B,EAC7B;QACE,KAAK,EAAE,6BAA6B;QACpC,WAAW,EACT,+DAA+D;QACjE,WAAW,EAAE,gBAAgB;QAC7B,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,IAAI;SACpB;KACF,EACD,KAAK,EAAE,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,EAAE;QACrD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,SAAS,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YACzD,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;YACvD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,aAAa,aAAa,4DAA4D;yBAC7F;qBACF;iBACF,CAAC;YACJ,CAAC;YACD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM;iBAC3B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;iBACzB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACvB,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,eAAe,CAAC,gBAAgB,EAAE,MAAM,EAAE,eAAe,CAAC;qBACjE;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QACjE,CAAC;IACH,CAAC,CACF,CAAC;IAEF,4EAA4E;IAC5E,oBAAoB;IACpB,4EAA4E;IAC5E,MAAM,CAAC,YAAY,CACjB,4BAA4B,EAC5B;QACE,KAAK,EAAE,uCAAuC;QAC9C,WAAW,EACT,mEAAmE;YACnE,wDAAwD;QAC1D,WAAW,EAAE,gBAAgB;QAC7B,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,IAAI;SACpB;KACF,EACD,KAAK,EAAE,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,EAAE;QACrD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,SAAS,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YACzD,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;YACvD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,aAAa,aAAa,4DAA4D;yBAC7F;qBACF;iBACF,CAAC;YACJ,CAAC;YACD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM;iBAC3B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,QAAQ,KAAK,GAAG,CAAC;iBAC9C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACvB,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,eAAe,CACnB,0BAA0B,EAC1B,MAAM,EACN,eAAe,CAChB;qBACF;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QACjE,CAAC;IACH,CAAC,CACF,CAAC;IAEF,4EAA4E;IAC5E,wBAAwB;IACxB,4EAA4E;IAC5E,MAAM,CAAC,YAAY,CACjB,gCAAgC,EAChC;QACE,KAAK,EAAE,gCAAgC;QACvC,WAAW,EACT,wEAAwE;YACxE,oGAAoG;QACtG,WAAW,EAAE,gBAAgB;QAC7B,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,IAAI;SACpB;KACF,EACD,KAAK,EAAE,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,EAAE;QACrD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,SAAS,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YACzD,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;YACvD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,aAAa,aAAa,4DAA4D;yBAC7F;qBACF;iBACF,CAAC;YACJ,CAAC;YACD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM;iBAC3B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,QAAQ,GAAG,GAAG,CAAC;iBAC5C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACvB,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,eAAe,CACnB,mBAAmB,EACnB,MAAM,EACN,eAAe,CAChB;qBACF;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QACjE,CAAC;IACH,CAAC,CACF,CAAC;IAEF,4EAA4E;IAC5E,kBAAkB;IAClB,4EAA4E;IAC5E,MAAM,CAAC,YAAY,CACjB,0BAA0B,EAC1B;QACE,KAAK,EAAE,0BAA0B;QACjC,WAAW,EAAE,wDAAwD;QACrE,WAAW,EAAE,gBAAgB;QAC7B,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,IAAI;SACpB;KACF,EACD,KAAK,EAAE,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,EAAE;QACrD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,SAAS,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YACzD,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;YACvD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,aAAa,aAAa,4DAA4D;yBAC7F;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;YAClC,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;gBACpC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;oBAClB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;wBAC/B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;oBACpB,CAAC;gBACH,CAAC;YACH,CAAC;YAED,MAAM,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;YAElC,IAAI,eAAe,KAAK,MAAM,EAAE,CAAC;gBAC/B,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;iBAClE,CAAC;YACJ,CAAC;YAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,sCAAsC,aAAa,IAAI;yBAC9D;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,MAAM,KAAK,GAAG;gBACZ,kBAAkB,aAAa,CAAC,WAAW,EAAE,OAAO,KAAK,CAAC,MAAM,QAAQ;gBACxE,EAAE;gBACF,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;aACjB,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QACjE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QACjE,CAAC;IACH,CAAC,CACF,CAAC;IAEF,4EAA4E;IAC5E,qBAAqB;IACrB,4EAA4E;IAC5E,MAAM,CAAC,YAAY,CACjB,6BAA6B,EAC7B;QACE,KAAK,EAAE,6BAA6B;QACpC,WAAW,EACT,2EAA2E;YAC3E,mFAAmF;QACrF,WAAW,EAAE,gBAAgB;QAC7B,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,IAAI;SACpB;KACF,EACD,KAAK,EAAE,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,EAAE;QACrD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,SAAS,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YACzD,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;YACvD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,aAAa,aAAa,4DAA4D;yBAC7F;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,MAAM,SAAS,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;YACvC,sBAAsB,CAAC,SAAS,CAAC,CAAC;YAElC,MAAM,aAAa,GAAG,SAAS;iBAC5B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;iBACxB,IAAI,CACH,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,gBAAgB,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,gBAAgB,IAAI,CAAC,CAAC,CAChE,CAAC;YAEJ,IAAI,eAAe,KAAK,MAAM,EAAE,CAAC;gBAC/B,OAAO;oBACL,OAAO,EAAE;wBACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;qBAC/D;iBACF,CAAC;YACJ,CAAC;YAED,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC/B,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,yCAAyC,aAAa,IAAI;yBACjE;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,MAAM,KAAK,GAAG,CAAC,qBAAqB,aAAa,CAAC,WAAW,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;YACxE,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;gBAClC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC;gBACrD,KAAK,CAAC,IAAI,CACR,OAAO,KAAK,CAAC,KAAK,kBAAkB,WAAW,iBAAiB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,GAAG,CACtG,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QACjE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QACjE,CAAC;IACH,CAAC,CACF,CAAC;IAEF,4EAA4E;IAC5E,sBAAsB;IACtB,4EAA4E;IAC5E,MAAM,CAAC,YAAY,CACjB,8BAA8B,EAC9B;QACE,KAAK,EAAE,kCAAkC;QACzC,WAAW,EACT,gEAAgE;YAChE,gCAAgC;QAClC,WAAW,EAAE;YACX,aAAa,EAAE,0BAA0B;YACzC,eAAe,EAAE,oBAAoB;SACtC;QACD,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,IAAI;SACpB;KACF,EACD,KAAK,EAAE,EAAE,aAAa,EAAE,eAAe,EAAE,EAAE,EAAE;QAC3C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;YAE3B,gCAAgC;YAChC,IAAI,QAAQ,GAAG,aAAa,CAAC;YAC7B,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;gBAC5C,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;gBACrD,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YACzB,CAAC;YAED,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,2DAA2D;yBAClE;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,yEAAyE;YACzE,8EAA8E;YAC9E,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YAExD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,iCAAiC,QAAQ,IAAI;yBACpD;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,IAAI,eAAe,KAAK,MAAM,EAAE,CAAC;gBAC/B,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;iBACnE,CAAC;YACJ,CAAC;YAED,MAAM,KAAK,GAAG;gBACZ,iBAAiB,QAAQ,GAAG;gBAC5B,EAAE;gBACF,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;aAC/B,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QACjE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QACjE,CAAC;IACH,CAAC,CACF,CAAC;IAEF,4EAA4E;IAC5E,gBAAgB;IAChB,4EAA4E;IAC5E,MAAM,CAAC,YAAY,CACjB,wBAAwB,EACxB;QACE,KAAK,EAAE,6BAA6B;QACpC,WAAW,EACT,wDAAwD;YACxD,8DAA8D;QAChE,WAAW,EAAE;YACX,IAAI,EAAE,CAAC;iBACJ,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,CACP,2DAA2D,CAC5D;YACH,aAAa,EAAE,0BAA0B;YACzC,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CACP,kEAAkE,CACnE;YACH,MAAM,EAAE,CAAC;iBACN,OAAO,EAAE;iBACT,OAAO,CAAC,IAAI,CAAC;iBACb,QAAQ,CACP,kEAAkE,CACnE;SACJ;QACD,WAAW,EAAE;YACX,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,KAAK;YACrB,aAAa,EAAE,IAAI;SACpB;KACF,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE;QAC/C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;YAE3B,gCAAgC;YAChC,IAAI,QAAQ,GAAG,aAAa,CAAC;YAC7B,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;gBAC5C,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;gBACrD,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YACzB,CAAC;YAED,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,2DAA2D;yBAClE;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,4DAA4D;YAC5D,0DAA0D;YAC1D,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;gBAC9D,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;YACpD,CAAC;YAED,iEAAiE;YACjE,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;gBACxD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACtB,MAAM,aAAa,GACjB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;oBACjE,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,aAAa,CACpC,IAAI,EACJ,QAAQ,EACR,aAAa,CACd,CAAC;oBACF,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;gBACpD,CAAC;YACH,CAAC;YAED,0CAA0C;YAC1C,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACvD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;QACpD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QACjE,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Utility Duolingo MCP tools.
3
+ *
4
+ * Tools: get_language_from_abbr, get_abbreviation_of
5
+ */
6
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
+ export declare function registerShopTools(server: McpServer): void;
8
+ //# sourceMappingURL=shop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shop.d.ts","sourceRoot":"","sources":["../../src/tools/shop.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8IzD"}