@vantageos/mosaic 0.4.0 → 0.5.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 (150) hide show
  1. package/CHANGELOG.md +39 -15
  2. package/README.md +114 -5
  3. package/dist/PipelineBoard-FucyGArR.d.cts +759 -0
  4. package/dist/PipelineBoard-FucyGArR.d.ts +759 -0
  5. package/dist/PipelineBoard.markdown-DIcvrS-2.d.cts +16 -0
  6. package/dist/PipelineBoard.markdown-DIcvrS-2.d.ts +16 -0
  7. package/dist/{StatusBadge.schema-1tOjB4Ir.d.cts → StatusBadge.schema-BEjSH2_4.d.cts} +2 -2
  8. package/dist/{StatusBadge.schema-1tOjB4Ir.d.ts → StatusBadge.schema-BEjSH2_4.d.ts} +2 -2
  9. package/dist/{Tabs.schema-BzcEyeq8.d.cts → Tabs.schema-Dqr6vwV3.d.cts} +2 -2
  10. package/dist/{Tabs.schema-BzcEyeq8.d.ts → Tabs.schema-Dqr6vwV3.d.ts} +2 -2
  11. package/dist/Timeline-Coo_3tA_.d.cts +114 -0
  12. package/dist/Timeline-Coo_3tA_.d.ts +114 -0
  13. package/dist/Timeline.markdown-C6UPDv1H.d.cts +4 -0
  14. package/dist/Timeline.markdown-C6UPDv1H.d.ts +4 -0
  15. package/dist/TransactionPreview-BzWDn8kE.d.cts +391 -0
  16. package/dist/TransactionPreview-BzWDn8kE.d.ts +391 -0
  17. package/dist/TransactionPreview.markdown-Dpb0VYgN.d.cts +7 -0
  18. package/dist/TransactionPreview.markdown-Dpb0VYgN.d.ts +7 -0
  19. package/dist/artifacts.cjs +186 -2
  20. package/dist/artifacts.cjs.map +1 -1
  21. package/dist/artifacts.js +186 -2
  22. package/dist/artifacts.js.map +1 -1
  23. package/dist/confirmation.cjs +724 -2
  24. package/dist/confirmation.cjs.map +1 -1
  25. package/dist/confirmation.d.cts +2 -1
  26. package/dist/confirmation.d.ts +2 -1
  27. package/dist/confirmation.js +722 -4
  28. package/dist/confirmation.js.map +1 -1
  29. package/dist/display.cjs +1551 -203
  30. package/dist/display.cjs.map +1 -1
  31. package/dist/display.d.cts +6 -229
  32. package/dist/display.d.ts +6 -229
  33. package/dist/display.js +1535 -206
  34. package/dist/display.js.map +1 -1
  35. package/dist/forms.cjs +139 -46
  36. package/dist/forms.cjs.map +1 -1
  37. package/dist/forms.d.cts +2 -2
  38. package/dist/forms.d.ts +2 -2
  39. package/dist/forms.js +139 -46
  40. package/dist/forms.js.map +1 -1
  41. package/dist/host.cjs +822 -0
  42. package/dist/host.cjs.map +1 -0
  43. package/dist/host.d.cts +287 -0
  44. package/dist/host.d.ts +287 -0
  45. package/dist/host.js +794 -0
  46. package/dist/host.js.map +1 -0
  47. package/dist/{index-CwXVgtGb.d.cts → index-BadRcCbm.d.cts} +28 -11
  48. package/dist/{index-CwXVgtGb.d.ts → index-BadRcCbm.d.ts} +28 -11
  49. package/dist/index.cjs +2198 -247
  50. package/dist/index.cjs.map +1 -1
  51. package/dist/index.d.cts +42 -8
  52. package/dist/index.d.ts +42 -8
  53. package/dist/index.js +2163 -251
  54. package/dist/index.js.map +1 -1
  55. package/dist/input.d.cts +2 -2
  56. package/dist/input.d.ts +2 -2
  57. package/dist/media.cjs +186 -2
  58. package/dist/media.cjs.map +1 -1
  59. package/dist/media.d.cts +1 -1
  60. package/dist/media.d.ts +1 -1
  61. package/dist/media.js +186 -2
  62. package/dist/media.js.map +1 -1
  63. package/dist/preact/artifacts.js +186 -2
  64. package/dist/preact/artifacts.js.map +1 -1
  65. package/dist/preact/confirmation.d.ts +321 -1
  66. package/dist/preact/confirmation.js +625 -4
  67. package/dist/preact/confirmation.js.map +1 -1
  68. package/dist/preact/display.d.ts +544 -47
  69. package/dist/preact/display.js +1190 -126
  70. package/dist/preact/display.js.map +1 -1
  71. package/dist/preact/forms.d.ts +32 -15
  72. package/dist/preact/forms.js +139 -46
  73. package/dist/preact/forms.js.map +1 -1
  74. package/dist/preact/host.d.ts +307 -0
  75. package/dist/preact/host.js +875 -0
  76. package/dist/preact/host.js.map +1 -0
  77. package/dist/preact/media.d.ts +37 -1
  78. package/dist/preact/media.js +423 -0
  79. package/dist/preact/media.js.map +1 -1
  80. package/dist/preact/progress.d.ts +92 -1
  81. package/dist/preact/progress.js +465 -3
  82. package/dist/preact/progress.js.map +1 -1
  83. package/dist/progress.cjs +521 -2
  84. package/dist/progress.cjs.map +1 -1
  85. package/dist/progress.d.cts +2 -1
  86. package/dist/progress.d.ts +2 -1
  87. package/dist/progress.js +518 -3
  88. package/dist/progress.js.map +1 -1
  89. package/dist/react/artifacts.cjs +186 -2
  90. package/dist/react/artifacts.cjs.map +1 -1
  91. package/dist/react/artifacts.js +186 -2
  92. package/dist/react/artifacts.js.map +1 -1
  93. package/dist/react/confirmation.cjs +626 -2
  94. package/dist/react/confirmation.cjs.map +1 -1
  95. package/dist/react/confirmation.d.cts +3 -3
  96. package/dist/react/confirmation.d.ts +3 -3
  97. package/dist/react/confirmation.js +625 -4
  98. package/dist/react/confirmation.js.map +1 -1
  99. package/dist/react/display.cjs +1076 -123
  100. package/dist/react/display.cjs.map +1 -1
  101. package/dist/react/display.d.cts +13 -27
  102. package/dist/react/display.d.ts +13 -27
  103. package/dist/react/display.js +1064 -126
  104. package/dist/react/display.js.map +1 -1
  105. package/dist/react/forms.cjs +139 -46
  106. package/dist/react/forms.cjs.map +1 -1
  107. package/dist/react/forms.d.cts +1 -1
  108. package/dist/react/forms.d.ts +1 -1
  109. package/dist/react/forms.js +139 -46
  110. package/dist/react/forms.js.map +1 -1
  111. package/dist/react/host.cjs +910 -0
  112. package/dist/react/host.cjs.map +1 -0
  113. package/dist/react/host.d.cts +24 -0
  114. package/dist/react/host.d.ts +24 -0
  115. package/dist/react/host.js +875 -0
  116. package/dist/react/host.js.map +1 -0
  117. package/dist/react/input.d.cts +1 -1
  118. package/dist/react/input.d.ts +1 -1
  119. package/dist/react/media.cjs +426 -0
  120. package/dist/react/media.cjs.map +1 -1
  121. package/dist/react/media.d.cts +19 -1
  122. package/dist/react/media.d.ts +19 -1
  123. package/dist/react/media.js +423 -0
  124. package/dist/react/media.js.map +1 -1
  125. package/dist/react/progress.cjs +467 -2
  126. package/dist/react/progress.cjs.map +1 -1
  127. package/dist/react/progress.d.cts +1 -1
  128. package/dist/react/progress.d.ts +1 -1
  129. package/dist/react/progress.js +465 -3
  130. package/dist/react/progress.js.map +1 -1
  131. package/dist/server/resource.cjs +151 -0
  132. package/dist/server/resource.cjs.map +1 -0
  133. package/dist/server/resource.d.cts +90 -0
  134. package/dist/server/resource.d.ts +90 -0
  135. package/dist/server/resource.js +147 -0
  136. package/dist/server/resource.js.map +1 -0
  137. package/dist/server.cjs +1100 -25
  138. package/dist/server.cjs.map +1 -1
  139. package/dist/server.d.cts +84 -5
  140. package/dist/server.d.ts +84 -5
  141. package/dist/server.js +1087 -27
  142. package/dist/server.js.map +1 -1
  143. package/package.json +250 -233
  144. package/registry.yaml +44 -2
  145. package/dist/Alert.schema-LPJE5gFP.d.cts +0 -71
  146. package/dist/Alert.schema-LPJE5gFP.d.ts +0 -71
  147. package/dist/ProgressBar.schema-CdVYx0Wq.d.cts +0 -22
  148. package/dist/ProgressBar.schema-CdVYx0Wq.d.ts +0 -22
  149. package/dist/{ConfirmDialog-B3CQQGmJ.d.cts → ConfirmDialog-BCtOcmHe.d.cts} +1 -1
  150. package/dist/{ConfirmDialog-B3CQQGmJ.d.ts → ConfirmDialog-BCtOcmHe.d.ts} +1 -1
package/dist/server.js CHANGED
@@ -1,32 +1,902 @@
1
1
  import { createUIResource } from '@mcp-ui/server';
2
- import { z } from 'zod';
2
+ import { z, ZodError } from 'zod';
3
3
 
4
4
  // src/server/create-mosaic-resource.ts
5
+
6
+ // src/i18n/strings.ts
7
+ var EN = {
8
+ // ─── Non-forms components ──────────────────────────────────────────────────
9
+ "ProgressBar.aria.label": "Progress",
10
+ "ProgressBar.error.invalidProps": "ProgressBar: invalid props",
11
+ "ConfirmDialog.button.confirm": "Confirm",
12
+ "ConfirmDialog.button.cancel": "Cancel",
13
+ "ConfirmDialog.aria.dialog": "Confirmation dialog",
14
+ "TableView.aria.table": "Data table",
15
+ "TableView.pagination.next": "Next page",
16
+ "TableView.pagination.prev": "Previous page",
17
+ "TableView.empty.message": "No data to display",
18
+ "TableView.error.invalidProps": "TableView: invalid props",
19
+ "MarkdownRenderer.aria.content": "Rendered Markdown content",
20
+ "MarkdownRenderer.error.invalidProps": "MarkdownRenderer: invalid props",
21
+ "MarkdownRenderer.error.tooLong": "Content exceeds maximum length",
22
+ "TokenDisplayOnceModal.button.copy": "Copy token",
23
+ "TokenDisplayOnceModal.button.close": "Close",
24
+ "TokenDisplayOnceModal.warning.once": "This token will only be shown once. Copy it now.",
25
+ "TokenDisplayOnceModal.copied": "Copied",
26
+ "StatusBadge.aria.status": "Status",
27
+ "StatusBadge.error.invalidProps": "StatusBadge: invalid props",
28
+ "Badge.aria.label": "Badge",
29
+ "Badge.error.invalidProps": "Badge: invalid props",
30
+ "EmptyState.error.invalidProps": "EmptyState: invalid props",
31
+ "Toast.aria.close": "Close notification",
32
+ "Toast.error.invalidProps": "Toast: invalid props",
33
+ "Alert.aria.dismiss": "Dismiss alert",
34
+ "Alert.error.invalidProps": "Alert: invalid props",
35
+ "VirtualList.empty.message": "No items to display",
36
+ "VirtualList.error.invalidProps": "VirtualList: invalid props",
37
+ "Skeleton.aria.label": "Loading",
38
+ "Skeleton.error.invalidProps": "Skeleton: invalid props",
39
+ // ─── Forms — useMosaicForm ─────────────────────────────────────────────────
40
+ "useMosaicForm.error.invalidProps": "useMosaicForm: invalid options",
41
+ // ─── Forms — FormProvider ──────────────────────────────────────────────────
42
+ "FormProvider.error.invalidProps": "FormProvider: invalid props",
43
+ // ─── Forms — FormField ────────────────────────────────────────────────────
44
+ "FormField.error.invalidProps": "FormField: invalid props",
45
+ // ─── Forms — ErrorDisplay ─────────────────────────────────────────────────
46
+ "ErrorDisplay.error.required": "This field is required",
47
+ "ErrorDisplay.error.min": "Value is below the minimum",
48
+ "ErrorDisplay.error.max": "Value exceeds the maximum",
49
+ "ErrorDisplay.error.minLength": "Input is too short",
50
+ "ErrorDisplay.error.maxLength": "Input is too long",
51
+ "ErrorDisplay.error.pattern": "Invalid format",
52
+ "ErrorDisplay.error.email": "Enter a valid email address",
53
+ "ErrorDisplay.error.url": "Enter a valid URL",
54
+ "ErrorDisplay.error.generic": "Invalid value",
55
+ // ─── Forms — SubmitButton ─────────────────────────────────────────────────
56
+ "SubmitButton.aria.submit": "Submit form",
57
+ "SubmitButton.state.loading": "Submitting\u2026",
58
+ "SubmitButton.error.invalidProps": "SubmitButton: invalid props",
59
+ // ─── Forms — Input ────────────────────────────────────────────────────────
60
+ "Input.aria.label": "Input field",
61
+ "Input.error.required": "This field is required",
62
+ "Input.error.invalid": "Invalid value",
63
+ "Input.error.tooLong": "Input is too long",
64
+ "Input.error.tooShort": "Input is too short",
65
+ "Input.error.invalidProps": "Input: invalid props",
66
+ // ─── Forms — Textarea ─────────────────────────────────────────────────────
67
+ "Textarea.aria.label": "Text area",
68
+ "Textarea.error.required": "This field is required",
69
+ "Textarea.error.tooLong": "Text is too long",
70
+ "Textarea.counter.remaining": "characters remaining",
71
+ "Textarea.error.invalidProps": "Textarea: invalid props",
72
+ // ─── Forms — FieldArray ───────────────────────────────────────────────────
73
+ "FieldArray.aria.list": "List of items",
74
+ "FieldArray.aria.addItem": "Add item",
75
+ "FieldArray.aria.removeItem": "Remove item",
76
+ "FieldArray.error.invalidProps": "FieldArray: invalid props",
77
+ // ─── Forms — Checkbox ─────────────────────────────────────────────────────
78
+ "Checkbox.aria.label": "Checkbox",
79
+ "Checkbox.error.required": "This field must be checked",
80
+ "Checkbox.error.invalidProps": "Checkbox: invalid props",
81
+ // ─── Forms — MultiSelect ──────────────────────────────────────────────────
82
+ "MultiSelect.aria.label": "Multi-select field",
83
+ "MultiSelect.aria.removeChip": "Remove",
84
+ "MultiSelect.error.required": "Select at least one option",
85
+ "MultiSelect.error.maxItems": "Maximum number of selections reached",
86
+ "MultiSelect.placeholder": "Select options\u2026",
87
+ "MultiSelect.search.placeholder": "Search\u2026",
88
+ "MultiSelect.empty": "No options available",
89
+ "MultiSelect.error.invalidProps": "MultiSelect: invalid props",
90
+ // ─── Forms — RadioGroup ───────────────────────────────────────────────────
91
+ "RadioGroup.aria.label": "Radio group",
92
+ "RadioGroup.error.required": "Select one option",
93
+ "RadioGroup.error.invalidProps": "RadioGroup: invalid props",
94
+ // ─── Forms — Select ───────────────────────────────────────────────────────
95
+ "Select.placeholder": "Select an option\u2026",
96
+ "Select.search.placeholder": "Search\u2026",
97
+ "Select.empty": "No options available",
98
+ "Select.error.required": "Select an option",
99
+ "Select.error.invalidProps": "Select: invalid props",
100
+ "ModelContext.selection.one": "1 row selected",
101
+ "ModelContext.selection.many": "{n} rows selected",
102
+ "ModelContext.selection.none": "No rows selected",
103
+ "TableView.sort.by": "Sort by",
104
+ "TableView.select.row": "Select row",
105
+ "TableView.select.all": "Select all rows",
106
+ "TableView.loading": "Loading table",
107
+ "StatCard.title": "Statistic",
108
+ "StatCard.trend.up": "Up",
109
+ "StatCard.trend.down": "Down",
110
+ "StatCard.trend.flat": "Flat",
111
+ "StatCard.empty.message": "No statistic to display",
112
+ "StatCard.loading": "Loading statistic",
113
+ "StatCard.error.invalidProps": "StatCard: invalid props",
114
+ "BalanceCard.title": "Balance",
115
+ "BalanceCard.network": "Network",
116
+ "BalanceCard.testnet": "Testnet",
117
+ "BalanceCard.address": "Address",
118
+ "BalanceCard.contract": "Token contract",
119
+ "BalanceCard.value": "Value",
120
+ "BalanceCard.copy": "Copy address",
121
+ "BalanceCard.copied": "Address copied",
122
+ "BalanceCard.empty.message": "No balance to display",
123
+ "BalanceCard.loading": "Loading balance",
124
+ "BalanceCard.error.invalidProps": "BalanceCard: invalid props",
125
+ "Timeline.title": "Timeline",
126
+ "Timeline.status.done": "Done",
127
+ "Timeline.status.current": "In progress",
128
+ "Timeline.status.pending": "Pending",
129
+ "Timeline.status.blocked": "Blocked",
130
+ "Timeline.completed": "{n} completed",
131
+ "Timeline.more": "{n} more",
132
+ "Timeline.empty.message": "No steps to display",
133
+ "Timeline.loading": "Loading timeline",
134
+ "Timeline.error.invalidProps": "Timeline: invalid props",
135
+ "MessageFeed.title": "Messages",
136
+ "MessageFeed.unread": "Unread",
137
+ "MessageFeed.attachment": "Attachment",
138
+ "MessageFeed.showing": "Showing the latest {n} of {total}",
139
+ "MessageFeed.empty.message": "No messages",
140
+ "MessageFeed.loading": "Loading messages",
141
+ "MessageFeed.error.invalidProps": "MessageFeed: invalid props",
142
+ "PipelineBoard.title": "Pipeline",
143
+ "PipelineBoard.deals.one": "1 deal",
144
+ "PipelineBoard.deals.many": "{n} deals",
145
+ "PipelineBoard.total": "Total",
146
+ "PipelineBoard.stage.empty": "No deals",
147
+ "PipelineBoard.filter.label": "Show stages",
148
+ "PipelineBoard.summary.open": "Open full board",
149
+ "PipelineBoard.more": "{n} more stages",
150
+ "PipelineBoard.empty.message": "No pipeline to display",
151
+ "PipelineBoard.loading": "Loading pipeline",
152
+ "PipelineBoard.error.invalidProps": "PipelineBoard: invalid props",
153
+ "PipelineBoard.col.stage": "Stage",
154
+ "PipelineBoard.col.deals": "Deals",
155
+ "TransactionPreview.title": "Transaction preview",
156
+ "TransactionPreview.notice": "NOT SIGNED - preparation only",
157
+ "TransactionPreview.kind.transfer": "Transfer",
158
+ "TransactionPreview.kind.swap": "Swap",
159
+ "TransactionPreview.testnet": "Testnet",
160
+ "TransactionPreview.field.network": "Network",
161
+ "TransactionPreview.field.from": "From",
162
+ "TransactionPreview.field.to": "To",
163
+ "TransactionPreview.field.amount": "Amount",
164
+ "TransactionPreview.field.fee": "Network fee",
165
+ "TransactionPreview.field.sell": "Sell",
166
+ "TransactionPreview.field.buy": "Buy",
167
+ "TransactionPreview.field.minReceived": "Minimum received",
168
+ "TransactionPreview.field.route": "Route",
169
+ "TransactionPreview.field.priceImpact": "Price impact",
170
+ "TransactionPreview.field.expires": "Quote expires",
171
+ "TransactionPreview.priceImpact.high": "High price impact",
172
+ "TransactionPreview.simulation.success": "Simulation succeeded",
173
+ "TransactionPreview.simulation.failed": "Simulation failed",
174
+ "TransactionPreview.simulation.unavailable": "Simulation unavailable",
175
+ "TransactionPreview.warnings": "Warnings",
176
+ "TransactionPreview.handoff": "Open in wallet",
177
+ "TransactionPreview.empty.message": "No transaction to preview",
178
+ "TransactionPreview.loading": "Loading preview",
179
+ "TransactionPreview.error.invalidProps": "TransactionPreview: invalid props",
180
+ "ProgressBar.title": "Progress",
181
+ "ConfirmDialog.title": "Confirmation",
182
+ "ConfirmDialog.options": "Answers",
183
+ "TableView.title": "Data table",
184
+ "TableView.markdown.more": "{n} more rows",
185
+ "MarkdownRenderer.title": "Markdown content",
186
+ "TokenDisplayOnceModal.title": "Token (shown once)",
187
+ "StatusBadge.title": "Status",
188
+ "TokenDisplayOnceModal.notice.once": "The value is shown once, in the app view only.",
189
+ "TokenDisplayOnceModal.field.scope": "Scope",
190
+ "TokenDisplayOnceModal.field.expires": "Expires",
191
+ "TokenDisplayOnceModal.field.fingerprint": "Fingerprint"
192
+ };
193
+ var FR = {
194
+ // ─── Non-forms components ──────────────────────────────────────────────────
195
+ "ProgressBar.aria.label": "Progression",
196
+ "ProgressBar.error.invalidProps": "ProgressBar : propri\xE9t\xE9s invalides",
197
+ "ConfirmDialog.button.confirm": "Confirmer",
198
+ "ConfirmDialog.button.cancel": "Annuler",
199
+ "ConfirmDialog.aria.dialog": "Bo\xEEte de dialogue de confirmation",
200
+ "TableView.aria.table": "Tableau de donn\xE9es",
201
+ "TableView.pagination.next": "Page suivante",
202
+ "TableView.pagination.prev": "Page pr\xE9c\xE9dente",
203
+ "TableView.empty.message": "Aucune donn\xE9e \xE0 afficher",
204
+ "TableView.error.invalidProps": "TableView : propri\xE9t\xE9s invalides",
205
+ "MarkdownRenderer.aria.content": "Contenu Markdown rendu",
206
+ "MarkdownRenderer.error.invalidProps": "MarkdownRenderer : propri\xE9t\xE9s invalides",
207
+ "MarkdownRenderer.error.tooLong": "Le contenu d\xE9passe la longueur maximale",
208
+ "TokenDisplayOnceModal.button.copy": "Copier le jeton",
209
+ "TokenDisplayOnceModal.button.close": "Fermer",
210
+ "TokenDisplayOnceModal.warning.once": "Ce jeton ne sera affich\xE9 qu'une seule fois. Copiez-le maintenant.",
211
+ "TokenDisplayOnceModal.copied": "Copi\xE9",
212
+ "StatusBadge.aria.status": "Statut",
213
+ "StatusBadge.error.invalidProps": "StatusBadge : propri\xE9t\xE9s invalides",
214
+ "Badge.aria.label": "Badge",
215
+ "Badge.error.invalidProps": "Badge : propri\xE9t\xE9s invalides",
216
+ "EmptyState.error.invalidProps": "EmptyState : propri\xE9t\xE9s invalides",
217
+ "Toast.aria.close": "Fermer la notification",
218
+ "Toast.error.invalidProps": "Toast : propri\xE9t\xE9s invalides",
219
+ "Alert.aria.dismiss": "Fermer l'alerte",
220
+ "Alert.error.invalidProps": "Alert : propri\xE9t\xE9s invalides",
221
+ "VirtualList.empty.message": "Aucun \xE9l\xE9ment \xE0 afficher",
222
+ "VirtualList.error.invalidProps": "VirtualList : propri\xE9t\xE9s invalides",
223
+ "Skeleton.aria.label": "Chargement",
224
+ "Skeleton.error.invalidProps": "Skeleton : propri\xE9t\xE9s invalides",
225
+ // ─── Forms — useMosaicForm ─────────────────────────────────────────────────
226
+ "useMosaicForm.error.invalidProps": "useMosaicForm : options invalides",
227
+ // ─── Forms — FormProvider ──────────────────────────────────────────────────
228
+ "FormProvider.error.invalidProps": "FormProvider : propri\xE9t\xE9s invalides",
229
+ // ─── Forms — FormField ────────────────────────────────────────────────────
230
+ "FormField.error.invalidProps": "FormField : propri\xE9t\xE9s invalides",
231
+ // ─── Forms — ErrorDisplay ─────────────────────────────────────────────────
232
+ "ErrorDisplay.error.required": "Ce champ est obligatoire",
233
+ "ErrorDisplay.error.min": "La valeur est inf\xE9rieure au minimum",
234
+ "ErrorDisplay.error.max": "La valeur d\xE9passe le maximum",
235
+ "ErrorDisplay.error.minLength": "La saisie est trop courte",
236
+ "ErrorDisplay.error.maxLength": "La saisie est trop longue",
237
+ "ErrorDisplay.error.pattern": "Format invalide",
238
+ "ErrorDisplay.error.email": "Saisissez une adresse e-mail valide",
239
+ "ErrorDisplay.error.url": "Saisissez une URL valide",
240
+ "ErrorDisplay.error.generic": "Valeur invalide",
241
+ // ─── Forms — SubmitButton ─────────────────────────────────────────────────
242
+ "SubmitButton.aria.submit": "Soumettre le formulaire",
243
+ "SubmitButton.state.loading": "Envoi en cours\u2026",
244
+ "SubmitButton.error.invalidProps": "SubmitButton : propri\xE9t\xE9s invalides",
245
+ // ─── Forms — Input ────────────────────────────────────────────────────────
246
+ "Input.aria.label": "Champ de saisie",
247
+ "Input.error.required": "Ce champ est obligatoire",
248
+ "Input.error.invalid": "Valeur invalide",
249
+ "Input.error.tooLong": "La saisie est trop longue",
250
+ "Input.error.tooShort": "La saisie est trop courte",
251
+ "Input.error.invalidProps": "Input : propri\xE9t\xE9s invalides",
252
+ // ─── Forms — Textarea ─────────────────────────────────────────────────────
253
+ "Textarea.aria.label": "Zone de texte",
254
+ "Textarea.error.required": "Ce champ est obligatoire",
255
+ "Textarea.error.tooLong": "Le texte est trop long",
256
+ "Textarea.counter.remaining": "caract\xE8res restants",
257
+ "Textarea.error.invalidProps": "Textarea : propri\xE9t\xE9s invalides",
258
+ // ─── Forms — FieldArray ───────────────────────────────────────────────────
259
+ "FieldArray.aria.list": "Liste d'\xE9l\xE9ments",
260
+ "FieldArray.aria.addItem": "Ajouter un \xE9l\xE9ment",
261
+ "FieldArray.aria.removeItem": "Supprimer l'\xE9l\xE9ment",
262
+ "FieldArray.error.invalidProps": "FieldArray : propri\xE9t\xE9s invalides",
263
+ // ─── Forms — Checkbox ─────────────────────────────────────────────────────
264
+ "Checkbox.aria.label": "Case \xE0 cocher",
265
+ "Checkbox.error.required": "Ce champ doit \xEAtre coch\xE9",
266
+ "Checkbox.error.invalidProps": "Checkbox : propri\xE9t\xE9s invalides",
267
+ // ─── Forms — MultiSelect ──────────────────────────────────────────────────
268
+ "MultiSelect.aria.label": "Champ de s\xE9lection multiple",
269
+ "MultiSelect.aria.removeChip": "Retirer",
270
+ "MultiSelect.error.required": "S\xE9lectionnez au moins une option",
271
+ "MultiSelect.error.maxItems": "Nombre maximum de s\xE9lections atteint",
272
+ "MultiSelect.placeholder": "S\xE9lectionner des options\u2026",
273
+ "MultiSelect.search.placeholder": "Rechercher\u2026",
274
+ "MultiSelect.empty": "Aucune option disponible",
275
+ "MultiSelect.error.invalidProps": "MultiSelect : propri\xE9t\xE9s invalides",
276
+ // ─── Forms — RadioGroup ───────────────────────────────────────────────────
277
+ "RadioGroup.aria.label": "Groupe de boutons radio",
278
+ "RadioGroup.error.required": "S\xE9lectionnez une option",
279
+ "RadioGroup.error.invalidProps": "RadioGroup : propri\xE9t\xE9s invalides",
280
+ // ─── Forms — Select ───────────────────────────────────────────────────────
281
+ "Select.placeholder": "S\xE9lectionner une option\u2026",
282
+ "Select.search.placeholder": "Rechercher\u2026",
283
+ "Select.empty": "Aucune option disponible",
284
+ "Select.error.required": "S\xE9lectionnez une option",
285
+ "Select.error.invalidProps": "Select : propri\xE9t\xE9s invalides",
286
+ "ModelContext.selection.one": "1 ligne s\xE9lectionn\xE9e",
287
+ "ModelContext.selection.many": "{n} lignes s\xE9lectionn\xE9es",
288
+ "ModelContext.selection.none": "Aucune ligne s\xE9lectionn\xE9e",
289
+ "TableView.sort.by": "Trier par",
290
+ "TableView.select.row": "S\xE9lectionner la ligne",
291
+ "TableView.select.all": "Tout s\xE9lectionner",
292
+ "TableView.loading": "Chargement du tableau",
293
+ "StatCard.title": "Statistique",
294
+ "StatCard.trend.up": "En hausse",
295
+ "StatCard.trend.down": "En baisse",
296
+ "StatCard.trend.flat": "Stable",
297
+ "StatCard.empty.message": "Aucune statistique \xE0 afficher",
298
+ "StatCard.loading": "Chargement de la statistique",
299
+ "StatCard.error.invalidProps": "StatCard : propri\xE9t\xE9s invalides",
300
+ "BalanceCard.title": "Solde",
301
+ "BalanceCard.network": "R\xE9seau",
302
+ "BalanceCard.testnet": "R\xE9seau de test",
303
+ "BalanceCard.address": "Adresse",
304
+ "BalanceCard.contract": "Contrat du jeton",
305
+ "BalanceCard.value": "Valeur",
306
+ "BalanceCard.copy": "Copier l'adresse",
307
+ "BalanceCard.copied": "Adresse copi\xE9e",
308
+ "BalanceCard.empty.message": "Aucun solde \xE0 afficher",
309
+ "BalanceCard.loading": "Chargement du solde",
310
+ "BalanceCard.error.invalidProps": "BalanceCard : propri\xE9t\xE9s invalides",
311
+ "Timeline.title": "Chronologie",
312
+ "Timeline.status.done": "Termin\xE9",
313
+ "Timeline.status.current": "En cours",
314
+ "Timeline.status.pending": "\xC0 venir",
315
+ "Timeline.status.blocked": "Bloqu\xE9",
316
+ "Timeline.completed": "{n} termin\xE9(s)",
317
+ "Timeline.more": "{n} de plus",
318
+ "Timeline.empty.message": "Aucune \xE9tape \xE0 afficher",
319
+ "Timeline.loading": "Chargement de la chronologie",
320
+ "Timeline.error.invalidProps": "Timeline : propri\xE9t\xE9s invalides",
321
+ "MessageFeed.title": "Messages",
322
+ "MessageFeed.unread": "Non lu",
323
+ "MessageFeed.attachment": "Pi\xE8ce jointe",
324
+ "MessageFeed.showing": "Affichage des {n} derniers sur {total}",
325
+ "MessageFeed.empty.message": "Aucun message",
326
+ "MessageFeed.loading": "Chargement des messages",
327
+ "MessageFeed.error.invalidProps": "MessageFeed : propri\xE9t\xE9s invalides",
328
+ "PipelineBoard.title": "Pipeline",
329
+ "PipelineBoard.deals.one": "1 affaire",
330
+ "PipelineBoard.deals.many": "{n} affaires",
331
+ "PipelineBoard.total": "Total",
332
+ "PipelineBoard.stage.empty": "Aucune affaire",
333
+ "PipelineBoard.filter.label": "Afficher les \xE9tapes",
334
+ "PipelineBoard.summary.open": "Ouvrir le tableau complet",
335
+ "PipelineBoard.more": "{n} \xE9tapes de plus",
336
+ "PipelineBoard.empty.message": "Aucun pipeline \xE0 afficher",
337
+ "PipelineBoard.loading": "Chargement du pipeline",
338
+ "PipelineBoard.error.invalidProps": "PipelineBoard : propri\xE9t\xE9s invalides",
339
+ "PipelineBoard.col.stage": "\xC9tape",
340
+ "PipelineBoard.col.deals": "Affaires",
341
+ "TransactionPreview.title": "Aper\xE7u de transaction",
342
+ "TransactionPreview.notice": "NON SIGN\xC9 - pr\xE9paration uniquement",
343
+ "TransactionPreview.kind.transfer": "Transfert",
344
+ "TransactionPreview.kind.swap": "\xC9change",
345
+ "TransactionPreview.testnet": "R\xE9seau de test",
346
+ "TransactionPreview.field.network": "R\xE9seau",
347
+ "TransactionPreview.field.from": "De",
348
+ "TransactionPreview.field.to": "\xC0",
349
+ "TransactionPreview.field.amount": "Montant",
350
+ "TransactionPreview.field.fee": "Frais de r\xE9seau",
351
+ "TransactionPreview.field.sell": "Vendre",
352
+ "TransactionPreview.field.buy": "Acheter",
353
+ "TransactionPreview.field.minReceived": "Minimum re\xE7u",
354
+ "TransactionPreview.field.route": "Itin\xE9raire",
355
+ "TransactionPreview.field.priceImpact": "Impact sur le prix",
356
+ "TransactionPreview.field.expires": "Expiration du devis",
357
+ "TransactionPreview.priceImpact.high": "Impact sur le prix \xE9lev\xE9",
358
+ "TransactionPreview.simulation.success": "Simulation r\xE9ussie",
359
+ "TransactionPreview.simulation.failed": "Simulation \xE9chou\xE9e",
360
+ "TransactionPreview.simulation.unavailable": "Simulation indisponible",
361
+ "TransactionPreview.warnings": "Avertissements",
362
+ "TransactionPreview.handoff": "Ouvrir dans le portefeuille",
363
+ "TransactionPreview.empty.message": "Aucune transaction \xE0 pr\xE9visualiser",
364
+ "TransactionPreview.loading": "Chargement de l'aper\xE7u",
365
+ "TransactionPreview.error.invalidProps": "TransactionPreview : propri\xE9t\xE9s invalides",
366
+ "ProgressBar.title": "Progression",
367
+ "ConfirmDialog.title": "Confirmation",
368
+ "ConfirmDialog.options": "R\xE9ponses",
369
+ "TableView.title": "Tableau de donn\xE9es",
370
+ "TableView.markdown.more": "{n} lignes de plus",
371
+ "MarkdownRenderer.title": "Contenu Markdown",
372
+ "TokenDisplayOnceModal.title": "Jeton (affich\xE9 une fois)",
373
+ "StatusBadge.title": "Statut",
374
+ "TokenDisplayOnceModal.notice.once": "La valeur n'est affich\xE9e qu'une fois, dans la vue de l'application uniquement.",
375
+ "TokenDisplayOnceModal.field.scope": "Port\xE9e",
376
+ "TokenDisplayOnceModal.field.expires": "Expire le",
377
+ "TokenDisplayOnceModal.field.fingerprint": "Empreinte"
378
+ };
379
+ var TABLE = {
380
+ en: EN,
381
+ fr: FR
382
+ };
383
+ function t(key, locale = "en") {
384
+ return TABLE[locale]?.[key] ?? TABLE.en[key];
385
+ }
386
+
387
+ // src/components/shared/markdown.ts
388
+ var SPECIAL = /([\\`*_[\]()<>&!|~])/g;
389
+ var BREAKS = /* @__PURE__ */ new Set([10, 11, 12, 13, 133, 8232, 8233]);
390
+ function flatten(text) {
391
+ let out = "";
392
+ let gap = false;
393
+ for (const c of text) {
394
+ const n = c.codePointAt(0) ?? 0;
395
+ if (BREAKS.has(n)) {
396
+ gap = true;
397
+ continue;
398
+ }
399
+ if (n < 32 && n !== 9) continue;
400
+ if (n === 127) continue;
401
+ if (gap) out += " ";
402
+ gap = false;
403
+ out += c;
404
+ }
405
+ return gap ? `${out} ` : out;
406
+ }
407
+ function mdEscape(text) {
408
+ const flat = flatten(text).replace(SPECIAL, "\\$1").replace(/\b(https?|ftp):\/\//gi, "$1:\\/\\/").replace(/\bwww\./gi, (m) => `${m.slice(0, 3)}\\.`);
409
+ return flat.replace(/^(\s*)([#>+-])/, "$1\\$2").replace(/^(\s*\d+)([.)])(?=\s|$)/, "$1\\$2");
410
+ }
411
+ function mdUrl(href) {
412
+ return href.replace(
413
+ /[()[\]\\<>`\s]/g,
414
+ (c) => `%${c.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")}`
415
+ );
416
+ }
417
+ function mdCode(text) {
418
+ const flat = flatten(text);
419
+ const longest = Math.max(0, ...(flat.match(/`+/g) ?? []).map((r) => r.length));
420
+ const fence = "`".repeat(longest + 1);
421
+ return `${fence} ${flat} ${fence}`;
422
+ }
423
+ function mdTable(headers, rows) {
424
+ const line = (cells) => `| ${cells.join(" | ")} |`;
425
+ return [line(headers), line(headers.map(() => "---")), ...rows.map(line)].join("\n");
426
+ }
427
+ function mdHeading(text, level = 1) {
428
+ return `${"#".repeat(level)} ${text}`;
429
+ }
5
430
  var MarkdownRendererPropsSchema = z.object({
6
431
  content: z.string(),
7
432
  locale: z.enum(["en", "fr"]),
8
433
  maxLength: z.number().positive().default(5e4),
9
434
  allowHtml: z.boolean().default(false)
10
435
  });
436
+
437
+ // src/components/artifacts/MarkdownRenderer.markdown.ts
438
+ function markdownRendererToMarkdown(props, locale = "en") {
439
+ const p = MarkdownRendererPropsSchema.parse({ locale, ...props });
440
+ return `${mdHeading(t("MarkdownRenderer.title", locale))}
441
+
442
+ ${p.content.slice(0, p.maxLength)}
443
+ `;
444
+ }
11
445
  var TokenDisplayOnceModalPropsSchema = z.object({
12
446
  token: z.string().min(1),
13
447
  title: z.string().min(1),
14
448
  warningMessage: z.string().min(1),
15
449
  copyLabel: z.string().min(1),
16
450
  closeLabel: z.string().min(1),
451
+ /** Non-secret metadata, shown in the view AND carried by the A-1 fallback. */
452
+ scope: z.string().optional(),
453
+ expiresAt: z.string().optional(),
454
+ /** Supplied by the issuer; NEVER derived from the secret. */
455
+ fingerprint: z.string().optional(),
456
+ locale: z.enum(["en", "fr"]).default("en")
457
+ });
458
+
459
+ // src/components/confirmation/TokenDisplayOnceModal.markdown.ts
460
+ function tokenDisplayOnceModalToMarkdown(props, locale = "en") {
461
+ const p = TokenDisplayOnceModalPropsSchema.omit({ token: true }).parse(props);
462
+ const rows = [
463
+ p.scope ? `- ${t("TokenDisplayOnceModal.field.scope", locale)}: ${mdEscape(p.scope)}` : "",
464
+ p.expiresAt ? `- ${t("TokenDisplayOnceModal.field.expires", locale)}: ${mdEscape(p.expiresAt)}` : "",
465
+ p.fingerprint ? `- ${t("TokenDisplayOnceModal.field.fingerprint", locale)}: ${mdEscape(p.fingerprint)}` : ""
466
+ ].filter(Boolean);
467
+ return `${mdHeading(t("TokenDisplayOnceModal.title", locale))}
468
+
469
+ **${mdEscape(p.title)}**
470
+
471
+ ${rows.length ? `${rows.join("\n")}
472
+
473
+ ` : ""}${t("TokenDisplayOnceModal.notice.once", locale)}
474
+ `;
475
+ }
476
+
477
+ // src/components/shared/datetime.ts
478
+ function formatTimestamp(iso, locale, timeZone) {
479
+ const d = new Date(iso);
480
+ if (Number.isNaN(d.getTime())) return iso;
481
+ try {
482
+ return new Intl.DateTimeFormat(locale, {
483
+ dateStyle: "medium",
484
+ timeStyle: "short",
485
+ ...timeZone ? { timeZone } : {}
486
+ }).format(d);
487
+ } catch {
488
+ return iso;
489
+ }
490
+ }
491
+
492
+ // src/components/shared/url.ts
493
+ function normalizeHttpUrl(value) {
494
+ if (typeof value !== "string") return void 0;
495
+ try {
496
+ const u = new URL(value);
497
+ return u.protocol === "https:" || u.protocol === "http:" ? u.href : void 0;
498
+ } catch {
499
+ return void 0;
500
+ }
501
+ }
502
+ var AmountSchema = z.object({
503
+ /** Decimal STRING (never a float). */
504
+ value: z.string().min(1),
505
+ symbol: z.string().min(1)
506
+ });
507
+ var QuoteSchema = z.object({
508
+ sell: AmountSchema,
509
+ buy: AmountSchema,
510
+ minReceived: AmountSchema.optional(),
511
+ route: z.array(z.string().min(1)).optional(),
512
+ /** Percent as a decimal string, e.g. "0.42". */
513
+ priceImpact: z.string().optional()
514
+ });
515
+ var TransactionPreviewPropsSchema = z.object({
516
+ kind: z.enum(["transfer", "swap"]).default("transfer"),
517
+ network: z.string().optional(),
518
+ testnet: z.boolean().default(false),
519
+ from: z.string().optional(),
520
+ to: z.string().optional(),
521
+ amount: AmountSchema.optional(),
522
+ fee: AmountSchema.optional(),
523
+ quote: QuoteSchema.optional(),
524
+ simulation: z.object({
525
+ status: z.enum(["success", "failed", "unavailable"]),
526
+ message: z.string().optional()
527
+ }).optional(),
528
+ warnings: z.array(z.string()).default([]),
529
+ /** ISO 8601 expiry of the quote. */
530
+ expiresAt: z.string().optional(),
531
+ /** Wallet link-out. Only http(s) urls are ever rendered. */
532
+ handoff: z.object({ url: z.string().min(1) }).optional(),
533
+ timeZone: z.string().optional(),
534
+ loading: z.boolean().default(false),
535
+ locale: z.enum(["en", "fr"]).default("en")
536
+ });
537
+ function hasPreviewContent(p) {
538
+ return Boolean(p.from || p.to || p.amount || p.quote || p.fee);
539
+ }
540
+
541
+ // src/components/confirmation/TransactionPreview.markdown.ts
542
+ var amt = (a) => `${a.value} ${a.symbol}`;
543
+ function transactionPreviewToMarkdown(props, locale = "en") {
544
+ const title = mdHeading(t("TransactionPreview.title", locale));
545
+ const notice = `**${t("TransactionPreview.notice", locale)}**`;
546
+ const parsed = TransactionPreviewPropsSchema.safeParse(props);
547
+ if (!parsed.success || !hasPreviewContent(parsed.data)) {
548
+ return `${title}
549
+
550
+ ${notice}
551
+
552
+ ${t("TransactionPreview.empty.message", locale)}
553
+ `;
554
+ }
555
+ const p = parsed.data;
556
+ const rows = [];
557
+ const add = (key, value) => {
558
+ if (value) rows.push([t(key, locale), mdEscape(value)]);
559
+ };
560
+ add(
561
+ "TransactionPreview.field.network",
562
+ [p.network, p.testnet ? t("TransactionPreview.testnet", locale) : ""].filter(Boolean).join(", ")
563
+ );
564
+ add("TransactionPreview.field.from", p.from);
565
+ add("TransactionPreview.field.to", p.to);
566
+ if (p.amount) add("TransactionPreview.field.amount", amt(p.amount));
567
+ if (p.quote) {
568
+ add("TransactionPreview.field.sell", amt(p.quote.sell));
569
+ add("TransactionPreview.field.buy", amt(p.quote.buy));
570
+ if (p.quote.minReceived) add("TransactionPreview.field.minReceived", amt(p.quote.minReceived));
571
+ if (p.quote.route) add("TransactionPreview.field.route", p.quote.route.join(" \u2192 "));
572
+ if (p.quote.priceImpact) add("TransactionPreview.field.priceImpact", `${p.quote.priceImpact}%`);
573
+ }
574
+ if (p.fee) add("TransactionPreview.field.fee", amt(p.fee));
575
+ if (p.expiresAt) {
576
+ add("TransactionPreview.field.expires", formatTimestamp(p.expiresAt, locale, p.timeZone));
577
+ }
578
+ const sections = [
579
+ `${title}
580
+
581
+ ${notice}`,
582
+ mdTable([t(`TransactionPreview.kind.${p.kind}`, locale), ""], rows)
583
+ ];
584
+ if (p.simulation) {
585
+ const msg = p.simulation.message ? ` - ${mdEscape(p.simulation.message)}` : "";
586
+ sections.push(`${t(`TransactionPreview.simulation.${p.simulation.status}`, locale)}${msg}`);
587
+ }
588
+ if (p.warnings.length > 0) {
589
+ sections.push(
590
+ `${t("TransactionPreview.warnings", locale)}:
591
+ ${p.warnings.map((w) => `- ${mdEscape(w)}`).join("\n")}`
592
+ );
593
+ }
594
+ const handoff = normalizeHttpUrl(p.handoff?.url);
595
+ if (handoff) sections.push(`${t("TransactionPreview.handoff", locale)}: <${mdUrl(handoff)}>`);
596
+ return `${sections.join("\n\n")}
597
+ `;
598
+ }
599
+
600
+ // src/components/shared/decimal.ts
601
+ var DECIMAL = /^(-)?(\d+)(?:\.(\d+))?$/;
602
+ function sumDecimalStrings(values) {
603
+ let scale = 0;
604
+ const parsed = [];
605
+ for (const v of values) {
606
+ const m = DECIMAL.exec(v);
607
+ if (!m) return void 0;
608
+ const frac2 = m[3] ?? "";
609
+ scale = Math.max(scale, frac2.length);
610
+ parsed.push({ neg: m[1] === "-", int: m[2] ?? "0", frac: frac2 });
611
+ }
612
+ let total = 0n;
613
+ for (const p of parsed) {
614
+ const n = BigInt(p.int + p.frac.padEnd(scale, "0"));
615
+ total += p.neg ? -n : n;
616
+ }
617
+ const neg = total < 0n;
618
+ const digits = (neg ? -total : total).toString().padStart(scale + 1, "0");
619
+ const int = digits.slice(0, digits.length - scale);
620
+ const frac = digits.slice(digits.length - scale).replace(/0+$/, "");
621
+ return `${neg ? "-" : ""}${int}${frac ? `.${frac}` : ""}`;
622
+ }
623
+ function formatDecimalString(value, locale, currency) {
624
+ if (!DECIMAL.test(value)) return value;
625
+ try {
626
+ const nf = new Intl.NumberFormat(
627
+ locale,
628
+ currency ? { style: "currency", currency } : { maximumFractionDigits: 20 }
629
+ );
630
+ return nf.format(value);
631
+ } catch {
632
+ return value;
633
+ }
634
+ }
635
+ var BalanceCardPropsSchema = z.object({
636
+ token: z.string().default(""),
637
+ balance: z.string().default(""),
638
+ address: z.string().default(""),
639
+ tokenAddress: z.string().optional(),
640
+ decimals: z.number().int().nonnegative().optional(),
641
+ network: z.string().optional(),
642
+ testnet: z.boolean().default(false),
643
+ /** Decimal string in `currency`. */
644
+ usdValue: z.string().optional(),
645
+ currency: z.string().default("USD"),
646
+ loading: z.boolean().default(false),
647
+ locale: z.enum(["en", "fr"]).default("en")
648
+ });
649
+
650
+ // src/components/display/BalanceCard.markdown.ts
651
+ function balanceCardToMarkdown(props, locale = "en") {
652
+ const parsed = BalanceCardPropsSchema.safeParse(props);
653
+ const title = mdHeading(t("BalanceCard.title", locale));
654
+ if (!parsed.success || parsed.data.token === "" && parsed.data.balance === "") {
655
+ return `${title}
656
+
657
+ ${t("BalanceCard.empty.message", locale)}
658
+ `;
659
+ }
660
+ const p = parsed.data;
661
+ const where = [p.network, p.testnet ? t("BalanceCard.testnet", locale) : ""].filter(Boolean);
662
+ const lines = [
663
+ `- ${mdEscape(p.token)}: ${mdEscape(p.balance)}${where.length ? ` (${mdEscape(where.join(", "))})` : ""}`
664
+ ];
665
+ if (p.usdValue) {
666
+ lines.push(
667
+ `- ${t("BalanceCard.value", locale)}: ${mdEscape(formatDecimalString(p.usdValue, locale, p.currency))}`
668
+ );
669
+ }
670
+ if (p.address) lines.push(`- ${t("BalanceCard.address", locale)}: ${mdCode(p.address)}`);
671
+ if (p.tokenAddress)
672
+ lines.push(`- ${t("BalanceCard.contract", locale)}: ${mdCode(p.tokenAddress)}`);
673
+ return `${title}
674
+
675
+ ${lines.join("\n")}
676
+ `;
677
+ }
678
+ var FeedMessageSchema = z.object({
679
+ id: z.string().optional(),
680
+ sender: z.string().min(1),
681
+ channel: z.string().optional(),
682
+ /** Plain text. Rendered as text, never as HTML. */
683
+ content: z.string(),
684
+ /** ISO 8601. */
685
+ timestamp: z.string(),
686
+ attachmentUrl: z.string().optional(),
687
+ attachmentLabel: z.string().optional(),
688
+ unread: z.boolean().optional()
689
+ });
690
+ var MessageFeedPropsSchema = z.object({
691
+ messages: z.array(FeedMessageSchema).default([]),
692
+ maxItems: z.number().int().positive().optional(),
693
+ /** IANA timezone for timestamps (e.g. `hostContext.timeZone`). */
694
+ timeZone: z.string().optional(),
695
+ /** Above this many shown messages the feed is virtualised through VirtualList. */
696
+ virtualizeThreshold: z.number().int().positive().default(50),
697
+ loading: z.boolean().default(false),
698
+ locale: z.enum(["en", "fr"]).default("en")
699
+ });
700
+ function latestMessages(messages, maxItems) {
701
+ const shown = maxItems === void 0 ? [...messages] : messages.slice(-maxItems);
702
+ return { shown, total: messages.length };
703
+ }
704
+
705
+ // src/components/display/MessageFeed.markdown.ts
706
+ function messageFeedToMarkdown(props, locale = "en") {
707
+ const parsed = MessageFeedPropsSchema.safeParse(props);
708
+ const title = mdHeading(t("MessageFeed.title", locale));
709
+ if (!parsed.success || parsed.data.messages.length === 0) {
710
+ return `${title}
711
+
712
+ ${t("MessageFeed.empty.message", locale)}
713
+ `;
714
+ }
715
+ const { messages, maxItems, timeZone } = parsed.data;
716
+ const { shown, total } = latestMessages(messages, maxItems);
717
+ const lines = shown.map((m) => {
718
+ const when = [formatTimestamp(m.timestamp, locale, timeZone), m.channel ?? ""].filter(Boolean).join(", ");
719
+ const href = normalizeHttpUrl(m.attachmentUrl);
720
+ const label = mdEscape(m.attachmentLabel ?? t("MessageFeed.attachment", locale));
721
+ const attachment = m.attachmentUrl ? href ? ` [${label}](${mdUrl(href)})` : ` ${label}` : "";
722
+ return `> **${mdEscape(m.sender)}** (${mdEscape(when)}): ${mdEscape(m.content)}${attachment}`;
723
+ });
724
+ const cut = shown.length < total ? `${t("MessageFeed.showing", locale).replace("{n}", String(shown.length)).replace("{total}", String(total))}
725
+
726
+ ` : "";
727
+ return `${title}
728
+
729
+ ${cut}${lines.join("\n>\n")}
730
+ `;
731
+ }
732
+
733
+ // src/components/display/PipelineBoard.logic.ts
734
+ function stageSummary(deals) {
735
+ const amounts = deals.flatMap((d) => d.amount === void 0 ? [] : [d.amount]);
736
+ return { count: deals.length, total: sumDecimalStrings(amounts) };
737
+ }
738
+ var PipelineDealSchema = z.object({
739
+ id: z.string().min(1),
740
+ title: z.string().min(1),
741
+ /** Decimal STRING (never a float), in the board currency. */
742
+ amount: z.string().optional(),
743
+ contact: z.string().optional(),
744
+ url: z.string().optional()
745
+ });
746
+ var PipelineStageSchema = z.object({
747
+ id: z.string().min(1),
748
+ name: z.string().min(1),
749
+ deals: z.array(PipelineDealSchema).default([])
750
+ });
751
+ var PipelineBoardPropsSchema = z.object({
752
+ stages: z.array(PipelineStageSchema).default([]),
753
+ /** ISO 4217 code used to format amounts. */
754
+ currency: z.string().default("EUR"),
755
+ layout: z.enum(["board", "summary"]).default("board"),
756
+ loading: z.boolean().default(false),
757
+ locale: z.enum(["en", "fr"]).default("en")
758
+ });
759
+
760
+ // src/components/display/PipelineBoard.markdown.ts
761
+ function pipelineBoardToMarkdown(props, locale = "en") {
762
+ const parsed = PipelineBoardPropsSchema.safeParse(props);
763
+ const title = mdHeading(t("PipelineBoard.title", locale));
764
+ if (!parsed.success || parsed.data.stages.length === 0) {
765
+ return `${title}
766
+
767
+ ${t("PipelineBoard.empty.message", locale)}
768
+ `;
769
+ }
770
+ const { stages, currency } = parsed.data;
771
+ const money = (v) => mdEscape(formatDecimalString(v, locale, currency));
772
+ const table = mdTable(
773
+ [
774
+ t("PipelineBoard.col.stage", locale),
775
+ t("PipelineBoard.col.deals", locale),
776
+ t("PipelineBoard.total", locale)
777
+ ],
778
+ stages.map((s) => {
779
+ const sum = stageSummary(s.deals);
780
+ return [
781
+ mdEscape(s.name),
782
+ String(sum.count),
783
+ sum.total === void 0 ? "-" : money(sum.total)
784
+ ];
785
+ })
786
+ );
787
+ const sections = stages.filter((s) => s.deals.length > 0).map((s) => {
788
+ const lines = s.deals.map((d) => {
789
+ const amount = d.amount === void 0 ? "" : ` (${money(d.amount)})`;
790
+ const contact = d.contact ? ` - ${mdEscape(d.contact)}` : "";
791
+ return `- ${mdEscape(d.title)}${amount}${contact}`;
792
+ });
793
+ return `${mdHeading(mdEscape(s.name), 2)}
794
+
795
+ ${lines.join("\n")}`;
796
+ });
797
+ return `${title}
798
+
799
+ ${table}
800
+ ${sections.length ? `
801
+ ${sections.join("\n\n")}
802
+ ` : ""}`;
803
+ }
804
+ var StatCardPropsSchema = z.object({
805
+ label: z.string().default(""),
806
+ value: z.string().default(""),
807
+ unit: z.string().optional(),
808
+ trend: z.enum(["up", "down", "flat"]).optional(),
809
+ /** Pre-formatted change, e.g. "+4.2%". */
810
+ change: z.string().optional(),
811
+ tone: z.enum(["neutral", "success", "warning", "danger"]).default("neutral"),
812
+ description: z.string().optional(),
813
+ loading: z.boolean().default(false),
17
814
  locale: z.enum(["en", "fr"]).default("en")
18
815
  });
816
+
817
+ // src/components/display/StatCard.markdown.ts
818
+ function statCardToMarkdown(props, locale = "en") {
819
+ const parsed = StatCardPropsSchema.safeParse(props);
820
+ const title = mdHeading(t("StatCard.title", locale));
821
+ if (!parsed.success || parsed.data.label === "" && parsed.data.value === "") {
822
+ return `${title}
823
+
824
+ ${t("StatCard.empty.message", locale)}
825
+ `;
826
+ }
827
+ const { label, value, unit, trend, change, description } = parsed.data;
828
+ const amount = unit ? `${value} ${unit}` : value;
829
+ const movement = [trend ? t(`StatCard.trend.${trend}`, locale) : "", change ?? ""].filter(Boolean).join(" ");
830
+ const line = `- **${mdEscape(label)}**: ${mdEscape(amount)}${movement ? ` (${mdEscape(movement)})` : ""}`;
831
+ return `${title}
832
+
833
+ ${line}
834
+ ${description ? `
835
+ ${mdEscape(description)}
836
+ ` : ""}`;
837
+ }
838
+ var ColumnKindSchema = z.enum(["text", "number", "amount", "icon"]);
839
+ var AlignSchema = z.enum(["start", "center", "end"]);
19
840
  var ColumnDefSchema = z.object({
20
841
  key: z.string().min(1),
21
- header: z.string().min(1)
842
+ header: z.string().min(1),
843
+ /** Cell kind: drives comparison and rendering. `amount` = decimal STRING, never a float. */
844
+ type: ColumnKindSchema.default("text"),
845
+ /** Defaults to `end` for `number` / `amount` columns, `start` otherwise. */
846
+ align: AlignSchema.optional(),
847
+ /** CSS width: a number is pixels. */
848
+ width: z.union([z.string().min(1), z.number().positive()]).optional(),
849
+ sortable: z.boolean().default(false),
850
+ /**
851
+ * Values of this column are masked in the A-1 markdown fallback and kept out of the HTML
852
+ * props of a tool result (delivered via the result `_meta`), never written to `content[]`.
853
+ */
854
+ sensitive: z.boolean().default(false)
22
855
  // render is a runtime function — excluded from Zod, typed separately
23
856
  });
857
+ var SortSchema = z.object({ key: z.string().min(1), direction: z.enum(["asc", "desc"]) });
24
858
  var TableViewPropsSchema = z.object({
25
859
  columns: z.array(ColumnDefSchema).min(1, "TableView requires at least one column"),
860
+ /**
861
+ * Serialisable rows, for views built through `createMosaicResource` (the React props carry
862
+ * `rows` separately).
863
+ */
864
+ rows: z.array(z.record(z.unknown())).default([]),
26
865
  virtualizeThreshold: z.number().int().positive().default(100),
27
866
  ariaLabel: z.string().min(1),
28
- locale: z.enum(["en", "fr"]).default("en")
867
+ locale: z.enum(["en", "fr"]).default("en"),
868
+ selectionMode: z.enum(["none", "single", "multiple"]).default("none"),
869
+ /** Initial sort. */
870
+ sort: SortSchema.optional(),
871
+ stickyHeader: z.boolean().default(false),
872
+ /** Scroll region height when `stickyHeader` is on (pixels). */
873
+ maxHeight: z.number().int().positive().default(400),
874
+ density: z.enum(["comfortable", "compact"]).default("comfortable"),
875
+ loading: z.boolean().default(false)
29
876
  });
877
+
878
+ // src/components/display/TableView.markdown.ts
879
+ var MARKDOWN_MAX_ROWS = 50;
880
+ var MASK = "\u2022\u2022\u2022\u2022";
881
+ function tableViewToMarkdown(props, locale = "en") {
882
+ const p = TableViewPropsSchema.parse(props);
883
+ const shown = p.rows.slice(0, MARKDOWN_MAX_ROWS);
884
+ const table = mdTable(
885
+ p.columns.map((c) => mdEscape(c.header)),
886
+ shown.map((r) => p.columns.map((c) => c.sensitive ? MASK : mdEscape(String(r[c.key] ?? ""))))
887
+ );
888
+ const rest = p.rows.length - shown.length;
889
+ const more = rest > 0 ? `
890
+ ${t("TableView.markdown.more", locale).replace("{n}", String(rest))}
891
+ ` : "";
892
+ const empty = p.rows.length === 0 ? `
893
+ ${t("TableView.empty.message", locale)}
894
+ ` : "";
895
+ return `${mdHeading(t("TableView.title", locale))}
896
+
897
+ ${table}
898
+ ${more}${empty}`;
899
+ }
30
900
  var ConfirmDialogPropsSchema = z.object({
31
901
  title: z.string().min(1),
32
902
  message: z.string().min(1),
@@ -35,12 +905,34 @@ var ConfirmDialogPropsSchema = z.object({
35
905
  variant: z.enum(["default", "danger"]).default("default"),
36
906
  locale: z.enum(["en", "fr"]).default("en")
37
907
  });
908
+
909
+ // src/components/input/ConfirmDialog.markdown.ts
910
+ function confirmDialogToMarkdown(props, locale = "en") {
911
+ const p = ConfirmDialogPropsSchema.parse(props);
912
+ return `${mdHeading(t("ConfirmDialog.title", locale))}
913
+
914
+ **${mdEscape(p.title)}**
915
+
916
+ ${mdEscape(p.message)}
917
+
918
+ ${t("ConfirmDialog.options", locale)}: ${mdEscape(p.confirmLabel)} / ${mdEscape(p.cancelLabel)}
919
+ `;
920
+ }
38
921
  var StatusBadgePropsSchema = z.object({
39
922
  status: z.string(),
40
923
  variant: z.enum(["success", "warning", "danger", "info", "neutral"]).default("neutral"),
41
924
  label: z.string().optional(),
42
925
  locale: z.enum(["en", "fr"])
43
926
  });
927
+
928
+ // src/components/media/StatusBadge.markdown.ts
929
+ function statusBadgeToMarkdown(props, locale = "en") {
930
+ const p = StatusBadgePropsSchema.parse({ locale, ...props });
931
+ return `${mdHeading(t("StatusBadge.title", locale))}
932
+
933
+ - ${mdEscape(p.label ?? p.status)} (${p.variant})
934
+ `;
935
+ }
44
936
  var ProgressBarPropsSchema = z.object({
45
937
  value: z.number().min(0).max(100),
46
938
  label: z.string().min(1),
@@ -48,6 +940,58 @@ var ProgressBarPropsSchema = z.object({
48
940
  colorVariant: z.enum(["default", "warning", "danger"]).default("default")
49
941
  });
50
942
 
943
+ // src/components/progress/ProgressBar.markdown.ts
944
+ function progressBarToMarkdown(props, locale = "en") {
945
+ const p = ProgressBarPropsSchema.parse(props);
946
+ const variant = p.colorVariant === "default" ? "" : ` (${p.colorVariant})`;
947
+ return `${mdHeading(t("ProgressBar.title", locale))}
948
+
949
+ - ${mdEscape(p.label)}: ${p.value}%${variant}
950
+ `;
951
+ }
952
+ var TimelineStepSchema = z.object({
953
+ id: z.string().optional(),
954
+ title: z.string().min(1),
955
+ status: z.enum(["done", "current", "pending", "blocked"]),
956
+ description: z.string().optional(),
957
+ /** ISO 8601. */
958
+ timestamp: z.string().optional()
959
+ });
960
+ var TimelinePropsSchema = z.object({
961
+ steps: z.array(TimelineStepSchema).default([]),
962
+ orientation: z.enum(["vertical", "horizontal"]).default("vertical"),
963
+ compact: z.boolean().default(false),
964
+ /** IANA timezone for timestamps (e.g. `hostContext.timeZone`). Default: the viewer's. */
965
+ timeZone: z.string().optional(),
966
+ loading: z.boolean().default(false),
967
+ locale: z.enum(["en", "fr"]).default("en")
968
+ });
969
+
970
+ // src/components/progress/Timeline.markdown.ts
971
+ function timelineToMarkdown(props, locale = "en") {
972
+ const parsed = TimelinePropsSchema.safeParse(props);
973
+ const title = mdHeading(t("Timeline.title", locale));
974
+ if (!parsed.success || parsed.data.steps.length === 0) {
975
+ return `${title}
976
+
977
+ ${t("Timeline.empty.message", locale)}
978
+ `;
979
+ }
980
+ const { steps, timeZone } = parsed.data;
981
+ const lines = steps.map((s, i) => {
982
+ const status = t(`Timeline.status.${s.status}`, locale);
983
+ const extras = [
984
+ s.description ? mdEscape(s.description) : "",
985
+ s.timestamp ? mdEscape(formatTimestamp(s.timestamp, locale, timeZone)) : ""
986
+ ].filter(Boolean);
987
+ return `${i + 1}. [${status}] ${mdEscape(s.title)}${extras.length ? ` - ${extras.join(" - ")}` : ""}`;
988
+ });
989
+ return `${title}
990
+
991
+ ${lines.join("\n")}
992
+ `;
993
+ }
994
+
51
995
  // src/server/create-mosaic-resource.ts
52
996
  var MCP_UI_CAPABILITY_KEY = "io.modelcontextprotocol/ui";
53
997
  var MOSAIC_MIME_TYPE = "text/html;profile=mcp-app";
@@ -57,42 +1001,50 @@ var SCHEMA_BY_NAME = {
57
1001
  TableView: TableViewPropsSchema,
58
1002
  MarkdownRenderer: MarkdownRendererPropsSchema,
59
1003
  TokenDisplayOnceModal: TokenDisplayOnceModalPropsSchema,
60
- StatusBadge: StatusBadgePropsSchema
1004
+ StatusBadge: StatusBadgePropsSchema,
1005
+ StatCard: StatCardPropsSchema,
1006
+ BalanceCard: BalanceCardPropsSchema,
1007
+ Timeline: TimelinePropsSchema,
1008
+ MessageFeed: MessageFeedPropsSchema,
1009
+ PipelineBoard: PipelineBoardPropsSchema,
1010
+ TransactionPreview: TransactionPreviewPropsSchema
61
1011
  };
62
- var COMPONENT_KEYS = Object.keys(SCHEMA_BY_NAME);
63
- var I18N_TITLE = {
64
- ProgressBar: { en: "Progress", fr: "Progression" },
65
- ConfirmDialog: { en: "Confirmation", fr: "Confirmation" },
66
- TableView: { en: "Data table", fr: "Tableau de donn\xE9es" },
67
- MarkdownRenderer: { en: "Markdown content", fr: "Contenu Markdown" },
68
- TokenDisplayOnceModal: { en: "Token (shown once)", fr: "Jeton (affich\xE9 une fois)" },
69
- StatusBadge: { en: "Status", fr: "Statut" }
1012
+ var MARKDOWN_BY_NAME = {
1013
+ ProgressBar: progressBarToMarkdown,
1014
+ ConfirmDialog: confirmDialogToMarkdown,
1015
+ TableView: tableViewToMarkdown,
1016
+ MarkdownRenderer: markdownRendererToMarkdown,
1017
+ TokenDisplayOnceModal: tokenDisplayOnceModalToMarkdown,
1018
+ StatusBadge: statusBadgeToMarkdown,
1019
+ StatCard: statCardToMarkdown,
1020
+ BalanceCard: balanceCardToMarkdown,
1021
+ Timeline: timelineToMarkdown,
1022
+ MessageFeed: messageFeedToMarkdown,
1023
+ PipelineBoard: pipelineBoardToMarkdown,
1024
+ TransactionPreview: transactionPreviewToMarkdown
70
1025
  };
1026
+ var COMPONENT_KEYS = Object.keys(SCHEMA_BY_NAME);
71
1027
  function escapeHtml(s) {
72
1028
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
73
1029
  }
74
- function fallbackMarkdown(componentName, locale) {
75
- const heading = I18N_TITLE[componentName][locale];
76
- const note = locale === "fr" ? "Rendu Markdown de secours \u2014 composant Mosaic charg\xE9 via MCP UI." : "Markdown fallback \u2014 Mosaic component rendered via MCP UI.";
77
- return `# ${heading}
78
-
79
- ${note}
80
- `;
81
- }
82
1030
  function buildHtml(componentName, props, locale) {
83
1031
  const propsJson = escapeHtml(JSON.stringify(props));
84
- const title = escapeHtml(I18N_TITLE[componentName][locale]);
85
- return `<!DOCTYPE html><html lang="${locale}"><head><meta charset="utf-8"><title>${title}</title></head><body><div id="mosaic-root" data-component="${componentName}" data-props='${propsJson}'></div></body></html>`;
1032
+ const title = escapeHtml(t(`${componentName}.title`, locale));
1033
+ return `<!DOCTYPE html><html lang="${locale === "fr" ? "fr" : "en"}"><head><meta charset="utf-8"><title>${title}</title></head><body><div id="mosaic-root" data-component="${componentName}" data-props='${propsJson}'></div></body></html>`;
86
1034
  }
87
- function createMosaicResource(componentName, props, locale = "en") {
1035
+ function createMosaicResource(componentName, props, locale = "en", options = {}) {
88
1036
  const schema = SCHEMA_BY_NAME[componentName];
89
1037
  if (!schema) {
90
1038
  throw new Error(`createMosaicResource: unknown component '${componentName}'`);
91
1039
  }
92
1040
  const validated = schema.parse(props);
93
- const uri = `ui://mosaic/${componentName.toLowerCase()}`;
94
- const html = buildHtml(componentName, validated, locale);
95
- const fallback = fallbackMarkdown(componentName, locale);
1041
+ const embedded = options.includeSecrets ? validated : splitSecrets(componentName, validated, []).publicProps;
1042
+ const fallback = options.markdownFallback ?? MARKDOWN_BY_NAME[componentName](embedded, locale);
1043
+ return buildResource(componentName, embedded, locale, fallback, options.uri);
1044
+ }
1045
+ function buildResource(componentName, embedded, locale, fallback, uriOverride) {
1046
+ const uri = uriOverride ?? `ui://mosaic/${componentName.toLowerCase()}`;
1047
+ const html = buildHtml(componentName, embedded, locale);
96
1048
  const resource = createUIResource({
97
1049
  uri,
98
1050
  content: { type: "rawHtml", htmlString: html },
@@ -109,8 +1061,116 @@ function createMosaicResource(componentName, props, locale = "en") {
109
1061
  resource.resource.mimeType = MOSAIC_MIME_TYPE;
110
1062
  return resource;
111
1063
  }
1064
+ var MOSAIC_NEVER_SERIALISE = {
1065
+ ProgressBar: [],
1066
+ ConfirmDialog: [],
1067
+ TableView: [],
1068
+ MarkdownRenderer: [],
1069
+ TokenDisplayOnceModal: ["token"],
1070
+ StatusBadge: [],
1071
+ StatCard: [],
1072
+ BalanceCard: [],
1073
+ Timeline: [],
1074
+ MessageFeed: [],
1075
+ PipelineBoard: [],
1076
+ TransactionPreview: []
1077
+ };
1078
+ var MosaicSecretLeakError = class extends Error {
1079
+ field;
1080
+ constructor(field, reason = "would be serialised into content[]") {
1081
+ super(`createMosaicToolResult: the value of "${field}" ${reason}`);
1082
+ this.name = "MosaicSecretLeakError";
1083
+ this.field = field;
1084
+ }
1085
+ };
1086
+ function splitSecrets(name, validated, extraFields) {
1087
+ const publicProps = { ...validated };
1088
+ const secrets = {};
1089
+ for (const f of extraFields) {
1090
+ if (!(f in validated))
1091
+ throw new Error(`createMosaicToolResult: unknown field "${f}" for ${name}`);
1092
+ }
1093
+ for (const field of [...MOSAIC_NEVER_SERIALISE[name], ...extraFields]) {
1094
+ if (field in publicProps) {
1095
+ secrets[field] = publicProps[field];
1096
+ delete publicProps[field];
1097
+ }
1098
+ }
1099
+ if (name === "TableView") {
1100
+ const columns = validated.columns ?? [];
1101
+ const sensitive = columns.filter((c) => c.sensitive).map((c) => c.key);
1102
+ if (sensitive.length > 0) {
1103
+ const cells = {};
1104
+ publicProps.rows = (validated.rows ?? []).map(
1105
+ (row, i) => {
1106
+ const rest = { ...row };
1107
+ for (const k of sensitive) {
1108
+ if (k in rest) {
1109
+ cells[`${i}.${k}`] = rest[k];
1110
+ delete rest[k];
1111
+ }
1112
+ }
1113
+ return rest;
1114
+ }
1115
+ );
1116
+ secrets.cells = cells;
1117
+ }
1118
+ }
1119
+ return { publicProps, secrets };
1120
+ }
1121
+ function fold(text) {
1122
+ return text.normalize("NFKC").toLowerCase();
1123
+ }
1124
+ function secretNeedles(secrets) {
1125
+ const out = [];
1126
+ for (const [field, v] of Object.entries(secrets)) {
1127
+ const values = field === "cells" && v && typeof v === "object" ? Object.values(v) : [v];
1128
+ for (const x of values) {
1129
+ const needle = typeof x === "string" ? x : typeof x === "number" || typeof x === "boolean" ? String(x) : x === null || x === void 0 ? "" : JSON.stringify(x);
1130
+ if (needle.length > 0) out.push({ field, needle });
1131
+ }
1132
+ }
1133
+ return out;
1134
+ }
112
1135
  var MOSAIC_SUPPORTED_COMPONENTS = COMPONENT_KEYS;
1136
+ function createMosaicToolResult(componentName, props, locale = "en", options = {}) {
1137
+ const schema = SCHEMA_BY_NAME[componentName];
1138
+ if (!schema) {
1139
+ throw new Error(`createMosaicResource: unknown component '${componentName}'`);
1140
+ }
1141
+ const validated = schema.parse(props);
1142
+ const { publicProps, secrets } = splitSecrets(
1143
+ componentName,
1144
+ validated,
1145
+ options.neverSerialise ?? []
1146
+ );
1147
+ let markdown;
1148
+ try {
1149
+ markdown = MARKDOWN_BY_NAME[componentName](publicProps, locale);
1150
+ } catch (err) {
1151
+ const declared = Object.keys(secrets).filter((k) => k !== "cells")[0];
1152
+ if (declared && err instanceof ZodError) {
1153
+ throw new MosaicSecretLeakError(
1154
+ declared,
1155
+ "is required by the fallback renderer and cannot be declared secret"
1156
+ );
1157
+ }
1158
+ throw err;
1159
+ }
1160
+ const ui = buildResource(componentName, publicProps, locale, markdown);
1161
+ const content = [
1162
+ { type: "text", text: markdown },
1163
+ ui
1164
+ ];
1165
+ const serialised = fold(JSON.stringify(content));
1166
+ for (const { field, needle } of secretNeedles(secrets)) {
1167
+ if (serialised.includes(fold(needle)) || serialised.includes(fold(JSON.stringify(needle).slice(1, -1)))) {
1168
+ throw new MosaicSecretLeakError(field);
1169
+ }
1170
+ }
1171
+ return Object.keys(secrets).length > 0 ? { content, _meta: { "mosaic/secrets": secrets } } : { content };
1172
+ }
113
1173
 
114
- export { MCP_UI_CAPABILITY_KEY, MOSAIC_MIME_TYPE, MOSAIC_SUPPORTED_COMPONENTS, createMosaicResource };
1174
+ export { MCP_UI_CAPABILITY_KEY, MOSAIC_MIME_TYPE, MOSAIC_NEVER_SERIALISE, MOSAIC_SUPPORTED_COMPONENTS, MosaicSecretLeakError, balanceCardToMarkdown, confirmDialogToMarkdown, createMosaicResource, createMosaicToolResult, markdownRendererToMarkdown, messageFeedToMarkdown, pipelineBoardToMarkdown, progressBarToMarkdown, statCardToMarkdown, statusBadgeToMarkdown, tableViewToMarkdown, timelineToMarkdown, tokenDisplayOnceModalToMarkdown, transactionPreviewToMarkdown };
115
1175
  //# sourceMappingURL=server.js.map
116
1176
  //# sourceMappingURL=server.js.map