@seed-ship/mcp-ui-solid 6.19.1 → 6.20.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 (257) hide show
  1. package/CHANGELOG.md +519 -0
  2. package/README.md +791 -1
  3. package/dist/adapters/connector.cjs +15 -4
  4. package/dist/adapters/connector.cjs.map +1 -1
  5. package/dist/adapters/connector.d.ts +38 -0
  6. package/dist/adapters/connector.d.ts.map +1 -1
  7. package/dist/adapters/connector.js +15 -4
  8. package/dist/adapters/connector.js.map +1 -1
  9. package/dist/adapters/index.d.ts +4 -3
  10. package/dist/adapters/index.d.ts.map +1 -1
  11. package/dist/adapters/macro-run.cjs +25 -13
  12. package/dist/adapters/macro-run.cjs.map +1 -1
  13. package/dist/adapters/macro-run.d.ts +37 -2
  14. package/dist/adapters/macro-run.d.ts.map +1 -1
  15. package/dist/adapters/macro-run.js +25 -13
  16. package/dist/adapters/macro-run.js.map +1 -1
  17. package/dist/adapters.cjs +2 -0
  18. package/dist/adapters.cjs.map +1 -1
  19. package/dist/adapters.js +4 -2
  20. package/dist/components/ActionGroupRenderer.cjs +3 -1
  21. package/dist/components/ActionGroupRenderer.cjs.map +1 -1
  22. package/dist/components/ActionGroupRenderer.d.ts.map +1 -1
  23. package/dist/components/ActionGroupRenderer.js +3 -1
  24. package/dist/components/ActionGroupRenderer.js.map +1 -1
  25. package/dist/components/AgentCard.cjs +11 -8
  26. package/dist/components/AgentCard.cjs.map +1 -1
  27. package/dist/components/AgentCard.d.ts.map +1 -1
  28. package/dist/components/AgentCard.js +11 -8
  29. package/dist/components/AgentCard.js.map +1 -1
  30. package/dist/components/AgentHandoff.cjs +6 -1
  31. package/dist/components/AgentHandoff.cjs.map +1 -1
  32. package/dist/components/AgentHandoff.d.ts.map +1 -1
  33. package/dist/components/AgentHandoff.js +6 -1
  34. package/dist/components/AgentHandoff.js.map +1 -1
  35. package/dist/components/ArtifactRenderer.cjs +25 -6
  36. package/dist/components/ArtifactRenderer.cjs.map +1 -1
  37. package/dist/components/ArtifactRenderer.d.ts.map +1 -1
  38. package/dist/components/ArtifactRenderer.js +25 -6
  39. package/dist/components/ArtifactRenderer.js.map +1 -1
  40. package/dist/components/AutocompleteDropdown.cjs +30 -24
  41. package/dist/components/AutocompleteDropdown.cjs.map +1 -1
  42. package/dist/components/AutocompleteDropdown.d.ts.map +1 -1
  43. package/dist/components/AutocompleteDropdown.js +30 -24
  44. package/dist/components/AutocompleteDropdown.js.map +1 -1
  45. package/dist/components/AutocompleteFormField.cjs +3 -1
  46. package/dist/components/AutocompleteFormField.cjs.map +1 -1
  47. package/dist/components/AutocompleteFormField.d.ts.map +1 -1
  48. package/dist/components/AutocompleteFormField.js +4 -2
  49. package/dist/components/AutocompleteFormField.js.map +1 -1
  50. package/dist/components/BriefingDiff.cjs +45 -39
  51. package/dist/components/BriefingDiff.cjs.map +1 -1
  52. package/dist/components/BriefingDiff.d.ts.map +1 -1
  53. package/dist/components/BriefingDiff.js +45 -39
  54. package/dist/components/BriefingDiff.js.map +1 -1
  55. package/dist/components/CarouselRenderer.cjs +8 -2
  56. package/dist/components/CarouselRenderer.cjs.map +1 -1
  57. package/dist/components/CarouselRenderer.d.ts.map +1 -1
  58. package/dist/components/CarouselRenderer.js +8 -2
  59. package/dist/components/CarouselRenderer.js.map +1 -1
  60. package/dist/components/ChartJSRenderer.cjs +60 -36
  61. package/dist/components/ChartJSRenderer.cjs.map +1 -1
  62. package/dist/components/ChartJSRenderer.d.ts.map +1 -1
  63. package/dist/components/ChartJSRenderer.js +61 -37
  64. package/dist/components/ChartJSRenderer.js.map +1 -1
  65. package/dist/components/ChatPrompt.cjs +15 -9
  66. package/dist/components/ChatPrompt.cjs.map +1 -1
  67. package/dist/components/ChatPrompt.d.ts.map +1 -1
  68. package/dist/components/ChatPrompt.js +15 -9
  69. package/dist/components/ChatPrompt.js.map +1 -1
  70. package/dist/components/CodeBlockRenderer.cjs +34 -16
  71. package/dist/components/CodeBlockRenderer.cjs.map +1 -1
  72. package/dist/components/CodeBlockRenderer.d.ts.map +1 -1
  73. package/dist/components/CodeBlockRenderer.js +34 -16
  74. package/dist/components/CodeBlockRenderer.js.map +1 -1
  75. package/dist/components/DataPreviewSection.cjs +91 -44
  76. package/dist/components/DataPreviewSection.cjs.map +1 -1
  77. package/dist/components/DataPreviewSection.d.ts.map +1 -1
  78. package/dist/components/DataPreviewSection.js +92 -45
  79. package/dist/components/DataPreviewSection.js.map +1 -1
  80. package/dist/components/DegradedFallback.cjs +20 -16
  81. package/dist/components/DegradedFallback.cjs.map +1 -1
  82. package/dist/components/DegradedFallback.d.ts.map +1 -1
  83. package/dist/components/DegradedFallback.js +20 -16
  84. package/dist/components/DegradedFallback.js.map +1 -1
  85. package/dist/components/FooterRenderer.cjs +21 -17
  86. package/dist/components/FooterRenderer.cjs.map +1 -1
  87. package/dist/components/FooterRenderer.d.ts.map +1 -1
  88. package/dist/components/FooterRenderer.js +21 -17
  89. package/dist/components/FooterRenderer.js.map +1 -1
  90. package/dist/components/FormFieldRenderer.cjs +116 -93
  91. package/dist/components/FormFieldRenderer.cjs.map +1 -1
  92. package/dist/components/FormFieldRenderer.d.ts.map +1 -1
  93. package/dist/components/FormFieldRenderer.js +116 -93
  94. package/dist/components/FormFieldRenderer.js.map +1 -1
  95. package/dist/components/FormRenderer.cjs +55 -31
  96. package/dist/components/FormRenderer.cjs.map +1 -1
  97. package/dist/components/FormRenderer.d.ts.map +1 -1
  98. package/dist/components/FormRenderer.js +55 -31
  99. package/dist/components/FormRenderer.js.map +1 -1
  100. package/dist/components/GenerativeUIErrorBoundary.cjs +20 -15
  101. package/dist/components/GenerativeUIErrorBoundary.cjs.map +1 -1
  102. package/dist/components/GenerativeUIErrorBoundary.d.ts.map +1 -1
  103. package/dist/components/GenerativeUIErrorBoundary.js +20 -15
  104. package/dist/components/GenerativeUIErrorBoundary.js.map +1 -1
  105. package/dist/components/GraphRenderer.cjs +56 -33
  106. package/dist/components/GraphRenderer.cjs.map +1 -1
  107. package/dist/components/GraphRenderer.d.ts.map +1 -1
  108. package/dist/components/GraphRenderer.js +56 -33
  109. package/dist/components/GraphRenderer.js.map +1 -1
  110. package/dist/components/ImageGalleryRenderer.cjs +13 -4
  111. package/dist/components/ImageGalleryRenderer.cjs.map +1 -1
  112. package/dist/components/ImageGalleryRenderer.d.ts.map +1 -1
  113. package/dist/components/ImageGalleryRenderer.js +13 -4
  114. package/dist/components/ImageGalleryRenderer.js.map +1 -1
  115. package/dist/components/LightboxOverlay.cjs +16 -8
  116. package/dist/components/LightboxOverlay.cjs.map +1 -1
  117. package/dist/components/LightboxOverlay.d.ts.map +1 -1
  118. package/dist/components/LightboxOverlay.js +17 -9
  119. package/dist/components/LightboxOverlay.js.map +1 -1
  120. package/dist/components/MapRenderer.cjs +59 -29
  121. package/dist/components/MapRenderer.cjs.map +1 -1
  122. package/dist/components/MapRenderer.d.ts +10 -2
  123. package/dist/components/MapRenderer.d.ts.map +1 -1
  124. package/dist/components/MapRenderer.js +60 -30
  125. package/dist/components/MapRenderer.js.map +1 -1
  126. package/dist/components/ModalRenderer.cjs +4 -1
  127. package/dist/components/ModalRenderer.cjs.map +1 -1
  128. package/dist/components/ModalRenderer.d.ts.map +1 -1
  129. package/dist/components/ModalRenderer.js +5 -2
  130. package/dist/components/ModalRenderer.js.map +1 -1
  131. package/dist/components/ScratchpadPanel.cjs +578 -535
  132. package/dist/components/ScratchpadPanel.cjs.map +1 -1
  133. package/dist/components/ScratchpadPanel.d.ts.map +1 -1
  134. package/dist/components/ScratchpadPanel.js +578 -535
  135. package/dist/components/ScratchpadPanel.js.map +1 -1
  136. package/dist/components/StreamingUIRenderer.cjs +92 -28
  137. package/dist/components/StreamingUIRenderer.cjs.map +1 -1
  138. package/dist/components/StreamingUIRenderer.d.ts.map +1 -1
  139. package/dist/components/StreamingUIRenderer.js +92 -28
  140. package/dist/components/StreamingUIRenderer.js.map +1 -1
  141. package/dist/components/UIResourceRenderer.cjs +456 -363
  142. package/dist/components/UIResourceRenderer.cjs.map +1 -1
  143. package/dist/components/UIResourceRenderer.d.ts +21 -0
  144. package/dist/components/UIResourceRenderer.d.ts.map +1 -1
  145. package/dist/components/UIResourceRenderer.js +458 -365
  146. package/dist/components/UIResourceRenderer.js.map +1 -1
  147. package/dist/components/VerifiedText.cjs +39 -20
  148. package/dist/components/VerifiedText.cjs.map +1 -1
  149. package/dist/components/VerifiedText.d.ts +2 -1
  150. package/dist/components/VerifiedText.d.ts.map +1 -1
  151. package/dist/components/VerifiedText.js +39 -20
  152. package/dist/components/VerifiedText.js.map +1 -1
  153. package/dist/components/VideoRenderer.cjs +10 -5
  154. package/dist/components/VideoRenderer.cjs.map +1 -1
  155. package/dist/components/VideoRenderer.d.ts.map +1 -1
  156. package/dist/components/VideoRenderer.js +10 -5
  157. package/dist/components/VideoRenderer.js.map +1 -1
  158. package/dist/components/chart-data-table.cjs +38 -17
  159. package/dist/components/chart-data-table.cjs.map +1 -1
  160. package/dist/components/chart-data-table.d.ts +30 -1
  161. package/dist/components/chart-data-table.d.ts.map +1 -1
  162. package/dist/components/chart-data-table.js +38 -17
  163. package/dist/components/chart-data-table.js.map +1 -1
  164. package/dist/context/MCPActionContext.cjs +3 -1
  165. package/dist/context/MCPActionContext.cjs.map +1 -1
  166. package/dist/context/MCPActionContext.d.ts.map +1 -1
  167. package/dist/context/MCPActionContext.js +3 -1
  168. package/dist/context/MCPActionContext.js.map +1 -1
  169. package/dist/context/MCPUIStringsContext.cjs +285 -2
  170. package/dist/context/MCPUIStringsContext.cjs.map +1 -1
  171. package/dist/context/MCPUIStringsContext.d.ts +600 -3
  172. package/dist/context/MCPUIStringsContext.d.ts.map +1 -1
  173. package/dist/context/MCPUIStringsContext.js +285 -2
  174. package/dist/context/MCPUIStringsContext.js.map +1 -1
  175. package/dist/hooks/index.d.ts +2 -2
  176. package/dist/hooks/index.d.ts.map +1 -1
  177. package/dist/hooks/useStreamingUI.cjs +28 -10
  178. package/dist/hooks/useStreamingUI.cjs.map +1 -1
  179. package/dist/hooks/useStreamingUI.d.ts +37 -0
  180. package/dist/hooks/useStreamingUI.d.ts.map +1 -1
  181. package/dist/hooks/useStreamingUI.js +28 -10
  182. package/dist/hooks/useStreamingUI.js.map +1 -1
  183. package/dist/hooks.cjs +1 -0
  184. package/dist/hooks.cjs.map +1 -1
  185. package/dist/hooks.js +2 -1
  186. package/dist/index.cjs +23 -8
  187. package/dist/index.cjs.map +1 -1
  188. package/dist/index.d.cts +9 -3
  189. package/dist/index.d.ts +9 -3
  190. package/dist/index.d.ts.map +1 -1
  191. package/dist/index.js +18 -3
  192. package/dist/index.js.map +1 -1
  193. package/dist/services/validation.cjs +41 -16
  194. package/dist/services/validation.cjs.map +1 -1
  195. package/dist/services/validation.d.ts +47 -2
  196. package/dist/services/validation.d.ts.map +1 -1
  197. package/dist/services/validation.js +41 -16
  198. package/dist/services/validation.js.map +1 -1
  199. package/dist/utils/degraded-projections.cjs +37 -12
  200. package/dist/utils/degraded-projections.cjs.map +1 -1
  201. package/dist/utils/degraded-projections.d.ts +39 -3
  202. package/dist/utils/degraded-projections.d.ts.map +1 -1
  203. package/dist/utils/degraded-projections.js +37 -12
  204. package/dist/utils/degraded-projections.js.map +1 -1
  205. package/dist/utils/format-string.cjs +10 -0
  206. package/dist/utils/format-string.cjs.map +1 -0
  207. package/dist/utils/format-string.d.ts +26 -0
  208. package/dist/utils/format-string.d.ts.map +1 -0
  209. package/dist/utils/format-string.js +10 -0
  210. package/dist/utils/format-string.js.map +1 -0
  211. package/dist/validation.cjs +3 -0
  212. package/dist/validation.cjs.map +1 -1
  213. package/dist/validation.d.cts +2 -1
  214. package/dist/validation.d.ts +2 -1
  215. package/dist/validation.d.ts.map +1 -1
  216. package/dist/validation.js +4 -1
  217. package/package.json +1 -1
  218. package/src/adapters/connector.ts +58 -4
  219. package/src/adapters/index.ts +12 -2
  220. package/src/adapters/macro-run.ts +71 -11
  221. package/src/components/ActionGroupRenderer.tsx +3 -1
  222. package/src/components/AgentCard.tsx +27 -9
  223. package/src/components/AgentHandoff.tsx +4 -1
  224. package/src/components/ArtifactRenderer.tsx +17 -5
  225. package/src/components/AutocompleteDropdown.tsx +8 -6
  226. package/src/components/AutocompleteFormField.tsx +5 -1
  227. package/src/components/BriefingDiff.tsx +11 -3
  228. package/src/components/CarouselRenderer.tsx +4 -2
  229. package/src/components/ChartJSRenderer.tsx +18 -9
  230. package/src/components/ChatPrompt.tsx +13 -8
  231. package/src/components/CodeBlockRenderer.tsx +12 -10
  232. package/src/components/DataPreviewSection.tsx +92 -26
  233. package/src/components/DegradedFallback.tsx +4 -2
  234. package/src/components/FooterRenderer.tsx +3 -1
  235. package/src/components/FormFieldRenderer.tsx +34 -19
  236. package/src/components/FormRenderer.tsx +38 -10
  237. package/src/components/GenerativeUIErrorBoundary.tsx +8 -3
  238. package/src/components/GraphRenderer.tsx +31 -16
  239. package/src/components/ImageGalleryRenderer.tsx +8 -4
  240. package/src/components/LightboxOverlay.tsx +6 -4
  241. package/src/components/MapRenderer.tsx +57 -20
  242. package/src/components/ModalRenderer.tsx +3 -1
  243. package/src/components/ScratchpadPanel.tsx +95 -44
  244. package/src/components/StreamingUIRenderer.tsx +41 -11
  245. package/src/components/UIResourceRenderer.tsx +145 -63
  246. package/src/components/VerifiedText.tsx +19 -9
  247. package/src/components/VideoRenderer.tsx +6 -4
  248. package/src/components/chart-data-table.ts +68 -14
  249. package/src/context/MCPActionContext.tsx +4 -1
  250. package/src/context/MCPUIStringsContext.tsx +1004 -1
  251. package/src/hooks/index.ts +2 -1
  252. package/src/hooks/useStreamingUI.ts +64 -10
  253. package/src/index.ts +23 -0
  254. package/src/services/validation.ts +93 -16
  255. package/src/utils/degraded-projections.ts +75 -12
  256. package/src/utils/format-string.ts +33 -0
  257. package/src/validation.ts +5 -0
@@ -1,3 +1,21 @@
1
+ import { formatMCPUIString } from "./format-string.js";
2
+ const DEGRADED_PROJECTION_LABELS = {
3
+ source: "Source",
4
+ target: "Target",
5
+ label: "Label",
6
+ node: "Node",
7
+ type: "Type",
8
+ lat: "Lat",
9
+ lng: "Lng",
10
+ info: "Info",
11
+ marker: "marker",
12
+ feature: "feature",
13
+ series: "Series {n}"
14
+ };
15
+ const withLabels = (labels) => ({
16
+ ...DEGRADED_PROJECTION_LABELS,
17
+ ...labels
18
+ });
1
19
  const MAX_PROJECTED_ROWS = 200;
2
20
  function cell(value) {
3
21
  if (value == null) return "";
@@ -10,11 +28,12 @@ function cell(value) {
10
28
  }
11
29
  return String(value);
12
30
  }
13
- function graphToDegradedTable(params) {
31
+ function graphToDegradedTable(params, labels) {
32
+ const l = withLabels(labels);
14
33
  const edges = params.edges ?? [];
15
34
  if (edges.length > 0) {
16
35
  return {
17
- columns: ["Source", "Target", "Label"],
36
+ columns: [l.source, l.target, l.label],
18
37
  rows: edges.slice(0, MAX_PROJECTED_ROWS).map((e) => {
19
38
  const label = [e.weight != null ? String(e.weight) : "", e.label ?? ""].filter(Boolean).join(" · ");
20
39
  return [cell(e.source), cell(e.target), label];
@@ -23,7 +42,7 @@ function graphToDegradedTable(params) {
23
42
  }
24
43
  const nodes = params.nodes ?? [];
25
44
  return {
26
- columns: ["Node", "Label"],
45
+ columns: [l.node, l.label],
27
46
  rows: nodes.slice(0, MAX_PROJECTED_ROWS).map((n) => [cell(n.id), cell(n.label ?? n.id)])
28
47
  };
29
48
  }
@@ -35,13 +54,14 @@ function firstLngLat(coords) {
35
54
  }
36
55
  return null;
37
56
  }
38
- function mapToDegradedTable(params) {
57
+ function mapToDegradedTable(params, labels) {
39
58
  var _a, _b, _c, _d;
59
+ const l = withLabels(labels);
40
60
  const rows = [];
41
61
  for (const m of params.markers ?? []) {
42
62
  const lat = Array.isArray(m.position) ? m.position[0] : (_a = m.position) == null ? void 0 : _a.lat;
43
63
  const lng = Array.isArray(m.position) ? m.position[1] : (_b = m.position) == null ? void 0 : _b.lng;
44
- rows.push(["marker", cell(lat), cell(lng), cell(m.tooltip ?? m.popup ?? "")]);
64
+ rows.push([l.marker, cell(lat), cell(lng), cell(m.tooltip ?? m.popup ?? "")]);
45
65
  }
46
66
  const fc = params.geojson;
47
67
  const features = Array.isArray(fc == null ? void 0 : fc.features) ? fc.features : [];
@@ -50,29 +70,33 @@ function mapToDegradedTable(params) {
50
70
  const props = f.properties ?? {};
51
71
  const propSummary = Object.keys(props).slice(0, 3).map((k) => `${k}=${cell(props[k])}`).join(", ");
52
72
  rows.push([
53
- cell(((_d = f.geometry) == null ? void 0 : _d.type) ?? "feature"),
73
+ cell(((_d = f.geometry) == null ? void 0 : _d.type) ?? l.feature),
54
74
  ll ? cell(ll[1]) : "",
55
75
  ll ? cell(ll[0]) : "",
56
76
  propSummary
57
77
  ]);
58
78
  }
59
79
  return {
60
- columns: ["Type", "Lat", "Lng", "Info"],
80
+ columns: [l.type, l.lat, l.lng, l.info],
61
81
  rows: rows.slice(0, MAX_PROJECTED_ROWS)
62
82
  };
63
83
  }
64
- function chartToDegradedTable(params) {
84
+ function chartToDegradedTable(params, labels) {
65
85
  var _a, _b;
86
+ const l = withLabels(labels);
66
87
  const datasets = ((_a = params.data) == null ? void 0 : _a.datasets) ?? [];
67
- const labels = ((_b = params.data) == null ? void 0 : _b.labels) ?? [];
68
- const rowCount = Math.max(labels.length, ...datasets.map((d) => {
88
+ const dataLabels = ((_b = params.data) == null ? void 0 : _b.labels) ?? [];
89
+ const rowCount = Math.max(dataLabels.length, ...datasets.map((d) => {
69
90
  var _a2;
70
91
  return ((_a2 = d.data) == null ? void 0 : _a2.length) ?? 0;
71
92
  }), 0);
72
- const columns = ["", ...datasets.map((d, i) => d.label ?? `Series ${i + 1}`)];
93
+ const columns = [
94
+ "",
95
+ ...datasets.map((d, i) => d.label ?? formatMCPUIString(l.series, { n: i + 1 }))
96
+ ];
73
97
  const rows = [];
74
98
  for (let r = 0; r < Math.min(rowCount, MAX_PROJECTED_ROWS); r++) {
75
- rows.push([cell(labels[r] ?? r + 1), ...datasets.map((d) => {
99
+ rows.push([cell(dataLabels[r] ?? r + 1), ...datasets.map((d) => {
76
100
  var _a2;
77
101
  return cell((_a2 = d.data) == null ? void 0 : _a2[r]);
78
102
  })]);
@@ -80,6 +104,7 @@ function chartToDegradedTable(params) {
80
104
  return { columns, rows };
81
105
  }
82
106
  export {
107
+ DEGRADED_PROJECTION_LABELS,
83
108
  chartToDegradedTable,
84
109
  graphToDegradedTable,
85
110
  mapToDegradedTable
@@ -1 +1 @@
1
- {"version":3,"file":"degraded-projections.js","sources":["../../src/utils/degraded-projections.ts"],"sourcesContent":["/**\n * Degraded-fallback projections (audit 2026-05-30, P2.5).\n *\n * Pure functions that turn a heavy renderer's params into a flat\n * `{ columns, rows }` table for `<DegradedFallback>` — the middle rung of\n * the fallback ladder shown when the native render (G6 / Leaflet / Chart.js)\n * is unavailable or throws. No peer deps, no side effects, fully testable.\n *\n * These are best-effort views: they surface the underlying data so the user\n * isn't left with a blank space, not faithful reproductions of the chart/\n * map/graph.\n */\n\nexport interface DegradedTable {\n columns: string[];\n rows: Array<Array<string | number>>;\n}\n\nconst MAX_PROJECTED_ROWS = 200;\n\n/** Compact a value to a single table cell string. */\nfunction cell(value: unknown): string {\n if (value == null) return '';\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n return String(value);\n}\n\n// ─── Graph ───────────────────────────────────────────────────────────────\n\n/**\n * Graph → edge table when edges exist (Source / Target / Label), else a\n * node list (Node / Label). The graph renderer can therefore degrade to a\n * readable relationship listing instead of a blank canvas.\n */\nexport function graphToDegradedTable(params: {\n nodes?: Array<{ id: string; label?: string }>;\n edges?: Array<{ source: string; target: string; label?: string; weight?: number }>;\n}): DegradedTable {\n const edges = params.edges ?? [];\n if (edges.length > 0) {\n return {\n columns: ['Source', 'Target', 'Label'],\n rows: edges.slice(0, MAX_PROJECTED_ROWS).map((e) => {\n const label = [e.weight != null ? String(e.weight) : '', e.label ?? '']\n .filter(Boolean)\n .join(' · ');\n return [cell(e.source), cell(e.target), label];\n }),\n };\n }\n const nodes = params.nodes ?? [];\n return {\n columns: ['Node', 'Label'],\n rows: nodes.slice(0, MAX_PROJECTED_ROWS).map((n) => [cell(n.id), cell(n.label ?? n.id)]),\n };\n}\n\n// ─── Map ───────────────────────────────────────────────────────────────────\n\ninterface GeoJSONLikeFeature {\n geometry?: { type?: string; coordinates?: unknown } | null;\n properties?: Record<string, unknown> | null;\n}\n\n/** Pull a representative `[lng, lat]` pair out of a geometry's coordinates. */\nfunction firstLngLat(coords: unknown): [number, number] | null {\n let c: unknown = coords;\n // Descend nested arrays until we reach a [number, number, ...] position.\n while (Array.isArray(c) && Array.isArray(c[0])) c = c[0];\n if (Array.isArray(c) && typeof c[0] === 'number' && typeof c[1] === 'number') {\n return [c[0], c[1]];\n }\n return null;\n}\n\n/**\n * Map → a coordinate table. Markers become Lat/Lng/Label rows; GeoJSON\n * features become Type / Lat / Lng (+ a compact properties summary). So a\n * map that can't paint still lists where its points are.\n */\nexport function mapToDegradedTable(params: {\n markers?: Array<{\n position: [number, number] | { lat: number; lng: number };\n tooltip?: string;\n popup?: string;\n }>;\n geojson?: unknown;\n}): DegradedTable {\n const rows: Array<Array<string | number>> = [];\n\n for (const m of params.markers ?? []) {\n const lat = Array.isArray(m.position) ? m.position[0] : m.position?.lat;\n const lng = Array.isArray(m.position) ? m.position[1] : m.position?.lng;\n rows.push(['marker', cell(lat), cell(lng), cell(m.tooltip ?? m.popup ?? '')]);\n }\n\n const fc = params.geojson as { features?: GeoJSONLikeFeature[] } | undefined;\n const features = Array.isArray(fc?.features) ? fc!.features : [];\n for (const f of features) {\n const ll = firstLngLat(f.geometry?.coordinates);\n const props = f.properties ?? {};\n const propSummary = Object.keys(props)\n .slice(0, 3)\n .map((k) => `${k}=${cell(props[k])}`)\n .join(', ');\n rows.push([\n cell(f.geometry?.type ?? 'feature'),\n ll ? cell(ll[1]) : '',\n ll ? cell(ll[0]) : '',\n propSummary,\n ]);\n }\n\n return {\n columns: ['Type', 'Lat', 'Lng', 'Info'],\n rows: rows.slice(0, MAX_PROJECTED_ROWS),\n };\n}\n\n// ─── Chart ───────────────────────────────────────────────────────────────\n\n/**\n * Chart → a series table: one row per label, one column per dataset. So a\n * chart that can't draw still shows its numbers. Point/object data (scatter,\n * bubble, time series) is stringified per cell.\n */\nexport function chartToDegradedTable(params: {\n data?: {\n labels?: Array<string | number>;\n datasets?: Array<{ label?: string; data?: unknown[] }>;\n };\n}): DegradedTable {\n const datasets = params.data?.datasets ?? [];\n const labels = params.data?.labels ?? [];\n const rowCount = Math.max(labels.length, ...datasets.map((d) => d.data?.length ?? 0), 0);\n\n const columns = ['', ...datasets.map((d, i) => d.label ?? `Series ${i + 1}`)];\n const rows: Array<Array<string | number>> = [];\n for (let r = 0; r < Math.min(rowCount, MAX_PROJECTED_ROWS); r++) {\n rows.push([cell(labels[r] ?? r + 1), ...datasets.map((d) => cell(d.data?.[r]))]);\n }\n return { columns, rows };\n}\n"],"names":["_a"],"mappings":"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"}
1
+ {"version":3,"file":"degraded-projections.js","sources":["../../src/utils/degraded-projections.ts"],"sourcesContent":["/**\n * Degraded-fallback projections (audit 2026-05-30, P2.5).\n *\n * Pure functions that turn a heavy renderer's params into a flat\n * `{ columns, rows }` table for `<DegradedFallback>` — the middle rung of\n * the fallback ladder shown when the native render (G6 / Leaflet / Chart.js)\n * is unavailable or throws. No peer deps, no side effects, fully testable.\n *\n * These are best-effort views: they surface the underlying data so the user\n * isn't left with a blank space, not faithful reproductions of the chart/\n * map/graph.\n */\n\nimport { formatMCPUIString } from './format-string';\n\n/**\n * Column headers and series names of the degraded tables.\n *\n * The projections are pure helpers with no access to `MCPUIStrings`, so the\n * wording is injected: each function takes an optional trailing `labels`\n * partial, and the renderers feed it from `useMCPUIStrings()`. Left out, the\n * English defaults below apply — the pre-v6.20.0 behaviour.\n *\n * @since v6.20.0\n */\nexport interface DegradedProjectionLabels {\n /** Graph edge table — source column. */\n source: string;\n /** Graph edge table — target column. */\n target: string;\n /** Graph edge / node table — label column. */\n label: string;\n /** Graph node table — node id column. */\n node: string;\n /** Map table — feature type column. */\n type: string;\n /** Map table — latitude column. */\n lat: string;\n /** Map table — longitude column. */\n lng: string;\n /** Map table — property summary column. */\n info: string;\n /** Map table — `Type` cell of a marker row (v6.20.0, 6th pass). */\n marker: string;\n /** Map table — `Type` cell of a GeoJSON feature without a geometry type (v6.20.0). */\n feature: string;\n /** Chart table — fallback dataset name. Template — `{n}`. */\n series: string;\n}\n\n/** English defaults for {@link DegradedProjectionLabels}. */\nexport const DEGRADED_PROJECTION_LABELS: DegradedProjectionLabels = {\n source: 'Source',\n target: 'Target',\n label: 'Label',\n node: 'Node',\n type: 'Type',\n lat: 'Lat',\n lng: 'Lng',\n info: 'Info',\n marker: 'marker',\n feature: 'feature',\n series: 'Series {n}',\n};\n\nconst withLabels = (labels?: Partial<DegradedProjectionLabels>): DegradedProjectionLabels => ({\n ...DEGRADED_PROJECTION_LABELS,\n ...labels,\n});\n\nexport interface DegradedTable {\n columns: string[];\n rows: Array<Array<string | number>>;\n}\n\nconst MAX_PROJECTED_ROWS = 200;\n\n/** Compact a value to a single table cell string. */\nfunction cell(value: unknown): string {\n if (value == null) return '';\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n return String(value);\n}\n\n// ─── Graph ───────────────────────────────────────────────────────────────\n\n/**\n * Graph → edge table when edges exist (Source / Target / Label), else a\n * node list (Node / Label). The graph renderer can therefore degrade to a\n * readable relationship listing instead of a blank canvas.\n */\nexport function graphToDegradedTable(params: {\n nodes?: Array<{ id: string; label?: string }>;\n edges?: Array<{ source: string; target: string; label?: string; weight?: number }>;\n}, labels?: Partial<DegradedProjectionLabels>): DegradedTable {\n const l = withLabels(labels);\n const edges = params.edges ?? [];\n if (edges.length > 0) {\n return {\n columns: [l.source, l.target, l.label],\n rows: edges.slice(0, MAX_PROJECTED_ROWS).map((e) => {\n const label = [e.weight != null ? String(e.weight) : '', e.label ?? '']\n .filter(Boolean)\n .join(' · ');\n return [cell(e.source), cell(e.target), label];\n }),\n };\n }\n const nodes = params.nodes ?? [];\n return {\n columns: [l.node, l.label],\n rows: nodes.slice(0, MAX_PROJECTED_ROWS).map((n) => [cell(n.id), cell(n.label ?? n.id)]),\n };\n}\n\n// ─── Map ───────────────────────────────────────────────────────────────────\n\ninterface GeoJSONLikeFeature {\n geometry?: { type?: string; coordinates?: unknown } | null;\n properties?: Record<string, unknown> | null;\n}\n\n/** Pull a representative `[lng, lat]` pair out of a geometry's coordinates. */\nfunction firstLngLat(coords: unknown): [number, number] | null {\n let c: unknown = coords;\n // Descend nested arrays until we reach a [number, number, ...] position.\n while (Array.isArray(c) && Array.isArray(c[0])) c = c[0];\n if (Array.isArray(c) && typeof c[0] === 'number' && typeof c[1] === 'number') {\n return [c[0], c[1]];\n }\n return null;\n}\n\n/**\n * Map → a coordinate table. Markers become Lat/Lng/Label rows; GeoJSON\n * features become Type / Lat / Lng (+ a compact properties summary). So a\n * map that can't paint still lists where its points are.\n */\nexport function mapToDegradedTable(params: {\n markers?: Array<{\n position: [number, number] | { lat: number; lng: number };\n tooltip?: string;\n popup?: string;\n }>;\n geojson?: unknown;\n}, labels?: Partial<DegradedProjectionLabels>): DegradedTable {\n const l = withLabels(labels);\n const rows: Array<Array<string | number>> = [];\n\n for (const m of params.markers ?? []) {\n const lat = Array.isArray(m.position) ? m.position[0] : m.position?.lat;\n const lng = Array.isArray(m.position) ? m.position[1] : m.position?.lng;\n rows.push([l.marker, cell(lat), cell(lng), cell(m.tooltip ?? m.popup ?? '')]);\n }\n\n const fc = params.geojson as { features?: GeoJSONLikeFeature[] } | undefined;\n const features = Array.isArray(fc?.features) ? fc!.features : [];\n for (const f of features) {\n const ll = firstLngLat(f.geometry?.coordinates);\n const props = f.properties ?? {};\n const propSummary = Object.keys(props)\n .slice(0, 3)\n .map((k) => `${k}=${cell(props[k])}`)\n .join(', ');\n rows.push([\n cell(f.geometry?.type ?? l.feature),\n ll ? cell(ll[1]) : '',\n ll ? cell(ll[0]) : '',\n propSummary,\n ]);\n }\n\n return {\n columns: [l.type, l.lat, l.lng, l.info],\n rows: rows.slice(0, MAX_PROJECTED_ROWS),\n };\n}\n\n// ─── Chart ───────────────────────────────────────────────────────────────\n\n/**\n * Chart → a series table: one row per label, one column per dataset. So a\n * chart that can't draw still shows its numbers. Point/object data (scatter,\n * bubble, time series) is stringified per cell.\n */\nexport function chartToDegradedTable(params: {\n data?: {\n labels?: Array<string | number>;\n datasets?: Array<{ label?: string; data?: unknown[] }>;\n };\n}, labels?: Partial<DegradedProjectionLabels>): DegradedTable {\n const l = withLabels(labels);\n const datasets = params.data?.datasets ?? [];\n const dataLabels = params.data?.labels ?? [];\n const rowCount = Math.max(dataLabels.length, ...datasets.map((d) => d.data?.length ?? 0), 0);\n\n const columns = [\n '',\n ...datasets.map((d, i) => d.label ?? formatMCPUIString(l.series, { n: i + 1 })),\n ];\n const rows: Array<Array<string | number>> = [];\n for (let r = 0; r < Math.min(rowCount, MAX_PROJECTED_ROWS); r++) {\n rows.push([cell(dataLabels[r] ?? r + 1), ...datasets.map((d) => cell(d.data?.[r]))]);\n }\n return { columns, rows };\n}\n"],"names":["_a"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ function formatMCPUIString(template, vars) {
4
+ return template.replace(
5
+ /\{(\w+)\}/g,
6
+ (match, name) => Object.prototype.hasOwnProperty.call(vars, name) ? String(vars[name]) : match
7
+ );
8
+ }
9
+ exports.formatMCPUIString = formatMCPUIString;
10
+ //# sourceMappingURL=format-string.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-string.cjs","sources":["../../src/utils/format-string.ts"],"sourcesContent":["/**\n * `formatMCPUIString` — the chrome-string template helper, runtime-free.\n *\n * @since v6.20.0 (extracted from `MCPUIStringsContext` so the pure adapters\n * under `src/adapters` can interpolate their own message templates without\n * importing `solid-js`). `MCPUIStringsContext` re-exports it, so every\n * existing import path — including the root barrel — keeps working.\n *\n * This module imports nothing. It must stay that way: `src/adapters/*` is\n * published as a dedicated subpath that never pulls in the renderer.\n */\n\n/**\n * Substitutes `{name}` placeholders in a chrome string template.\n *\n * Only the keys present in `vars` are replaced; an unknown placeholder is\n * left verbatim so a mistyped or locale-specific template degrades to\n * visible text rather than to `undefined`.\n *\n * @example\n * ```ts\n * formatMCPUIString('Sort by {column}', { column: 'Revenue' }) // 'Sort by Revenue'\n * formatMCPUIString('Export CSV ({count} rows)', { count: 42 }) // 'Export CSV (42 rows)'\n * ```\n */\nexport function formatMCPUIString(\n template: string,\n vars: Record<string, string | number>\n): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, name: string) =>\n Object.prototype.hasOwnProperty.call(vars, name) ? String(vars[name]) : match\n )\n}\n"],"names":[],"mappings":";;AAyBO,SAAS,kBACd,UACA,MACQ;AACR,SAAO,SAAS;AAAA,IAAQ;AAAA,IAAc,CAAC,OAAO,SAC5C,OAAO,UAAU,eAAe,KAAK,MAAM,IAAI,IAAI,OAAO,KAAK,IAAI,CAAC,IAAI;AAAA,EAAA;AAE5E;;"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * `formatMCPUIString` — the chrome-string template helper, runtime-free.
3
+ *
4
+ * @since v6.20.0 (extracted from `MCPUIStringsContext` so the pure adapters
5
+ * under `src/adapters` can interpolate their own message templates without
6
+ * importing `solid-js`). `MCPUIStringsContext` re-exports it, so every
7
+ * existing import path — including the root barrel — keeps working.
8
+ *
9
+ * This module imports nothing. It must stay that way: `src/adapters/*` is
10
+ * published as a dedicated subpath that never pulls in the renderer.
11
+ */
12
+ /**
13
+ * Substitutes `{name}` placeholders in a chrome string template.
14
+ *
15
+ * Only the keys present in `vars` are replaced; an unknown placeholder is
16
+ * left verbatim so a mistyped or locale-specific template degrades to
17
+ * visible text rather than to `undefined`.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * formatMCPUIString('Sort by {column}', { column: 'Revenue' }) // 'Sort by Revenue'
22
+ * formatMCPUIString('Export CSV ({count} rows)', { count: 42 }) // 'Export CSV (42 rows)'
23
+ * ```
24
+ */
25
+ export declare function formatMCPUIString(template: string, vars: Record<string, string | number>): string;
26
+ //# sourceMappingURL=format-string.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-string.d.ts","sourceRoot":"","sources":["../../src/utils/format-string.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GACpC,MAAM,CAIR"}
@@ -0,0 +1,10 @@
1
+ function formatMCPUIString(template, vars) {
2
+ return template.replace(
3
+ /\{(\w+)\}/g,
4
+ (match, name) => Object.prototype.hasOwnProperty.call(vars, name) ? String(vars[name]) : match
5
+ );
6
+ }
7
+ export {
8
+ formatMCPUIString
9
+ };
10
+ //# sourceMappingURL=format-string.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-string.js","sources":["../../src/utils/format-string.ts"],"sourcesContent":["/**\n * `formatMCPUIString` — the chrome-string template helper, runtime-free.\n *\n * @since v6.20.0 (extracted from `MCPUIStringsContext` so the pure adapters\n * under `src/adapters` can interpolate their own message templates without\n * importing `solid-js`). `MCPUIStringsContext` re-exports it, so every\n * existing import path — including the root barrel — keeps working.\n *\n * This module imports nothing. It must stay that way: `src/adapters/*` is\n * published as a dedicated subpath that never pulls in the renderer.\n */\n\n/**\n * Substitutes `{name}` placeholders in a chrome string template.\n *\n * Only the keys present in `vars` are replaced; an unknown placeholder is\n * left verbatim so a mistyped or locale-specific template degrades to\n * visible text rather than to `undefined`.\n *\n * @example\n * ```ts\n * formatMCPUIString('Sort by {column}', { column: 'Revenue' }) // 'Sort by Revenue'\n * formatMCPUIString('Export CSV ({count} rows)', { count: 42 }) // 'Export CSV (42 rows)'\n * ```\n */\nexport function formatMCPUIString(\n template: string,\n vars: Record<string, string | number>\n): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, name: string) =>\n Object.prototype.hasOwnProperty.call(vars, name) ? String(vars[name]) : match\n )\n}\n"],"names":[],"mappings":"AAyBO,SAAS,kBACd,UACA,MACQ;AACR,SAAO,SAAS;AAAA,IAAQ;AAAA,IAAc,CAAC,OAAO,SAC5C,OAAO,UAAU,eAAe,KAAK,MAAM,IAAI,IAAI,OAAO,KAAK,IAAI,CAAC,IAAI;AAAA,EAAA;AAE5E;"}
@@ -2,9 +2,12 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const validation = require("./services/validation.cjs");
4
4
  exports.DEFAULT_RESOURCE_LIMITS = validation.DEFAULT_RESOURCE_LIMITS;
5
+ exports.DEFAULT_VALIDATION_MESSAGES = validation.DEFAULT_VALIDATION_MESSAGES;
5
6
  exports.sanitizeString = validation.sanitizeString;
6
7
  exports.validateChartComponent = validation.validateChartComponent;
7
8
  exports.validateComponent = validation.validateComponent;
9
+ exports.validateFieldValue = validation.validateFieldValue;
10
+ exports.validateFormData = validation.validateFormData;
8
11
  exports.validateGridPosition = validation.validateGridPosition;
9
12
  exports.validateIframeDomain = validation.validateIframeDomain;
10
13
  exports.validateLayout = validation.validateLayout;
@@ -1 +1 @@
1
- {"version":3,"file":"validation.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
1
+ {"version":3,"file":"validation.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;"}
@@ -9,6 +9,7 @@
9
9
  * import { validateLayout } from '@seed-ship/mcp-ui-solid/validation'
10
10
  * ```
11
11
  */
12
- export { validateComponent, validateLayout, validateGridPosition, validateChartComponent, validateTableComponent, validatePayloadSize, validateIframeDomain, sanitizeString, DEFAULT_RESOURCE_LIMITS, } from './services/validation';
12
+ export { validateComponent, validateLayout, validateGridPosition, validateChartComponent, validateTableComponent, validatePayloadSize, validateIframeDomain, sanitizeString, DEFAULT_RESOURCE_LIMITS, validateFieldValue, validateFormData, DEFAULT_VALIDATION_MESSAGES, } from './services/validation';
13
+ export type { FormValidationMessages } from './services/validation';
13
14
  export type { UIComponent, UILayout, GridPosition, ComponentType, ChartComponentParams, TableComponentParams, MetricComponentParams, TextComponentParams, ValidationResult, ResourceLimits, } from './types';
14
15
  //# sourceMappingURL=validation.d.ts.map
@@ -9,6 +9,7 @@
9
9
  * import { validateLayout } from '@seed-ship/mcp-ui-solid/validation'
10
10
  * ```
11
11
  */
12
- export { validateComponent, validateLayout, validateGridPosition, validateChartComponent, validateTableComponent, validatePayloadSize, validateIframeDomain, sanitizeString, DEFAULT_RESOURCE_LIMITS, } from './services/validation';
12
+ export { validateComponent, validateLayout, validateGridPosition, validateChartComponent, validateTableComponent, validatePayloadSize, validateIframeDomain, sanitizeString, DEFAULT_RESOURCE_LIMITS, validateFieldValue, validateFormData, DEFAULT_VALIDATION_MESSAGES, } from './services/validation';
13
+ export type { FormValidationMessages } from './services/validation';
13
14
  export type { UIComponent, UILayout, GridPosition, ComponentType, ChartComponentParams, TableComponentParams, MetricComponentParams, TextComponentParams, ValidationResult, ResourceLimits, } from './types';
14
15
  //# sourceMappingURL=validation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,uBAAuB,GACxB,MAAM,uBAAuB,CAAA;AAG9B,YAAY,EACV,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,GACf,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,uBAAuB,EAEvB,kBAAkB,EAClB,gBAAgB,EAChB,2BAA2B,GAC5B,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAGnE,YAAY,EACV,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,GACf,MAAM,SAAS,CAAA"}
@@ -1,9 +1,12 @@
1
- import { DEFAULT_RESOURCE_LIMITS, sanitizeString, validateChartComponent, validateComponent, validateGridPosition, validateIframeDomain, validateLayout, validatePayloadSize, validateTableComponent } from "./services/validation.js";
1
+ import { DEFAULT_RESOURCE_LIMITS, DEFAULT_VALIDATION_MESSAGES, sanitizeString, validateChartComponent, validateComponent, validateFieldValue, validateFormData, validateGridPosition, validateIframeDomain, validateLayout, validatePayloadSize, validateTableComponent } from "./services/validation.js";
2
2
  export {
3
3
  DEFAULT_RESOURCE_LIMITS,
4
+ DEFAULT_VALIDATION_MESSAGES,
4
5
  sanitizeString,
5
6
  validateChartComponent,
6
7
  validateComponent,
8
+ validateFieldValue,
9
+ validateFormData,
7
10
  validateGridPosition,
8
11
  validateIframeDomain,
9
12
  validateLayout,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seed-ship/mcp-ui-solid",
3
- "version": "6.19.1",
3
+ "version": "6.20.0",
4
4
  "description": "SolidJS components for rendering MCP-generated UI resources",
5
5
  "type": "module",
6
6
  "files": [
@@ -29,6 +29,7 @@ import {
29
29
  type ConnectorAction,
30
30
  } from '@seed-ship/mcp-ui-spec'
31
31
  import { z } from 'zod'
32
+ import { formatMCPUIString } from '../utils/format-string'
32
33
 
33
34
  // ─────────────────────────────────────────────────────────────
34
35
  // connectorActionsToActionGroup
@@ -74,11 +75,57 @@ export function connectorActionsToActionGroup(
74
75
  // connectorResultToUILayout
75
76
  // ─────────────────────────────────────────────────────────────
76
77
 
78
+ /**
79
+ * The visible wording of the two degraded states (R2).
80
+ *
81
+ * These paragraphs are rendered as `text` components, so unlike the payload
82
+ * they are the LIBRARY's own chrome. They cannot go through
83
+ * `MCPUIStrings` — the adapters are runtime-free and never import
84
+ * `solid-js` — so a host localizes them through
85
+ * `ConnectorResultToUILayoutOptions.messages` instead.
86
+ *
87
+ * Every field is a template resolved with `formatMCPUIString`.
88
+ *
89
+ * @since v6.20.0 — the defaults used to be hardcoded French.
90
+ */
91
+ export interface ConnectorAdapterMessages {
92
+ /**
93
+ * Unreadable payload (tier 3). Template — `{versionSuffix}` is
94
+ * `degradedVersionSuffix` when the payload carried a string
95
+ * `schemaVersion`, and `''` otherwise.
96
+ */
97
+ degradedNotice: string
98
+ /** Inserted into `degradedNotice`. Template — `{version}`. */
99
+ degradedVersionSuffix: string
100
+ /**
101
+ * Usable envelope, unknown version (tier 2). Template — `{version}` = the
102
+ * version read, `{expected}` = `CONNECTOR_DYNAMIC_RESULT_V1`.
103
+ */
104
+ versionWarning: string
105
+ }
106
+
107
+ /** English defaults for {@link ConnectorAdapterMessages}. */
108
+ export const DEFAULT_CONNECTOR_MESSAGES: ConnectorAdapterMessages = {
109
+ degradedNotice:
110
+ '### Result not rendered\n\nThe connector result could not be interpreted{versionSuffix}. This explicit state replaces a silent disappearance of the rendering.',
111
+ degradedVersionSuffix: ' (schema: `{version}`)',
112
+ versionWarning:
113
+ '> \u26A0 Unrecognized connector schema (`{version}`, expected `{expected}`). The rendering below is in degraded mode.',
114
+ }
115
+
77
116
  export interface ConnectorResultToUILayoutOptions {
78
117
  /** Layout id. Default derived from `connectorId` + `queryHash` / `toolName`. */
79
118
  id?: string
80
119
  /** Heading for the actions `action-group`. */
81
120
  actionsTitle?: string
121
+ /**
122
+ * Partial override of the degraded-state wording, merged over
123
+ * {@link DEFAULT_CONNECTOR_MESSAGES}. Hosts that render in another
124
+ * language pass their own paragraphs here.
125
+ *
126
+ * @since v6.20.0
127
+ */
128
+ messages?: Partial<ConnectorAdapterMessages>
82
129
  }
83
130
 
84
131
  /**
@@ -144,6 +191,7 @@ export function connectorResultToUILayout(
144
191
  options: ConnectorResultToUILayoutOptions = {}
145
192
  ): UILayout {
146
193
  const strict = ConnectorDynamicResultV1Schema.safeParse(result)
194
+ const messages: ConnectorAdapterMessages = { ...DEFAULT_CONNECTOR_MESSAGES, ...options.messages }
147
195
 
148
196
  // ── Tier 3 : unreadable ───────────────────────────────────
149
197
  if (!strict.success) {
@@ -158,9 +206,12 @@ export function connectorResultToUILayout(
158
206
  components: [
159
207
  degradedTextComponent(
160
208
  'connector-degraded-notice',
161
- `### Résultat non rendu\n\nLe résultat du connecteur n'a pas pu être interprété${
162
- typeof version === 'string' ? ` (schéma : \`${version}\`)` : ''
163
- }. Cet état explicite remplace une disparition silencieuse du rendu.`
209
+ formatMCPUIString(messages.degradedNotice, {
210
+ versionSuffix:
211
+ typeof version === 'string'
212
+ ? formatMCPUIString(messages.degradedVersionSuffix, { version })
213
+ : '',
214
+ })
164
215
  ),
165
216
  ],
166
217
  grid: { ...DEFAULT_GRID },
@@ -171,7 +222,10 @@ export function connectorResultToUILayout(
171
222
  const components: UIComponent[] = [
172
223
  degradedTextComponent(
173
224
  'connector-version-warning',
174
- `> ⚠ Schéma connecteur non reconnu (\`${r.schemaVersion}\`, attendu \`${CONNECTOR_DYNAMIC_RESULT_V1}\`). Le rendu ci-dessous est en mode dégradé.`
225
+ formatMCPUIString(messages.versionWarning, {
226
+ version: r.schemaVersion,
227
+ expected: CONNECTOR_DYNAMIC_RESULT_V1,
228
+ })
175
229
  ),
176
230
  ...collectComponents(r),
177
231
  ]
@@ -14,13 +14,23 @@
14
14
  * ```
15
15
  */
16
16
 
17
- export { connectorResultToUILayout, connectorActionsToActionGroup } from './connector';
17
+ export {
18
+ connectorResultToUILayout,
19
+ connectorActionsToActionGroup,
20
+ DEFAULT_CONNECTOR_MESSAGES,
21
+ } from './connector';
18
22
  export type {
19
23
  ConnectorResultToUILayoutOptions,
20
24
  ConnectorActionsToActionGroupOptions,
25
+ ConnectorAdapterMessages,
21
26
  } from './connector';
22
27
 
23
- export { macroRunToScratchpadState, macroInterrogationToChatPromptConfig } from './macro-run';
28
+ export {
29
+ macroRunToScratchpadState,
30
+ macroInterrogationToChatPromptConfig,
31
+ DEFAULT_MACRO_RUN_MESSAGES,
32
+ } from './macro-run';
33
+ export type { MacroRunAdapterMessages, MacroRunAdapterOptions } from './macro-run';
24
34
 
25
35
  export {
26
36
  createComparisonLayout,
@@ -174,7 +174,59 @@ function resultSectionType(componentType: unknown): ScratchpadSection['type'] {
174
174
  }
175
175
  }
176
176
 
177
- function buildError(run: MacroRunV1): ScratchpadState['error'] | undefined {
177
+ /**
178
+ * The English wording this adapter produces on its own — section titles and
179
+ * the fallbacks used when the run (or the interrogation) carries none.
180
+ *
181
+ * The adapter is runtime-free by contract: no `solid-js`, no
182
+ * `MCPUIStringsContext`. Hosts that render in another language pass a
183
+ * partial override through `MacroRunAdapterOptions.messages`, exactly like
184
+ * `ConnectorResultToUILayoutOptions.messages`.
185
+ *
186
+ * @since v6.20.0
187
+ */
188
+ export interface MacroRunAdapterMessages {
189
+ /** Title of the always-present `agent_card` section. */
190
+ agentSectionTitle: string;
191
+ /** Title of the `stepper` / `split_stepper` section. */
192
+ progressSectionTitle: string;
193
+ /** Title of each result section. */
194
+ resultSectionTitle: string;
195
+ /** Error message of an aborted run that carries no `error`. */
196
+ runAborted: string;
197
+ /** Error message of a failed run that carries no `error`. */
198
+ runFailed: string;
199
+ /** Prompt body of an elicitation with no usable schema and no message. */
200
+ confirmDefault: string;
201
+ }
202
+
203
+ /** English defaults for {@link MacroRunAdapterMessages}. */
204
+ export const DEFAULT_MACRO_RUN_MESSAGES: MacroRunAdapterMessages = {
205
+ agentSectionTitle: 'Agent',
206
+ progressSectionTitle: 'Progress',
207
+ resultSectionTitle: 'Result',
208
+ runAborted: 'Macro run aborted.',
209
+ runFailed: 'Macro run failed.',
210
+ confirmDefault: 'Please confirm to continue.',
211
+ };
212
+
213
+ /** Options shared by the MacroRun adapters. @since v6.20.0 */
214
+ export interface MacroRunAdapterOptions {
215
+ /**
216
+ * Partial override of the adapter's own wording, merged over
217
+ * {@link DEFAULT_MACRO_RUN_MESSAGES}.
218
+ */
219
+ messages?: Partial<MacroRunAdapterMessages>;
220
+ }
221
+
222
+ const withMessages = (
223
+ options: MacroRunAdapterOptions = {}
224
+ ): MacroRunAdapterMessages => ({ ...DEFAULT_MACRO_RUN_MESSAGES, ...options.messages });
225
+
226
+ function buildError(
227
+ run: MacroRunV1,
228
+ messages: MacroRunAdapterMessages
229
+ ): ScratchpadState['error'] | undefined {
178
230
  if (run.status !== 'failed' && run.status !== 'aborted') return undefined;
179
231
  const aborted = run.status === 'aborted';
180
232
  if (run.error) {
@@ -187,7 +239,7 @@ function buildError(run: MacroRunV1): ScratchpadState['error'] | undefined {
187
239
  return err;
188
240
  }
189
241
  return {
190
- message: aborted ? 'Macro run aborted.' : 'Macro run failed.',
242
+ message: aborted ? messages.runAborted : messages.runFailed,
191
243
  retryable: false,
192
244
  };
193
245
  }
@@ -209,13 +261,17 @@ function buildError(run: MacroRunV1): ScratchpadState['error'] | undefined {
209
261
  *
210
262
  * Pure: no fetch, no SSE, no persistence. The host owns all wiring.
211
263
  */
212
- export function macroRunToScratchpadState(run: MacroRunV1): ScratchpadState {
264
+ export function macroRunToScratchpadState(
265
+ run: MacroRunV1,
266
+ options: MacroRunAdapterOptions = {}
267
+ ): ScratchpadState {
268
+ const messages = withMessages(options);
213
269
  const sections: ScratchpadSection[] = [];
214
270
 
215
271
  // 1. Agent card — always present.
216
272
  sections.push({
217
273
  id: 'macro-agent',
218
- title: 'Agent',
274
+ title: messages.agentSectionTitle,
219
275
  type: 'agent_card',
220
276
  content: buildAgentCard(run),
221
277
  editable: false,
@@ -229,7 +285,7 @@ export function macroRunToScratchpadState(run: MacroRunV1): ScratchpadState {
229
285
  hasParallel
230
286
  ? {
231
287
  id: 'macro-split-stepper',
232
- title: 'Progress',
288
+ title: messages.progressSectionTitle,
233
289
  type: 'split_stepper',
234
290
  content: buildSplitStepperContent(run.steps),
235
291
  editable: false,
@@ -237,7 +293,7 @@ export function macroRunToScratchpadState(run: MacroRunV1): ScratchpadState {
237
293
  }
238
294
  : {
239
295
  id: 'macro-stepper',
240
- title: 'Progress',
296
+ title: messages.progressSectionTitle,
241
297
  type: 'stepper',
242
298
  content: buildStepperContent(run.steps),
243
299
  editable: false,
@@ -252,7 +308,7 @@ export function macroRunToScratchpadState(run: MacroRunV1): ScratchpadState {
252
308
  id: 'macro-prompt',
253
309
  title: run.pendingInterrogation.title,
254
310
  type: 'prompt',
255
- content: macroInterrogationToChatPromptConfig(run.pendingInterrogation),
311
+ content: macroInterrogationToChatPromptConfig(run.pendingInterrogation, options),
256
312
  editable: false,
257
313
  source: 'agent',
258
314
  });
@@ -265,7 +321,7 @@ export function macroRunToScratchpadState(run: MacroRunV1): ScratchpadState {
265
321
  results.forEach((component, index) => {
266
322
  sections.push({
267
323
  id: `macro-result-${String(component?.id ?? index)}`,
268
- title: 'Result',
324
+ title: messages.resultSectionTitle,
269
325
  type: resultSectionType(component?.type),
270
326
  content: component,
271
327
  editable: false,
@@ -282,7 +338,7 @@ export function macroRunToScratchpadState(run: MacroRunV1): ScratchpadState {
282
338
  status: RUN_STATUS_TO_SCRATCHPAD[run.status],
283
339
  };
284
340
 
285
- const error = buildError(run);
341
+ const error = buildError(run, messages);
286
342
  if (error) state.error = error;
287
343
 
288
344
  return state;
@@ -311,7 +367,11 @@ function isElicitationSchema(value: unknown): value is ElicitationRequestedSchem
311
367
  * {@link macroRunToScratchpadState} (which calls it for an embedded
312
368
  * `pendingInterrogation`).
313
369
  */
314
- export function macroInterrogationToChatPromptConfig(q: MacroInterrogationV1): ChatPromptConfig {
370
+ export function macroInterrogationToChatPromptConfig(
371
+ q: MacroInterrogationV1,
372
+ options: MacroRunAdapterOptions = {}
373
+ ): ChatPromptConfig {
374
+ const messages = withMessages(options);
315
375
  switch (q.kind) {
316
376
  case 'choice': {
317
377
  const options: ChoiceOption[] = (q.options ?? []).map((o) => {
@@ -355,7 +415,7 @@ export function macroInterrogationToChatPromptConfig(q: MacroInterrogationV1): C
355
415
  return {
356
416
  type: 'confirm',
357
417
  title: q.title,
358
- config: { message: q.message ?? 'Please confirm to continue.' },
418
+ config: { message: q.message ?? messages.confirmDefault },
359
419
  };
360
420
  }
361
421
  }
@@ -7,6 +7,7 @@ import { Component, For, Show } from 'solid-js'
7
7
  import type { UIComponent, ActionGroupParams, ActionComponentParams } from '../types'
8
8
  import { useAction } from '../hooks/useAction'
9
9
  import { safeUrl } from '../utils/safe-url'
10
+ import { useMCPUIStrings } from '../context/MCPUIStringsContext'
10
11
 
11
12
  export interface ActionGroupRendererProps {
12
13
  /**
@@ -147,6 +148,7 @@ const ActionButton: Component<{
147
148
  * ```
148
149
  */
149
150
  export const ActionGroupRenderer: Component<ActionGroupRendererProps> = (props) => {
151
+ const strings = useMCPUIStrings()
150
152
  const params = () => props.params || (props.component?.params as ActionGroupParams) || { actions: [] }
151
153
 
152
154
  const layoutClass = () => {
@@ -181,7 +183,7 @@ export const ActionGroupRenderer: Component<ActionGroupRendererProps> = (props)
181
183
  <div
182
184
  class={`${layoutClass()} ${gapClass()} ${params()?.fullWidth ? 'w-full' : ''}`}
183
185
  role="group"
184
- aria-label={params()?.label || 'Action group'}
186
+ aria-label={params()?.label || strings.actionGroupLabel}
185
187
  >
186
188
  <For each={params()?.actions || []}>
187
189
  {(action, index) => <ActionButton action={action} index={index()} />}