@adeu/mcp-server 1.8.0 → 1.9.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,745 @@
1
+ <!-- FILE: src/adeu/templates/markdown_ui.html -->
2
+ <!DOCTYPE html>
3
+ <html>
4
+
5
+ <head>
6
+ <meta charset="utf-8">
7
+ <title>Adeu Markdown UI</title>
8
+ <meta name="color-scheme" content="light dark">
9
+ <link rel="preconnect" href="https://fonts.googleapis.com">
10
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
+ <link
12
+ href="https://fonts.googleapis.com/css2?family=Jost:wght@400;500;600&family=Lora:ital,wght@0,600;1,600&display=swap"
13
+ rel="stylesheet">
14
+ <style>
15
+ :root {
16
+ --brand-sand: #e8c0a1;
17
+ --brand-sand-light: #f2d9c7;
18
+ --brand-sand-dark: #d4a882;
19
+ --brand-mint: #e6f3f0;
20
+ --brand-mint-dark: #c9e4de;
21
+ --brand-navy: #1a2a2c;
22
+ --brand-navy-light: #2a3a3c;
23
+ --brand-mauve: #dacad2;
24
+ --neutral-50: #fafafa;
25
+ --neutral-100: #f5f5f5;
26
+ --neutral-200: #e5e5e5;
27
+ --neutral-300: #d9d9d9;
28
+ --neutral-600: #555969;
29
+ --neutral-800: #1e2028;
30
+ --neutral-900: #171717;
31
+ --font-lora: 'Lora', Georgia, serif;
32
+ --font-jost: 'Jost', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
33
+ --bg-body: var(--neutral-50);
34
+ --bg-card: #ffffff;
35
+ --border-card: var(--neutral-200);
36
+ --text-main: var(--neutral-600);
37
+ --text-heading: var(--brand-navy);
38
+ --bg-blockquote: rgba(232, 192, 161, 0.15);
39
+ }
40
+
41
+ @media (prefers-color-scheme: dark) {
42
+ :root {
43
+ --bg-body: var(--neutral-900);
44
+ --bg-card: var(--brand-navy);
45
+ --border-card: var(--brand-navy-light);
46
+ --text-main: rgba(255, 255, 255, 0.85);
47
+ --text-heading: #ffffff;
48
+ --bg-blockquote: rgba(232, 192, 161, 0.1);
49
+ --neutral-100: var(--brand-navy-light);
50
+ }
51
+ }
52
+
53
+ html,
54
+ body {
55
+ margin: 0;
56
+ padding: 0;
57
+ box-sizing: border-box;
58
+ background-color: transparent;
59
+ }
60
+
61
+ body {
62
+ font-family: var(--font-jost);
63
+ color: var(--text-main);
64
+ line-height: 1.6;
65
+ -webkit-font-smoothing: antialiased;
66
+ padding: 16px;
67
+ }
68
+
69
+ .adeu-card {
70
+ background-color: var(--bg-card);
71
+ border: 1px solid var(--border-card);
72
+ border-radius: 12px;
73
+ overflow: hidden;
74
+ display: flex;
75
+ flex-direction: column;
76
+ }
77
+
78
+ .navbar {
79
+ flex-shrink: 0;
80
+ background-color: var(--bg-card);
81
+ padding: 16px 32px;
82
+ border-bottom: 1px solid var(--border-card);
83
+ display: flex;
84
+ align-items: center;
85
+ justify-content: space-between;
86
+ position: relative;
87
+ }
88
+
89
+ .logo-container {
90
+ display: flex;
91
+ align-items: center;
92
+ flex: 1;
93
+ }
94
+
95
+ .nav-title {
96
+ position: absolute;
97
+ left: 50%;
98
+ transform: translateX(-50%);
99
+ font-family: var(--font-lora);
100
+ font-weight: 600;
101
+ color: var(--text-heading);
102
+ font-size: 1.1rem;
103
+ white-space: nowrap;
104
+ overflow: hidden;
105
+ text-overflow: ellipsis;
106
+ max-width: 40%;
107
+ text-align: center;
108
+ }
109
+
110
+ .nav-actions {
111
+ display: flex;
112
+ align-items: center;
113
+ justify-content: flex-end;
114
+ flex: 1;
115
+ }
116
+
117
+ #copy-btn {
118
+ display: none;
119
+ align-items: center;
120
+ gap: 6px;
121
+ background: transparent;
122
+ border: none;
123
+ color: var(--text-main);
124
+ font-family: var(--font-jost);
125
+ font-size: 0.85rem;
126
+ font-weight: 500;
127
+ cursor: pointer;
128
+ padding: 8px;
129
+ border-radius: 6px;
130
+ transition: all 0.2s ease;
131
+ }
132
+
133
+ #copy-btn:hover {
134
+ color: var(--text-heading);
135
+ background: var(--neutral-100);
136
+ }
137
+
138
+ #open-btn {
139
+ display: none;
140
+ align-items: center;
141
+ gap: 6px;
142
+ background: transparent;
143
+ border: none;
144
+ color: var(--text-main);
145
+ font-family: var(--font-jost);
146
+ font-size: 0.85rem;
147
+ font-weight: 500;
148
+ cursor: pointer;
149
+ padding: 8px;
150
+ border-radius: 6px;
151
+ transition: all 0.2s ease;
152
+ }
153
+
154
+ #open-btn:hover {
155
+ color: var(--text-heading);
156
+ background: var(--neutral-100);
157
+ }
158
+
159
+ @media (prefers-color-scheme: dark) {
160
+ #copy-btn:hover {
161
+ background: var(--brand-navy-light);
162
+ }
163
+ #open-btn:hover {
164
+ background: var(--brand-navy-light);
165
+ }
166
+ }
167
+
168
+ .logo-container svg {
169
+ max-width: 80px;
170
+ height: auto;
171
+ }
172
+
173
+ .logo-container svg path,
174
+ .logo-container svg rect,
175
+ .logo-container svg polygon,
176
+ .logo-container svg circle {
177
+ transition: fill 0.2s ease;
178
+ }
179
+
180
+ @media (prefers-color-scheme: dark) {
181
+
182
+ .logo-container svg path,
183
+ .logo-container svg rect,
184
+ .logo-container svg polygon,
185
+ .logo-container svg circle,
186
+ .logo-container svg {
187
+ fill: #ffffff !important;
188
+ }
189
+ }
190
+
191
+ .content-wrapper {
192
+ position: relative;
193
+ }
194
+
195
+ .content-wrapper::-webkit-scrollbar {
196
+ width: 6px;
197
+ }
198
+
199
+ .content-wrapper::-webkit-scrollbar-track {
200
+ background: transparent;
201
+ }
202
+
203
+ .content-wrapper::-webkit-scrollbar-thumb {
204
+ background-color: var(--border-card);
205
+ border-radius: 4px;
206
+ }
207
+
208
+ #app {
209
+ padding: 32px;
210
+ display: flow-root;
211
+ }
212
+
213
+ .fade-overlay {
214
+ position: absolute;
215
+ bottom: 0;
216
+ left: 0;
217
+ right: 0;
218
+ height: 80px;
219
+ background: linear-gradient(to bottom, rgba(255, 255, 255, 0), var(--bg-card));
220
+ pointer-events: none;
221
+ display: none;
222
+ }
223
+
224
+ @media (prefers-color-scheme: dark) {
225
+ .fade-overlay {
226
+ background: linear-gradient(to bottom, rgba(26, 42, 44, 0), var(--bg-card));
227
+ }
228
+ }
229
+
230
+ .toggle-container {
231
+ flex-shrink: 0;
232
+ display: none;
233
+ justify-content: center;
234
+ align-items: center;
235
+ padding: 12px;
236
+ border-top: 1px solid var(--border-card);
237
+ background-color: var(--bg-card);
238
+ }
239
+
240
+ #toggle-btn {
241
+ background: transparent;
242
+ border: none;
243
+ color: var(--brand-sand-dark);
244
+ font-family: var(--font-jost);
245
+ font-weight: 600;
246
+ font-size: 0.95rem;
247
+ cursor: pointer;
248
+ display: flex;
249
+ align-items: center;
250
+ gap: 6px;
251
+ padding: 8px 16px;
252
+ border-radius: 6px;
253
+ transition: all 0.2s ease;
254
+ }
255
+
256
+ #toggle-btn:hover {
257
+ color: var(--text-heading);
258
+ background: var(--neutral-100);
259
+ }
260
+
261
+ @media (prefers-color-scheme: dark) {
262
+ #toggle-btn:hover {
263
+ background: var(--brand-navy-light);
264
+ }
265
+ }
266
+
267
+ #toggle-icon {
268
+ transition: transform 0.3s ease;
269
+ }
270
+
271
+ h1,
272
+ h2,
273
+ h3,
274
+ h4 {
275
+ font-family: var(--font-lora);
276
+ color: var(--text-heading);
277
+ font-weight: 600;
278
+ letter-spacing: -0.02em;
279
+ margin-top: 1.5em;
280
+ margin-bottom: 0.5em;
281
+ }
282
+
283
+ h1 {
284
+ font-size: 2.25rem;
285
+ border-bottom: 1px solid var(--border-card);
286
+ padding-bottom: 0.3em;
287
+ margin-top: 0;
288
+ }
289
+
290
+ h2 {
291
+ font-size: 1.75rem;
292
+ }
293
+
294
+ h3 {
295
+ font-size: 1.25rem;
296
+ }
297
+
298
+ a {
299
+ color: var(--brand-sand-dark);
300
+ text-decoration: none;
301
+ border-bottom: 1px solid transparent;
302
+ transition: border 0.2s ease;
303
+ }
304
+
305
+ a:hover {
306
+ border-bottom-color: var(--brand-sand-dark);
307
+ }
308
+
309
+ strong {
310
+ font-weight: 600;
311
+ color: var(--text-heading);
312
+ }
313
+
314
+ ul,
315
+ ol {
316
+ padding-left: 1.5rem;
317
+ margin-bottom: 1rem;
318
+ }
319
+
320
+ li {
321
+ margin-bottom: 0.5rem;
322
+ }
323
+
324
+ blockquote {
325
+ border-left: 4px solid var(--brand-sand);
326
+ padding: 12px 20px;
327
+ margin: 24px 0;
328
+ color: var(--text-main);
329
+ background: var(--bg-blockquote);
330
+ border-radius: 0 8px 8px 0;
331
+ font-style: italic;
332
+ }
333
+
334
+ code {
335
+ font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace;
336
+ font-size: 0.85em;
337
+ background: var(--neutral-100);
338
+ color: var(--brand-sand-dark);
339
+ padding: 0.2em 0.4em;
340
+ border-radius: 4px;
341
+ }
342
+
343
+ pre code {
344
+ display: block;
345
+ padding: 16px;
346
+ background: var(--neutral-900);
347
+ color: #e5e5e5;
348
+ border-radius: 8px;
349
+ overflow-x: auto;
350
+ }
351
+
352
+ .skeleton {
353
+ background: linear-gradient(90deg, var(--neutral-100) 25%, var(--border-card) 50%, var(--neutral-100) 75%);
354
+ background-size: 200% 100%;
355
+ animation: skeleton 1.5s ease-in-out infinite;
356
+ border-radius: 4px;
357
+ }
358
+
359
+ @keyframes skeleton {
360
+ 0% {
361
+ background-position: 200% 0;
362
+ }
363
+
364
+ 100% {
365
+ background-position: -200% 0;
366
+ }
367
+ }
368
+
369
+ .alert {
370
+ padding: 16px;
371
+ border-radius: 8px;
372
+ margin-bottom: 20px;
373
+ display: flex;
374
+ flex-direction: column;
375
+ gap: 8px;
376
+ background-color: #fef2f2;
377
+ border: 1px solid #fecaca;
378
+ color: #991b1b;
379
+ }
380
+
381
+ @media (prefers-color-scheme: dark) {
382
+ .alert {
383
+ background-color: rgba(127, 29, 29, 0.2);
384
+ border-color: rgba(248, 113, 113, 0.3);
385
+ color: #fca5a5;
386
+ }
387
+ }
388
+
389
+ .alert-title {
390
+ font-weight: 600;
391
+ font-size: 1.1em;
392
+ margin: 0;
393
+ display: flex;
394
+ align-items: center;
395
+ gap: 8px;
396
+ font-family: var(--font-lora);
397
+ }
398
+
399
+ .alert-body {
400
+ margin: 0;
401
+ font-size: 0.95em;
402
+ }
403
+
404
+ .alert-details {
405
+ background: rgba(0, 0, 0, 0.05);
406
+ padding: 12px;
407
+ border-radius: 6px;
408
+ font-family: ui-monospace, Consolas, monospace;
409
+ font-size: 0.85em;
410
+ white-space: pre-wrap;
411
+ word-break: break-all;
412
+ margin-top: 8px;
413
+ border: 1px solid rgba(0, 0, 0, 0.1);
414
+ }
415
+ </style>
416
+ <script id="marked-script">[[marked_js_code | safe]]</script>
417
+ </head>
418
+
419
+ <body>
420
+ <div class="adeu-card">
421
+ <nav class="navbar">
422
+ <div class="logo-container">
423
+ [[ adeu_svg_code ]]
424
+ </div>
425
+
426
+ <div class="nav-title" id="nav-title"></div>
427
+
428
+ <div class="nav-actions">
429
+ <button id="copy-btn" title="Copy Markdown">
430
+ <svg id="copy-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor"
431
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
432
+ <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
433
+ <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
434
+ </svg>
435
+ <span id="copy-text" style="display: none;"></span>
436
+ </button>
437
+ <button id="open-btn" title="Open in Native App">
438
+ <svg id="open-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor"
439
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
440
+ <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
441
+ <polyline points="15 3 21 3 21 9"></polyline>
442
+ <line x1="10" y1="14" x2="21" y2="3"></line>
443
+ </svg>
444
+ <span id="open-text" style="display: none;"></span>
445
+ </button>
446
+ </div>
447
+ </nav>
448
+
449
+ <div class="content-wrapper" id="content-wrapper">
450
+ <div id="app">
451
+ <div class="skeleton" style="height: 36px; width: 40%; margin-bottom: 24px;"></div>
452
+ <div class="skeleton" style="height: 16px; width: 100%; margin-bottom: 12px;"></div>
453
+ <div class="skeleton" style="height: 16px; width: 95%; margin-bottom: 12px;"></div>
454
+ <div class="skeleton" style="height: 16px; width: 90%; margin-bottom: 24px;"></div>
455
+ <div class="skeleton" style="height: 16px; width: 80%; margin-bottom: 12px;"></div>
456
+ </div>
457
+ <div class="fade-overlay" id="fade-overlay"></div>
458
+ </div>
459
+
460
+ <div class="toggle-container" id="toggle-container">
461
+ <button id="toggle-btn">
462
+ <span id="toggle-text">Show More</span>
463
+ <svg id="toggle-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor"
464
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="transform: rotate(0deg);">
465
+ <polyline points="6 9 12 15 18 9"></polyline>
466
+ </svg>
467
+ </button>
468
+ </div>
469
+ </div>
470
+
471
+ <script>
472
+ const appDiv = document.getElementById('app');
473
+ const INIT_ID = 1;
474
+ let isExpanded = false; // START COLLAPSED BY DEFAULT!
475
+
476
+ let rawMarkdownText = "";
477
+ let currentFilePath = null;
478
+ const navTitle = document.getElementById('nav-title');
479
+ const copyBtn = document.getElementById('copy-btn');
480
+ const copyIcon = document.getElementById('copy-icon');
481
+ const copyText = document.getElementById('copy-text');
482
+ const openBtn = document.getElementById('open-btn');
483
+ const openText = document.getElementById('open-text');
484
+
485
+ function fallbackCopyTextToClipboard(text) {
486
+ return new Promise((resolve, reject) => {
487
+ const textArea = document.createElement("textarea");
488
+ textArea.value = text;
489
+ textArea.style.top = "0";
490
+ textArea.style.left = "0";
491
+ textArea.style.position = "fixed";
492
+ textArea.style.opacity = "0";
493
+
494
+ document.body.appendChild(textArea);
495
+ textArea.focus();
496
+ textArea.select();
497
+
498
+ try {
499
+ const successful = document.execCommand('copy');
500
+ if (successful) {
501
+ resolve();
502
+ } else {
503
+ reject(new Error("execCommand returned false"));
504
+ }
505
+ } catch (err) {
506
+ reject(err);
507
+ } finally {
508
+ document.body.removeChild(textArea);
509
+ }
510
+ });
511
+ }
512
+
513
+ copyBtn.addEventListener('click', async () => {
514
+ try {
515
+ if (navigator.clipboard && window.isSecureContext) {
516
+ try {
517
+ await navigator.clipboard.writeText(rawMarkdownText);
518
+ } catch (e) {
519
+ await fallbackCopyTextToClipboard(rawMarkdownText);
520
+ }
521
+ } else {
522
+ await fallbackCopyTextToClipboard(rawMarkdownText);
523
+ }
524
+
525
+ const originalSvg = copyIcon.innerHTML;
526
+ copyIcon.innerHTML = `<polyline points="20 6 9 17 4 12"></polyline>`;
527
+
528
+ copyText.textContent = "Copied!";
529
+ copyText.style.display = "inline";
530
+ copyBtn.style.color = "#10b981";
531
+
532
+ setTimeout(() => {
533
+ copyIcon.innerHTML = originalSvg;
534
+ copyText.textContent = "";
535
+ copyText.style.display = "none";
536
+ copyBtn.style.color = "";
537
+ }, 2000);
538
+ } catch (err) {
539
+ console.error('Failed to copy text: ', err);
540
+ copyText.textContent = "Failed";
541
+ copyText.style.display = "inline";
542
+ copyBtn.title = err.toString();
543
+
544
+ setTimeout(() => {
545
+ copyText.textContent = "";
546
+ copyText.style.display = "none";
547
+ copyBtn.title = "Copy Markdown";
548
+ }, 3000);
549
+ }
550
+ });
551
+
552
+ openBtn.addEventListener('click', () => {
553
+ if (!currentFilePath) return;
554
+
555
+ const reqId = Date.now();
556
+
557
+ window.parent.postMessage({
558
+ jsonrpc: "2.0",
559
+ id: reqId,
560
+ method: "tools/call",
561
+ params: {
562
+ name: "open_local_file",
563
+ arguments: {
564
+ file_path: currentFilePath
565
+ }
566
+ }
567
+ }, "*");
568
+
569
+ openText.textContent = "Opening...";
570
+ openText.style.display = "inline";
571
+
572
+ setTimeout(() => {
573
+ openText.style.display = "none";
574
+ openText.textContent = "";
575
+ }, 2000);
576
+ });
577
+
578
+ function escapeHtml(unsafe) {
579
+ return (unsafe || "").toString()
580
+ .replace(/&/g, "&amp;")
581
+ .replace(/</g, "&lt;")
582
+ .replace(/>/g, "&gt;")
583
+ .replace(/"/g, "&quot;")
584
+ .replace(/'/g, "&#039;");
585
+ }
586
+
587
+ function showError(title, message, details = null) {
588
+ let html = `
589
+ <div class="alert">
590
+ <div class="alert-title">
591
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg>
592
+ ${escapeHtml(title)}
593
+ </div>
594
+ <div class="alert-body">${escapeHtml(message)}</div>
595
+ `;
596
+ if (details) {
597
+ html += `<div class="alert-details">${escapeHtml(details)}</div>`;
598
+ }
599
+ html += `</div>`;
600
+ appDiv.innerHTML = html;
601
+ }
602
+
603
+ function checkCollapsible() {
604
+ const wrapper = document.getElementById('content-wrapper');
605
+ const toggleContainer = document.getElementById('toggle-container');
606
+ const fadeOverlay = document.getElementById('fade-overlay');
607
+ const toggleIcon = document.getElementById('toggle-icon');
608
+ const toggleText = document.getElementById('toggle-text');
609
+
610
+ // 1. If no markdown, we are showing the skeleton. Do not collapse!
611
+ if (!rawMarkdownText) {
612
+ toggleContainer.style.display = 'none';
613
+ wrapper.style.maxHeight = 'none';
614
+ wrapper.style.overflowY = 'visible';
615
+ fadeOverlay.style.display = 'none';
616
+ triggerResize();
617
+ return;
618
+ }
619
+
620
+ // 2. Data is loaded
621
+ const realHeight = appDiv.scrollHeight;
622
+ const COLLAPSE_THRESHOLD = 300;
623
+ const COLLAPSED_HEIGHT = 150;
624
+ const EXPANDED_MAX_HEIGHT = 500;
625
+
626
+ if (realHeight > COLLAPSE_THRESHOLD) {
627
+ toggleContainer.style.display = 'flex';
628
+ if (isExpanded) {
629
+ // Open view! Scroll inside max 500px window
630
+ wrapper.style.maxHeight = EXPANDED_MAX_HEIGHT + 'px';
631
+ wrapper.style.overflowY = 'auto';
632
+ fadeOverlay.style.display = 'none';
633
+ toggleIcon.style.transform = 'rotate(180deg)';
634
+ toggleText.textContent = 'Show Less';
635
+ } else {
636
+ // Collapsed View
637
+ wrapper.style.maxHeight = COLLAPSED_HEIGHT + 'px';
638
+ wrapper.style.overflowY = 'hidden';
639
+ fadeOverlay.style.display = 'block';
640
+ toggleIcon.style.transform = 'rotate(0deg)';
641
+ toggleText.textContent = 'Show More';
642
+ }
643
+ } else {
644
+ toggleContainer.style.display = 'none';
645
+ wrapper.style.maxHeight = 'none';
646
+ wrapper.style.overflowY = 'visible';
647
+ fadeOverlay.style.display = 'none';
648
+ }
649
+
650
+ triggerResize();
651
+ }
652
+
653
+ document.getElementById('toggle-btn').addEventListener('click', () => {
654
+ isExpanded = !isExpanded;
655
+ checkCollapsible();
656
+ });
657
+
658
+ function triggerResize() {
659
+ // Measure the exact unconstrained height of the outer card
660
+ const card = document.querySelector('.adeu-card');
661
+ const containerChrome = 34; // 16px padding top/bottom + 2px borders
662
+
663
+ const requestedHeight = card.offsetHeight + containerChrome;
664
+
665
+ window.parent.postMessage({
666
+ jsonrpc: "2.0",
667
+ method: "ui/notifications/size-changed",
668
+ params: { height: Math.ceil(requestedHeight), width: 600 }
669
+ }, "*");
670
+ }
671
+
672
+ window.addEventListener("message", (event) => {
673
+ try {
674
+ if (!event.data || event.data.jsonrpc !== "2.0") return;
675
+ const msg = event.data;
676
+
677
+ if (msg.id === INIT_ID) {
678
+ window.parent.postMessage({
679
+ jsonrpc: "2.0",
680
+ method: "ui/notifications/initialized",
681
+ params: {}
682
+ }, "*");
683
+ return;
684
+ }
685
+
686
+ if (msg.method === "ui/notifications/tool-result") {
687
+ if (window.__MARKED_ERROR || typeof marked === 'undefined') {
688
+ showError("Missing Dependency", "The Markdown renderer failed to load.", window.__MARKED_ERROR || "marked is undefined.");
689
+ return;
690
+ }
691
+
692
+ const result = msg.params;
693
+
694
+ // If the state is pending, or no markdown is returned, completely hide the UI
695
+ if (!result || !result.structuredContent || result.structuredContent.status === "pending" || !result.structuredContent.markdown) {
696
+ document.documentElement.style.display = 'none';
697
+ window.parent.postMessage({
698
+ jsonrpc: "2.0",
699
+ method: "ui/notifications/size-changed",
700
+ params: { height: 0, width: 0 }
701
+ }, "*");
702
+ return;
703
+ }
704
+
705
+ // Render Markdown
706
+ rawMarkdownText = result.structuredContent.markdown;
707
+ if (result.structuredContent.file_path) {
708
+ currentFilePath = result.structuredContent.file_path;
709
+ openBtn.style.display = 'flex';
710
+ } else {
711
+ currentFilePath = null;
712
+ openBtn.style.display = 'none';
713
+ }
714
+ appDiv.innerHTML = marked.parse(rawMarkdownText);
715
+ copyBtn.style.display = 'flex';
716
+
717
+ if (result.structuredContent.title) {
718
+ navTitle.textContent = result.structuredContent.title;
719
+ navTitle.title = result.structuredContent.title;
720
+ }
721
+ }
722
+ } catch (error) {
723
+ showError("Rendering Engine Error", "An unexpected error occurred.", error.toString() + "\n" + error.stack);
724
+ }
725
+ });
726
+
727
+ const observer = new ResizeObserver(() => {
728
+ checkCollapsible();
729
+ });
730
+ observer.observe(appDiv);
731
+
732
+ window.parent.postMessage({
733
+ jsonrpc: "2.0",
734
+ id: INIT_ID,
735
+ method: "ui/initialize",
736
+ params: {
737
+ appInfo: { name: "Adeu Markdown UI", version: "1.1.0" },
738
+ appCapabilities: {},
739
+ protocolVersion: "2025-11-21"
740
+ }
741
+ }, "*");
742
+ </script>
743
+ </body>
744
+
745
+ </html>