@miragon/mcp-toolkit-ui 0.10.1

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 (320) hide show
  1. package/README.md +36 -0
  2. package/dist/app/adapt-data-widget.d.ts +33 -0
  3. package/dist/app/adapt-data-widget.d.ts.map +1 -0
  4. package/dist/app/adapt-data-widget.js +35 -0
  5. package/dist/app/adapt-data-widget.js.map +1 -0
  6. package/dist/app/builder/CatalogueSheet.d.ts +13 -0
  7. package/dist/app/builder/CatalogueSheet.d.ts.map +1 -0
  8. package/dist/app/builder/CatalogueSheet.js +33 -0
  9. package/dist/app/builder/CatalogueSheet.js.map +1 -0
  10. package/dist/app/builder/PipelineStrip.d.ts +22 -0
  11. package/dist/app/builder/PipelineStrip.d.ts.map +1 -0
  12. package/dist/app/builder/PipelineStrip.js +31 -0
  13. package/dist/app/builder/PipelineStrip.js.map +1 -0
  14. package/dist/app/builder/PreviewPane.d.ts +13 -0
  15. package/dist/app/builder/PreviewPane.d.ts.map +1 -0
  16. package/dist/app/builder/PreviewPane.js +21 -0
  17. package/dist/app/builder/PreviewPane.js.map +1 -0
  18. package/dist/app/builder/SaveDialog.d.ts +14 -0
  19. package/dist/app/builder/SaveDialog.d.ts.map +1 -0
  20. package/dist/app/builder/SaveDialog.js +14 -0
  21. package/dist/app/builder/SaveDialog.js.map +1 -0
  22. package/dist/app/builder/Toolbar.d.ts +17 -0
  23. package/dist/app/builder/Toolbar.d.ts.map +1 -0
  24. package/dist/app/builder/Toolbar.js +15 -0
  25. package/dist/app/builder/Toolbar.js.map +1 -0
  26. package/dist/app/builder/Workspace.d.ts +28 -0
  27. package/dist/app/builder/Workspace.d.ts.map +1 -0
  28. package/dist/app/builder/Workspace.js +117 -0
  29. package/dist/app/builder/Workspace.js.map +1 -0
  30. package/dist/app/builder/builder-model.d.ts +86 -0
  31. package/dist/app/builder/builder-model.d.ts.map +1 -0
  32. package/dist/app/builder/builder-model.js +174 -0
  33. package/dist/app/builder/builder-model.js.map +1 -0
  34. package/dist/app/builder/builder-reducer.d.ts +71 -0
  35. package/dist/app/builder/builder-reducer.d.ts.map +1 -0
  36. package/dist/app/builder/builder-reducer.js +201 -0
  37. package/dist/app/builder/builder-reducer.js.map +1 -0
  38. package/dist/app/builder/labels.d.ts +78 -0
  39. package/dist/app/builder/labels.d.ts.map +1 -0
  40. package/dist/app/builder/labels.js +71 -0
  41. package/dist/app/builder/labels.js.map +1 -0
  42. package/dist/app/builder/status-chip.d.ts +10 -0
  43. package/dist/app/builder/status-chip.d.ts.map +1 -0
  44. package/dist/app/builder/status-chip.js +16 -0
  45. package/dist/app/builder/status-chip.js.map +1 -0
  46. package/dist/app/host-bridge.d.ts +211 -0
  47. package/dist/app/host-bridge.d.ts.map +1 -0
  48. package/dist/app/host-bridge.js +247 -0
  49. package/dist/app/host-bridge.js.map +1 -0
  50. package/dist/app/index.d.ts +16 -0
  51. package/dist/app/index.d.ts.map +1 -0
  52. package/dist/app/index.js +18 -0
  53. package/dist/app/index.js.map +1 -0
  54. package/dist/app/layout-builder.d.ts +48 -0
  55. package/dist/app/layout-builder.d.ts.map +1 -0
  56. package/dist/app/layout-builder.js +418 -0
  57. package/dist/app/layout-builder.js.map +1 -0
  58. package/dist/app/mcp-app-view.d.ts +43 -0
  59. package/dist/app/mcp-app-view.d.ts.map +1 -0
  60. package/dist/app/mcp-app-view.js +169 -0
  61. package/dist/app/mcp-app-view.js.map +1 -0
  62. package/dist/app/mcp-toolkit-app.d.ts +18 -0
  63. package/dist/app/mcp-toolkit-app.d.ts.map +1 -0
  64. package/dist/app/mcp-toolkit-app.js +22 -0
  65. package/dist/app/mcp-toolkit-app.js.map +1 -0
  66. package/dist/app/use-host-actions.d.ts +57 -0
  67. package/dist/app/use-host-actions.d.ts.map +1 -0
  68. package/dist/app/use-host-actions.js +42 -0
  69. package/dist/app/use-host-actions.js.map +1 -0
  70. package/dist/app/widget-fixture.d.ts +180 -0
  71. package/dist/app/widget-fixture.d.ts.map +1 -0
  72. package/dist/app/widget-fixture.js +273 -0
  73. package/dist/app/widget-fixture.js.map +1 -0
  74. package/dist/app/widget-props-sheet.d.ts +20 -0
  75. package/dist/app/widget-props-sheet.d.ts.map +1 -0
  76. package/dist/app/widget-props-sheet.js +87 -0
  77. package/dist/app/widget-props-sheet.js.map +1 -0
  78. package/dist/app/widget-renderer.d.ts +87 -0
  79. package/dist/app/widget-renderer.d.ts.map +1 -0
  80. package/dist/app/widget-renderer.js +105 -0
  81. package/dist/app/widget-renderer.js.map +1 -0
  82. package/dist/components/DrillButton.d.ts +22 -0
  83. package/dist/components/DrillButton.d.ts.map +1 -0
  84. package/dist/components/DrillButton.js +13 -0
  85. package/dist/components/DrillButton.js.map +1 -0
  86. package/dist/components/FilterBar.d.ts +28 -0
  87. package/dist/components/FilterBar.d.ts.map +1 -0
  88. package/dist/components/FilterBar.js +12 -0
  89. package/dist/components/FilterBar.js.map +1 -0
  90. package/dist/components/GridLayout.d.ts +26 -0
  91. package/dist/components/GridLayout.d.ts.map +1 -0
  92. package/dist/components/GridLayout.js +31 -0
  93. package/dist/components/GridLayout.js.map +1 -0
  94. package/dist/components/GroupCard.d.ts +21 -0
  95. package/dist/components/GroupCard.d.ts.map +1 -0
  96. package/dist/components/GroupCard.js +24 -0
  97. package/dist/components/GroupCard.js.map +1 -0
  98. package/dist/components/KpiGrid.d.ts +43 -0
  99. package/dist/components/KpiGrid.d.ts.map +1 -0
  100. package/dist/components/KpiGrid.js +35 -0
  101. package/dist/components/KpiGrid.js.map +1 -0
  102. package/dist/components/ListFooter.d.ts +22 -0
  103. package/dist/components/ListFooter.d.ts.map +1 -0
  104. package/dist/components/ListFooter.js +13 -0
  105. package/dist/components/ListFooter.js.map +1 -0
  106. package/dist/components/Pills.d.ts +25 -0
  107. package/dist/components/Pills.d.ts.map +1 -0
  108. package/dist/components/Pills.js +17 -0
  109. package/dist/components/Pills.js.map +1 -0
  110. package/dist/components/SectionHeading.d.ts +16 -0
  111. package/dist/components/SectionHeading.d.ts.map +1 -0
  112. package/dist/components/SectionHeading.js +10 -0
  113. package/dist/components/SectionHeading.js.map +1 -0
  114. package/dist/components/WidgetHeader.d.ts +21 -0
  115. package/dist/components/WidgetHeader.d.ts.map +1 -0
  116. package/dist/components/WidgetHeader.js +11 -0
  117. package/dist/components/WidgetHeader.js.map +1 -0
  118. package/dist/hooks/index.d.ts +11 -0
  119. package/dist/hooks/index.d.ts.map +1 -0
  120. package/dist/hooks/index.js +7 -0
  121. package/dist/hooks/index.js.map +1 -0
  122. package/dist/hooks/use-debounced-value.d.ts +7 -0
  123. package/dist/hooks/use-debounced-value.d.ts.map +1 -0
  124. package/dist/hooks/use-debounced-value.js +15 -0
  125. package/dist/hooks/use-debounced-value.js.map +1 -0
  126. package/dist/hooks/use-mobile.d.ts +6 -0
  127. package/dist/hooks/use-mobile.d.ts.map +1 -0
  128. package/dist/hooks/use-mobile.js +19 -0
  129. package/dist/hooks/use-mobile.js.map +1 -0
  130. package/dist/hooks/use-tool-query.d.ts +21 -0
  131. package/dist/hooks/use-tool-query.d.ts.map +1 -0
  132. package/dist/hooks/use-tool-query.js +47 -0
  133. package/dist/hooks/use-tool-query.js.map +1 -0
  134. package/dist/hooks/use-tool-result-recovery.d.ts +54 -0
  135. package/dist/hooks/use-tool-result-recovery.d.ts.map +1 -0
  136. package/dist/hooks/use-tool-result-recovery.js +93 -0
  137. package/dist/hooks/use-tool-result-recovery.js.map +1 -0
  138. package/dist/hooks/use-view-data.d.ts +19 -0
  139. package/dist/hooks/use-view-data.d.ts.map +1 -0
  140. package/dist/hooks/use-view-data.js +18 -0
  141. package/dist/hooks/use-view-data.js.map +1 -0
  142. package/dist/hooks/use-view-tool-query.d.ts +18 -0
  143. package/dist/hooks/use-view-tool-query.d.ts.map +1 -0
  144. package/dist/hooks/use-view-tool-query.js +29 -0
  145. package/dist/hooks/use-view-tool-query.js.map +1 -0
  146. package/dist/index.d.ts +47 -0
  147. package/dist/index.d.ts.map +1 -0
  148. package/dist/index.js +56 -0
  149. package/dist/index.js.map +1 -0
  150. package/dist/lib/parse-tool-result.d.ts +39 -0
  151. package/dist/lib/parse-tool-result.d.ts.map +1 -0
  152. package/dist/lib/parse-tool-result.js +66 -0
  153. package/dist/lib/parse-tool-result.js.map +1 -0
  154. package/dist/lib/tone-utils.d.ts +18 -0
  155. package/dist/lib/tone-utils.d.ts.map +1 -0
  156. package/dist/lib/tone-utils.js +25 -0
  157. package/dist/lib/tone-utils.js.map +1 -0
  158. package/dist/lib/utils.d.ts +3 -0
  159. package/dist/lib/utils.d.ts.map +1 -0
  160. package/dist/lib/utils.js +6 -0
  161. package/dist/lib/utils.js.map +1 -0
  162. package/dist/locale/index.d.ts +3 -0
  163. package/dist/locale/index.d.ts.map +1 -0
  164. package/dist/locale/index.js +7 -0
  165. package/dist/locale/index.js.map +1 -0
  166. package/dist/locale/locale-provider.d.ts +50 -0
  167. package/dist/locale/locale-provider.d.ts.map +1 -0
  168. package/dist/locale/locale-provider.js +47 -0
  169. package/dist/locale/locale-provider.js.map +1 -0
  170. package/dist/primitives/alert.d.ts +10 -0
  171. package/dist/primitives/alert.d.ts.map +1 -0
  172. package/dist/primitives/alert.js +25 -0
  173. package/dist/primitives/alert.js.map +1 -0
  174. package/dist/primitives/badge.d.ts +8 -0
  175. package/dist/primitives/badge.d.ts.map +1 -0
  176. package/dist/primitives/badge.js +34 -0
  177. package/dist/primitives/badge.js.map +1 -0
  178. package/dist/primitives/button.d.ts +11 -0
  179. package/dist/primitives/button.d.ts.map +1 -0
  180. package/dist/primitives/button.js +36 -0
  181. package/dist/primitives/button.js.map +1 -0
  182. package/dist/primitives/card.d.ts +12 -0
  183. package/dist/primitives/card.d.ts.map +1 -0
  184. package/dist/primitives/card.js +25 -0
  185. package/dist/primitives/card.js.map +1 -0
  186. package/dist/primitives/dialog.d.ts +18 -0
  187. package/dist/primitives/dialog.d.ts.map +1 -0
  188. package/dist/primitives/dialog.js +38 -0
  189. package/dist/primitives/dialog.js.map +1 -0
  190. package/dist/primitives/input.d.ts +4 -0
  191. package/dist/primitives/input.d.ts.map +1 -0
  192. package/dist/primitives/input.js +7 -0
  193. package/dist/primitives/input.js.map +1 -0
  194. package/dist/primitives/scroll-area.d.ts +6 -0
  195. package/dist/primitives/scroll-area.d.ts.map +1 -0
  196. package/dist/primitives/scroll-area.js +11 -0
  197. package/dist/primitives/scroll-area.js.map +1 -0
  198. package/dist/primitives/select.d.ts +16 -0
  199. package/dist/primitives/select.d.ts.map +1 -0
  200. package/dist/primitives/select.js +38 -0
  201. package/dist/primitives/select.js.map +1 -0
  202. package/dist/primitives/separator.d.ts +4 -0
  203. package/dist/primitives/separator.d.ts.map +1 -0
  204. package/dist/primitives/separator.js +9 -0
  205. package/dist/primitives/separator.js.map +1 -0
  206. package/dist/primitives/sheet.d.ts +15 -0
  207. package/dist/primitives/sheet.d.ts.map +1 -0
  208. package/dist/primitives/sheet.js +41 -0
  209. package/dist/primitives/sheet.js.map +1 -0
  210. package/dist/primitives/skeleton.d.ts +3 -0
  211. package/dist/primitives/skeleton.d.ts.map +1 -0
  212. package/dist/primitives/skeleton.js +7 -0
  213. package/dist/primitives/skeleton.js.map +1 -0
  214. package/dist/primitives/switch.d.ts +5 -0
  215. package/dist/primitives/switch.d.ts.map +1 -0
  216. package/dist/primitives/switch.js +8 -0
  217. package/dist/primitives/switch.js.map +1 -0
  218. package/dist/primitives/table.d.ts +11 -0
  219. package/dist/primitives/table.d.ts.map +1 -0
  220. package/dist/primitives/table.js +28 -0
  221. package/dist/primitives/table.js.map +1 -0
  222. package/dist/primitives/tabs.d.ts +12 -0
  223. package/dist/primitives/tabs.d.ts.map +1 -0
  224. package/dist/primitives/tabs.js +29 -0
  225. package/dist/primitives/tabs.js.map +1 -0
  226. package/dist/providers/query-provider.d.ts +11 -0
  227. package/dist/providers/query-provider.d.ts.map +1 -0
  228. package/dist/providers/query-provider.js +20 -0
  229. package/dist/providers/query-provider.js.map +1 -0
  230. package/dist/theme/create-theme.d.ts +130 -0
  231. package/dist/theme/create-theme.d.ts.map +1 -0
  232. package/dist/theme/create-theme.js +65 -0
  233. package/dist/theme/create-theme.js.map +1 -0
  234. package/dist/theme/index.d.ts +7 -0
  235. package/dist/theme/index.d.ts.map +1 -0
  236. package/dist/theme/index.js +7 -0
  237. package/dist/theme/index.js.map +1 -0
  238. package/dist/theme/presets.d.ts +25 -0
  239. package/dist/theme/presets.d.ts.map +1 -0
  240. package/dist/theme/presets.js +68 -0
  241. package/dist/theme/presets.js.map +1 -0
  242. package/dist/theme/theme-provider.d.ts +69 -0
  243. package/dist/theme/theme-provider.d.ts.map +1 -0
  244. package/dist/theme/theme-provider.js +79 -0
  245. package/dist/theme/theme-provider.js.map +1 -0
  246. package/package.json +71 -0
  247. package/src/app/adapt-data-widget.tsx +51 -0
  248. package/src/app/builder/CatalogueSheet.tsx +230 -0
  249. package/src/app/builder/PipelineStrip.tsx +260 -0
  250. package/src/app/builder/PreviewPane.tsx +72 -0
  251. package/src/app/builder/SaveDialog.tsx +95 -0
  252. package/src/app/builder/Toolbar.tsx +95 -0
  253. package/src/app/builder/Workspace.tsx +483 -0
  254. package/src/app/builder/builder-model.test.ts +351 -0
  255. package/src/app/builder/builder-model.ts +213 -0
  256. package/src/app/builder/builder-reducer.test.ts +441 -0
  257. package/src/app/builder/builder-reducer.ts +289 -0
  258. package/src/app/builder/labels.ts +139 -0
  259. package/src/app/builder/status-chip.tsx +37 -0
  260. package/src/app/host-bridge.test.ts +206 -0
  261. package/src/app/host-bridge.tsx +371 -0
  262. package/src/app/index.ts +51 -0
  263. package/src/app/layout-builder.tsx +872 -0
  264. package/src/app/mcp-app-view.tsx +367 -0
  265. package/src/app/mcp-toolkit-app.tsx +25 -0
  266. package/src/app/use-host-actions.test.ts +16 -0
  267. package/src/app/use-host-actions.tsx +88 -0
  268. package/src/app/widget-fixture.test.ts +108 -0
  269. package/src/app/widget-fixture.tsx +441 -0
  270. package/src/app/widget-props-sheet.tsx +285 -0
  271. package/src/app/widget-renderer.test.ts +42 -0
  272. package/src/app/widget-renderer.tsx +200 -0
  273. package/src/components/DrillButton.tsx +37 -0
  274. package/src/components/FilterBar.tsx +68 -0
  275. package/src/components/GridLayout.tsx +49 -0
  276. package/src/components/GroupCard.tsx +52 -0
  277. package/src/components/KpiGrid.tsx +134 -0
  278. package/src/components/ListFooter.tsx +48 -0
  279. package/src/components/Pills.tsx +45 -0
  280. package/src/components/SectionHeading.tsx +26 -0
  281. package/src/components/WidgetHeader.tsx +51 -0
  282. package/src/globals.css +168 -0
  283. package/src/hooks/index.ts +17 -0
  284. package/src/hooks/use-debounced-value.ts +15 -0
  285. package/src/hooks/use-mobile.ts +24 -0
  286. package/src/hooks/use-tool-query.ts +63 -0
  287. package/src/hooks/use-tool-result-recovery.test.ts +65 -0
  288. package/src/hooks/use-tool-result-recovery.ts +144 -0
  289. package/src/hooks/use-view-data.ts +31 -0
  290. package/src/hooks/use-view-tool-query.ts +38 -0
  291. package/src/index.ts +134 -0
  292. package/src/lib/parse-tool-result.test.ts +139 -0
  293. package/src/lib/parse-tool-result.ts +89 -0
  294. package/src/lib/tone-utils.test.ts +35 -0
  295. package/src/lib/tone-utils.ts +38 -0
  296. package/src/lib/utils.ts +6 -0
  297. package/src/locale/index.ts +7 -0
  298. package/src/locale/locale-provider.tsx +81 -0
  299. package/src/primitives/alert.tsx +60 -0
  300. package/src/primitives/badge.tsx +49 -0
  301. package/src/primitives/button.tsx +62 -0
  302. package/src/primitives/card.tsx +92 -0
  303. package/src/primitives/dialog.tsx +144 -0
  304. package/src/primitives/input.tsx +21 -0
  305. package/src/primitives/scroll-area.tsx +54 -0
  306. package/src/primitives/select.tsx +173 -0
  307. package/src/primitives/separator.tsx +21 -0
  308. package/src/primitives/sheet.tsx +134 -0
  309. package/src/primitives/skeleton.tsx +13 -0
  310. package/src/primitives/switch.tsx +24 -0
  311. package/src/primitives/table.tsx +87 -0
  312. package/src/primitives/tabs.tsx +79 -0
  313. package/src/providers/query-provider.tsx +38 -0
  314. package/src/theme/create-theme.test.ts +108 -0
  315. package/src/theme/create-theme.ts +158 -0
  316. package/src/theme/index.ts +9 -0
  317. package/src/theme/presets.ts +82 -0
  318. package/src/theme/theme-provider.tsx +152 -0
  319. package/src/ui-catalog.test.ts +112 -0
  320. package/ui-catalog.json +1280 -0
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Shared label contract for the visual LayoutBuilder.
3
+ *
4
+ * Extracted from `layout-builder.tsx` so the presentational sub-components
5
+ * (Toolbar, PipelineStrip, Workspace, CatalogueSheet, SaveDialog, PreviewPane)
6
+ * can depend on the labels without importing the orchestrating container —
7
+ * which would create an import cycle. React-free and `mcp-use`-free.
8
+ */
9
+ export interface LayoutBuilderLabels {
10
+ title?: string;
11
+ builderBadge?: string;
12
+ previewBadge?: string;
13
+ catalogue?: string;
14
+ save?: string;
15
+ done?: string;
16
+ viewLayoutTab?: string;
17
+ viewPipelineTab?: string;
18
+ viewPreviewTab?: string;
19
+ saveDialogTitle?: string;
20
+ saveDialogDescription?: string;
21
+ saveNameLabel?: string;
22
+ saveDescriptionLabel?: string;
23
+ saveConfirm?: string;
24
+ cancel?: string;
25
+ pipelineHeader?: string;
26
+ keysHeader?: string;
27
+ stepsHeader?: string;
28
+ keyName?: string;
29
+ keyValue?: string;
30
+ stepContextId?: string;
31
+ stepPickerLabel?: string;
32
+ addKey?: string;
33
+ addStep?: string;
34
+ emptyKeys?: string;
35
+ emptySteps?: string;
36
+ statusUpToDate?: string;
37
+ statusPending?: string;
38
+ statusRefreshing?: string;
39
+ paletteHeader?: string;
40
+ paletteEmpty?: string;
41
+ canvasEmpty?: string;
42
+ canvasDropHint?: string;
43
+ addRow?: string;
44
+ addTab?: string;
45
+ removeRow?: string;
46
+ renameTab?: string;
47
+ removeTab?: string;
48
+ tabsLabel?: string;
49
+ catalogueDescription?: string;
50
+ catalogueKeys?: string;
51
+ catalogueSteps?: string;
52
+ catalogueUnreachable?: string;
53
+ catalogueUnreachableEmpty?: string;
54
+ catalogueProducedBy?: string;
55
+ catalogueConsumedBy?: string;
56
+ catalogueNeedsKeys?: string;
57
+ cataloguePickKey?: string;
58
+ catalogueAddProducingStep?: string;
59
+ catalogueLive?: string;
60
+ catalogueMissing?: string;
61
+ /** Banner shown when the catalogue fetch fails (prefixes the reason). */
62
+ catalogueError?: string;
63
+ /** Heading for the pipeline-validation warning banner. */
64
+ validationWarning?: string;
65
+ /** Inline message when a save fails (prefixes the reason). */
66
+ saveError?: string;
67
+ /** Inline message when a tab rename is rejected (duplicate label). */
68
+ renameDuplicate?: string;
69
+ }
70
+ export declare const DEFAULT_LABELS: Required<LayoutBuilderLabels>;
71
+ /**
72
+ * MIME type used to carry a widget id across the palette → canvas drag.
73
+ * Shared between the palette items and the canvas drop targets.
74
+ */
75
+ export declare const WIDGET_DRAG_MIME = "application/x-mcp-widget-id";
76
+ /** Refresh status for the auto-apply chip and the pipeline strip. */
77
+ export type RefreshStatus = "idle" | "pending" | "refreshing";
78
+ //# sourceMappingURL=labels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../../../src/app/builder/labels.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAClC,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAClC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,0DAA0D;IAC1D,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,sEAAsE;IACtE,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,mBAAmB,CA0DxD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,gCAAgC,CAAA;AAE7D,qEAAqE;AACrE,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,YAAY,CAAA"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Shared label contract for the visual LayoutBuilder.
3
+ *
4
+ * Extracted from `layout-builder.tsx` so the presentational sub-components
5
+ * (Toolbar, PipelineStrip, Workspace, CatalogueSheet, SaveDialog, PreviewPane)
6
+ * can depend on the labels without importing the orchestrating container —
7
+ * which would create an import cycle. React-free and `mcp-use`-free.
8
+ */
9
+ export const DEFAULT_LABELS = {
10
+ title: "View Builder",
11
+ builderBadge: "Builder",
12
+ previewBadge: "Preview",
13
+ catalogue: "Catalogue",
14
+ save: "Save",
15
+ done: "Done",
16
+ viewLayoutTab: "Layout",
17
+ viewPipelineTab: "Pipeline",
18
+ viewPreviewTab: "Preview",
19
+ saveDialogTitle: "Save dashboard",
20
+ saveDialogDescription: "Persists the current layout along with the keys and steps that populate it.",
21
+ saveNameLabel: "Name",
22
+ saveDescriptionLabel: "Description",
23
+ saveConfirm: "Save dashboard",
24
+ cancel: "Cancel",
25
+ pipelineHeader: "Pipeline",
26
+ keysHeader: "Keys",
27
+ stepsHeader: "Steps",
28
+ keyName: "key",
29
+ keyValue: 'value, "literal", true, {…}',
30
+ stepContextId: "ctx id",
31
+ stepPickerLabel: "pick a step",
32
+ addKey: "Add key",
33
+ addStep: "Add step",
34
+ emptyKeys: "No keys seeded.",
35
+ emptySteps: "No steps configured.",
36
+ statusUpToDate: "Up to date",
37
+ statusPending: "Applying soon…",
38
+ statusRefreshing: "Applying…",
39
+ paletteHeader: "Palette",
40
+ paletteEmpty: "No widgets reachable yet — seed a key or add a step.",
41
+ canvasEmpty: "Drag a widget here, or click one in the palette.",
42
+ canvasDropHint: "Drop to add",
43
+ addRow: "Add row",
44
+ addTab: "Add tab",
45
+ removeRow: "Remove row",
46
+ renameTab: "Rename tab",
47
+ removeTab: "Remove tab",
48
+ tabsLabel: "Tabs",
49
+ catalogueDescription: "Every key and widget the framework knows about, whether or not it's reachable right now.",
50
+ catalogueKeys: "Keys",
51
+ catalogueSteps: "Steps",
52
+ catalogueUnreachable: "Unreachable widgets",
53
+ catalogueUnreachableEmpty: "Every registered widget is reachable.",
54
+ catalogueProducedBy: "produced by",
55
+ catalogueConsumedBy: "consumed by",
56
+ catalogueNeedsKeys: "needs",
57
+ cataloguePickKey: "Add as key",
58
+ catalogueAddProducingStep: "Add producing step",
59
+ catalogueLive: "live",
60
+ catalogueMissing: "missing",
61
+ catalogueError: "Couldn't refresh the builder catalogue",
62
+ validationWarning: "This pipeline won't render as configured",
63
+ saveError: "Couldn't save",
64
+ renameDuplicate: "A tab with that name already exists.",
65
+ };
66
+ /**
67
+ * MIME type used to carry a widget id across the palette → canvas drag.
68
+ * Shared between the palette items and the canvas drop targets.
69
+ */
70
+ export const WIDGET_DRAG_MIME = "application/x-mcp-widget-id";
71
+ //# sourceMappingURL=labels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"labels.js","sourceRoot":"","sources":["../../../src/app/builder/labels.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAgEH,MAAM,CAAC,MAAM,cAAc,GAAkC;IAC3D,KAAK,EAAE,cAAc;IACrB,YAAY,EAAE,SAAS;IACvB,YAAY,EAAE,SAAS;IACvB,SAAS,EAAE,WAAW;IACtB,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,aAAa,EAAE,QAAQ;IACvB,eAAe,EAAE,UAAU;IAC3B,cAAc,EAAE,SAAS;IACzB,eAAe,EAAE,gBAAgB;IACjC,qBAAqB,EACnB,6EAA6E;IAC/E,aAAa,EAAE,MAAM;IACrB,oBAAoB,EAAE,aAAa;IACnC,WAAW,EAAE,gBAAgB;IAC7B,MAAM,EAAE,QAAQ;IAChB,cAAc,EAAE,UAAU;IAC1B,UAAU,EAAE,MAAM;IAClB,WAAW,EAAE,OAAO;IACpB,OAAO,EAAE,KAAK;IACd,QAAQ,EAAE,6BAA6B;IACvC,aAAa,EAAE,QAAQ;IACvB,eAAe,EAAE,aAAa;IAC9B,MAAM,EAAE,SAAS;IACjB,OAAO,EAAE,UAAU;IACnB,SAAS,EAAE,iBAAiB;IAC5B,UAAU,EAAE,sBAAsB;IAClC,cAAc,EAAE,YAAY;IAC5B,aAAa,EAAE,gBAAgB;IAC/B,gBAAgB,EAAE,WAAW;IAC7B,aAAa,EAAE,SAAS;IACxB,YAAY,EAAE,sDAAsD;IACpE,WAAW,EAAE,kDAAkD;IAC/D,cAAc,EAAE,aAAa;IAC7B,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,SAAS;IACjB,SAAS,EAAE,YAAY;IACvB,SAAS,EAAE,YAAY;IACvB,SAAS,EAAE,YAAY;IACvB,SAAS,EAAE,MAAM;IACjB,oBAAoB,EAClB,0FAA0F;IAC5F,aAAa,EAAE,MAAM;IACrB,cAAc,EAAE,OAAO;IACvB,oBAAoB,EAAE,qBAAqB;IAC3C,yBAAyB,EAAE,uCAAuC;IAClE,mBAAmB,EAAE,aAAa;IAClC,mBAAmB,EAAE,aAAa;IAClC,kBAAkB,EAAE,OAAO;IAC3B,gBAAgB,EAAE,YAAY;IAC9B,yBAAyB,EAAE,oBAAoB;IAC/C,aAAa,EAAE,MAAM;IACrB,gBAAgB,EAAE,SAAS;IAC3B,cAAc,EAAE,wCAAwC;IACxD,iBAAiB,EAAE,0CAA0C;IAC7D,SAAS,EAAE,eAAe;IAC1B,eAAe,EAAE,sCAAsC;CACxD,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,6BAA6B,CAAA"}
@@ -0,0 +1,10 @@
1
+ import type { LayoutBuilderLabels, RefreshStatus } from "./labels.js";
2
+ /**
3
+ * Compact auto-apply status chip. Shared by the Toolbar and the
4
+ * PipelineStrip so both surfaces show the same refresh state.
5
+ */
6
+ export declare function StatusChip({ status, L, }: {
7
+ status: RefreshStatus;
8
+ L: Required<LayoutBuilderLabels>;
9
+ }): import("react").JSX.Element;
10
+ //# sourceMappingURL=status-chip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-chip.d.ts","sourceRoot":"","sources":["../../../src/app/builder/status-chip.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAErE;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,CAAC,GACF,EAAE;IACD,MAAM,EAAE,aAAa,CAAA;IACrB,CAAC,EAAE,QAAQ,CAAC,mBAAmB,CAAC,CAAA;CACjC,+BAuBA"}
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { CircleDot, Loader2 } from "lucide-react";
3
+ /**
4
+ * Compact auto-apply status chip. Shared by the Toolbar and the
5
+ * PipelineStrip so both surfaces show the same refresh state.
6
+ */
7
+ export function StatusChip({ status, L, }) {
8
+ if (status === "idle") {
9
+ return (_jsxs("span", { className: "text-muted-foreground inline-flex items-center gap-1.5", children: [_jsx(CircleDot, { className: "size-3" }), L.statusUpToDate] }));
10
+ }
11
+ if (status === "pending") {
12
+ return (_jsxs("span", { className: "inline-flex items-center gap-1.5 text-amber-600 dark:text-amber-400", children: [_jsx("span", { className: "size-1.5 animate-pulse rounded-full bg-amber-500" }), L.statusPending] }));
13
+ }
14
+ return (_jsxs("span", { className: "text-primary inline-flex items-center gap-1.5", children: [_jsx(Loader2, { className: "size-3 animate-spin" }), L.statusRefreshing] }));
15
+ }
16
+ //# sourceMappingURL=status-chip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-chip.js","sourceRoot":"","sources":["../../../src/app/builder/status-chip.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAGjD;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,EACzB,MAAM,EACN,CAAC,GAIF;IACC,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CACL,gBAAM,SAAS,EAAC,wDAAwD,aACtE,KAAC,SAAS,IAAC,SAAS,EAAC,QAAQ,GAAG,EAC/B,CAAC,CAAC,cAAc,IACZ,CACR,CAAA;IACH,CAAC;IACD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,CACL,gBAAM,SAAS,EAAC,qEAAqE,aACnF,eAAM,SAAS,EAAC,kDAAkD,GAAG,EACpE,CAAC,CAAC,aAAa,IACX,CACR,CAAA;IACH,CAAC;IACD,OAAO,CACL,gBAAM,SAAS,EAAC,+CAA+C,aAC7D,KAAC,OAAO,IAAC,SAAS,EAAC,qBAAqB,GAAG,EAC1C,CAAC,CAAC,gBAAgB,IACd,CACR,CAAA;AACH,CAAC"}
@@ -0,0 +1,211 @@
1
+ import { type ReactNode } from "react";
2
+ /**
3
+ * The host capabilities a hand-built widget needs, abstracted away from any one
4
+ * host runtime. A `HostBridge` is the single seam a portable widget talks to:
5
+ * write the widget against {@link useHostBridge} and it runs unchanged in our
6
+ * own `mcp-use` host, inside ChatGPT (OpenAI Apps SDK), or as a standalone web
7
+ * app driven directly by a `@modelcontextprotocol/sdk` client — only the
8
+ * surrounding adapter changes.
9
+ *
10
+ * This is deliberately the *minimum* a deterministic UI needs, not a mirror of
11
+ * any host's full surface. Each adapter maps these verbs onto its host and
12
+ * fails soft where the host cannot honour them (see the per-factory docs).
13
+ */
14
+ export interface HostBridge {
15
+ /**
16
+ * Invoke an MCP tool on the connected server and resolve with its raw
17
+ * response (typically `{ structuredContent, content, … }`). Callers decode it
18
+ * with `parseToolResult`. Rejects if the call fails so a widget's own error
19
+ * state (TanStack Query, try/catch) can surface it.
20
+ */
21
+ callTool(name: string, args: Record<string, unknown>): Promise<unknown>;
22
+ /**
23
+ * Hand a natural-language prompt back to the conversation to drive a new model
24
+ * turn (navigate to another widget, ask the agent to analyse something). In
25
+ * hosts without a conversation (standalone web app) this is a no-op unless an
26
+ * `onFollowup` handler is supplied.
27
+ */
28
+ sendFollowup(prompt: string): void;
29
+ /**
30
+ * Ask the host to open a URL outside the (often sandboxed) widget frame.
31
+ * Falls back to `window.open` only where no host bridge mediates links.
32
+ */
33
+ openExternal(url: string): void;
34
+ /**
35
+ * The structured data this widget was rendered with, if the host pushed any
36
+ * (the tool result's `structuredContent` / `toolOutput`). Returns `null` when
37
+ * the host delivers data another way (e.g. props) or has none.
38
+ */
39
+ getWidgetData<T>(): T | null;
40
+ /**
41
+ * Persist a short text the model should see on the next turn (selection,
42
+ * filter, current view). Optional: not every host exposes model context, and
43
+ * a standalone web app has no model at all — callers must guard its absence.
44
+ */
45
+ setModelContext?(text: string): void;
46
+ /** The host's colour-scheme preference, when it reports one. */
47
+ theme?: "light" | "dark";
48
+ }
49
+ /**
50
+ * Provide an explicit {@link HostBridge} to a subtree. Wrap a portable widget in
51
+ * the adapter for the host it is running in — {@link createChatGptHostBridge},
52
+ * {@link createStandaloneHostBridge}, or {@link createMcpUseHostBridge} — and
53
+ * every `useHostBridge()` below resolves to it.
54
+ *
55
+ * Omitting the provider is supported: {@link useHostBridge} (and, for backward
56
+ * compatibility, `useHostActions`) then fall back to the `mcp-use`/react default
57
+ * bridge so existing widgets keep working without any wrapping.
58
+ */
59
+ export declare function HostBridgeProvider({ bridge, children, }: {
60
+ bridge: HostBridge;
61
+ children: ReactNode;
62
+ }): ReactNode;
63
+ /**
64
+ * Read the explicit {@link HostBridge} from context, or `null` if no
65
+ * {@link HostBridgeProvider} is present. Adapters that want to *fall back* to the
66
+ * default `mcp-use` bridge (rather than throw) use this instead of
67
+ * {@link useHostBridge}.
68
+ */
69
+ export declare function useHostBridgeOrNull(): HostBridge | null;
70
+ /**
71
+ * The {@link HostBridge} for the current subtree. Resolution order:
72
+ *
73
+ * 1. An explicit bridge from the nearest {@link HostBridgeProvider}.
74
+ * 2. The default `mcp-use`/react bridge ({@link createMcpUseHostBridge}), so a
75
+ * widget mounted in our own host needs no provider.
76
+ *
77
+ * The `mcp-use` hooks the default bridge wraps must run under an `mcp-use`
78
+ * provider/host context; outside one (e.g. a bare unit test render) wrap the
79
+ * widget in a `HostBridgeProvider` with a {@link createStandaloneHostBridge}
80
+ * instead. This hook never returns `null`: a portable widget can always assume a
81
+ * bridge exists.
82
+ */
83
+ export declare function useHostBridge(): HostBridge;
84
+ /**
85
+ * Build a {@link HostBridge} backed by `mcp-use`/react — the default for widgets
86
+ * running in the toolkit's own host. Wraps `useWidget()` (host actions,
87
+ * `toolOutput`, `theme`) and `useCallTool` so it preserves exactly the behaviour
88
+ * widgets had before the bridge abstraction:
89
+ *
90
+ * - `openExternal` routes through the host's `openExternal` and falls back to
91
+ * `window.open` when no host bridge is wired (local dev preview) — mirroring
92
+ * the original `useHostActions.openLink`.
93
+ * - `sendFollowup` routes through `sendFollowUpMessage` and swallows rejections
94
+ * with a `console.warn`, as `useHostActions` did.
95
+ *
96
+ * Must be called inside an `mcp-use` host context (it calls `mcp-use` hooks).
97
+ * Use {@link createMcpUseHostBridge} for the standalone factory variant.
98
+ */
99
+ export declare function useMcpUseHostBridge(): HostBridge;
100
+ /**
101
+ * Factory form of {@link useMcpUseHostBridge} for symmetry with the other
102
+ * adapters. Because the `mcp-use` bridge is hook-driven (it reads live host
103
+ * context), the "factory" is really the hook itself — call it from a component.
104
+ *
105
+ * @example
106
+ * function MyWidget() {
107
+ * const bridge = createMcpUseHostBridge() // === useMcpUseHostBridge()
108
+ * // …or rely on useHostBridge()'s default and skip the provider entirely.
109
+ * }
110
+ */
111
+ export declare const createMcpUseHostBridge: typeof useMcpUseHostBridge;
112
+ /**
113
+ * Minimal structural view of the OpenAI Apps SDK `window.openai` object this
114
+ * adapter reads. Every field is optional: the real SDK shape varies across
115
+ * versions and host builds, so the adapter probes each method/field defensively
116
+ * and degrades to a no-op (with a `console.warn`) rather than assuming presence.
117
+ *
118
+ * Assumptions documented here (verify against the Apps SDK you target):
119
+ * - `callTool(name, args)` resolves with the tool response. Required for tool
120
+ * calls; without it `callTool` rejects with a clear error.
121
+ * - `sendFollowUpMessage` is called with `{ prompt }` (older builds) — we also
122
+ * accept a bare-string signature and try both shapes.
123
+ * - `openExternal` is called with `{ href }`.
124
+ * - `toolOutput` (preferred) or `toolResponseMetadata` carries the structured
125
+ * widget data; `setWidgetState(state)` persists model-visible state.
126
+ * - `theme` is `"light"` | `"dark"`.
127
+ */
128
+ export interface OpenAiAppsSdk {
129
+ callTool?: (name: string, args: Record<string, unknown>) => Promise<unknown>;
130
+ sendFollowUpMessage?: (arg: {
131
+ prompt: string;
132
+ } | string) => unknown;
133
+ sendFollowupMessage?: (arg: {
134
+ prompt: string;
135
+ } | string) => unknown;
136
+ openExternal?: (payload: {
137
+ href: string;
138
+ } | string) => unknown;
139
+ toolOutput?: unknown;
140
+ toolResponseMetadata?: unknown;
141
+ setWidgetState?: (state: Record<string, unknown>) => unknown;
142
+ theme?: unknown;
143
+ }
144
+ /**
145
+ * Build a {@link HostBridge} for the OpenAI Apps SDK (ChatGPT). Reads the host's
146
+ * `window.openai` object and maps the bridge verbs onto it **defensively** —
147
+ * every method is probed before use, and a missing one degrades to a logged
148
+ * no-op (or, for `callTool`, a rejected promise) instead of crashing the widget.
149
+ * This is what lets the *same* hand-built widget run in ChatGPT with no code
150
+ * change, even across Apps SDK versions whose surface drifts.
151
+ *
152
+ * Pass an explicit `sdk` to test the guards without a real `window.openai`
153
+ * (passing `null` exercises the fully-absent path). See {@link OpenAiAppsSdk}
154
+ * for the documented assumptions about the SDK shape.
155
+ */
156
+ export declare function createChatGptHostBridge(sdk?: OpenAiAppsSdk | null): HostBridge;
157
+ /** Options for {@link createStandaloneHostBridge}. */
158
+ export interface StandaloneHostBridgeOptions {
159
+ /**
160
+ * The only required capability: how to call a tool on the server. In a
161
+ * standalone web app this typically wraps a `@modelcontextprotocol/sdk`
162
+ * `Client.callTool({ name, arguments })`, but any function with this shape
163
+ * works — that injection is the whole point: hand-built widgets render
164
+ * against *any* existing MCP server without the toolkit's host runtime.
165
+ */
166
+ callTool: (name: string, args: Record<string, unknown>) => Promise<unknown>;
167
+ /**
168
+ * Supply the structured data a widget reads via `getWidgetData()`. A static
169
+ * value, or a getter `() => value` that is re-read on each call (so the data
170
+ * can change without rebuilding the bridge). Any function is treated as a
171
+ * getter — widget data is never itself a function. Optional: many standalone
172
+ * widgets fetch everything through `callTool` instead.
173
+ */
174
+ getData?: unknown;
175
+ /**
176
+ * Handle a `sendFollowup` prompt. A standalone app has no conversation, so
177
+ * this is where you wire "ask the model" to your own chat UI, a toast, or a
178
+ * logger. Omit to make `sendFollowup` a logged no-op.
179
+ */
180
+ onFollowup?: (prompt: string) => void;
181
+ /**
182
+ * Handle `openExternal`. Defaults to `window.open(url, "_blank")` when omitted
183
+ * (a standalone app is not sandboxed, so that is safe).
184
+ */
185
+ onOpenExternal?: (url: string) => void;
186
+ /** Handle `setModelContext`. Omit to make it a logged no-op. */
187
+ onModelContext?: (text: string) => void;
188
+ /** Static theme to report to widgets. */
189
+ theme?: "light" | "dark";
190
+ }
191
+ /**
192
+ * Build a {@link HostBridge} for a standalone web app driven against an existing
193
+ * MCP server — no toolkit host, no `createFrameworkApp`. You inject `callTool`
194
+ * (usually a thin wrapper over a `@modelcontextprotocol/sdk` client); the
195
+ * conversation-shaped verbs (`sendFollowup`, `setModelContext`) are no-ops
196
+ * unless you wire handlers, and `openExternal` defaults to `window.open`.
197
+ *
198
+ * This is the decoupling layer that turns the toolkit's hand-built widgets into
199
+ * a reusable UI kit for *any* MCP server: render `<HostBridgeProvider bridge=…>`
200
+ * once at the app root and every portable widget below works. The widget fixture
201
+ * harness also builds on this factory so host simulation has a single source.
202
+ *
203
+ * @example
204
+ * const client = new Client(…) // @modelcontextprotocol/sdk
205
+ * const bridge = createStandaloneHostBridge({
206
+ * callTool: (name, args) => client.callTool({ name, arguments: args }),
207
+ * getData: () => currentRecord,
208
+ * })
209
+ */
210
+ export declare function createStandaloneHostBridge(options: StandaloneHostBridgeOptions): HostBridge;
211
+ //# sourceMappingURL=host-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-bridge.d.ts","sourceRoot":"","sources":["../../src/app/host-bridge.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,247 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext, useMemo } from "react";
3
+ import { useWidget } from "mcp-use/react";
4
+ const HostBridgeContext = createContext(null);
5
+ /**
6
+ * Provide an explicit {@link HostBridge} to a subtree. Wrap a portable widget in
7
+ * the adapter for the host it is running in — {@link createChatGptHostBridge},
8
+ * {@link createStandaloneHostBridge}, or {@link createMcpUseHostBridge} — and
9
+ * every `useHostBridge()` below resolves to it.
10
+ *
11
+ * Omitting the provider is supported: {@link useHostBridge} (and, for backward
12
+ * compatibility, `useHostActions`) then fall back to the `mcp-use`/react default
13
+ * bridge so existing widgets keep working without any wrapping.
14
+ */
15
+ export function HostBridgeProvider({ bridge, children, }) {
16
+ return _jsx(HostBridgeContext.Provider, { value: bridge, children: children });
17
+ }
18
+ /**
19
+ * Read the explicit {@link HostBridge} from context, or `null` if no
20
+ * {@link HostBridgeProvider} is present. Adapters that want to *fall back* to the
21
+ * default `mcp-use` bridge (rather than throw) use this instead of
22
+ * {@link useHostBridge}.
23
+ */
24
+ export function useHostBridgeOrNull() {
25
+ return useContext(HostBridgeContext);
26
+ }
27
+ /**
28
+ * The {@link HostBridge} for the current subtree. Resolution order:
29
+ *
30
+ * 1. An explicit bridge from the nearest {@link HostBridgeProvider}.
31
+ * 2. The default `mcp-use`/react bridge ({@link createMcpUseHostBridge}), so a
32
+ * widget mounted in our own host needs no provider.
33
+ *
34
+ * The `mcp-use` hooks the default bridge wraps must run under an `mcp-use`
35
+ * provider/host context; outside one (e.g. a bare unit test render) wrap the
36
+ * widget in a `HostBridgeProvider` with a {@link createStandaloneHostBridge}
37
+ * instead. This hook never returns `null`: a portable widget can always assume a
38
+ * bridge exists.
39
+ */
40
+ export function useHostBridge() {
41
+ const explicit = useContext(HostBridgeContext);
42
+ // Always call the default-bridge hook (Rules of Hooks): it's cheap and only
43
+ // *used* when no explicit bridge is provided. The mcp-use hooks underneath are
44
+ // host-context readers, safe to call even when their result goes unused.
45
+ const fallback = useMcpUseHostBridge();
46
+ return explicit ?? fallback;
47
+ }
48
+ /**
49
+ * Build a {@link HostBridge} backed by `mcp-use`/react — the default for widgets
50
+ * running in the toolkit's own host. Wraps `useWidget()` (host actions,
51
+ * `toolOutput`, `theme`) and `useCallTool` so it preserves exactly the behaviour
52
+ * widgets had before the bridge abstraction:
53
+ *
54
+ * - `openExternal` routes through the host's `openExternal` and falls back to
55
+ * `window.open` when no host bridge is wired (local dev preview) — mirroring
56
+ * the original `useHostActions.openLink`.
57
+ * - `sendFollowup` routes through `sendFollowUpMessage` and swallows rejections
58
+ * with a `console.warn`, as `useHostActions` did.
59
+ *
60
+ * Must be called inside an `mcp-use` host context (it calls `mcp-use` hooks).
61
+ * Use {@link createMcpUseHostBridge} for the standalone factory variant.
62
+ */
63
+ export function useMcpUseHostBridge() {
64
+ const widget = useWidget();
65
+ const { callTool, sendFollowUpMessage, openExternal, output, theme, setState } = widget;
66
+ return useMemo(() => ({
67
+ callTool: (name, args) => callTool(name, args),
68
+ sendFollowup: (prompt) => {
69
+ void sendFollowUpMessage(prompt).catch((err) => {
70
+ console.warn("[host-bridge] sendFollowUpMessage failed:", err);
71
+ });
72
+ },
73
+ openExternal: (url) => {
74
+ try {
75
+ openExternal(url);
76
+ }
77
+ catch {
78
+ // No host bridge (local dev preview) — fall back to window.open.
79
+ if (typeof window !== "undefined")
80
+ window.open(url, "_blank", "noopener");
81
+ }
82
+ },
83
+ getWidgetData: () => output ?? null,
84
+ setModelContext: (text) => {
85
+ void setState({ __model_context: text }).catch((err) => {
86
+ console.warn("[host-bridge] setState (model context) failed:", err);
87
+ });
88
+ },
89
+ theme: theme === "dark" ? "dark" : "light",
90
+ }), [callTool, sendFollowUpMessage, openExternal, output, theme, setState]);
91
+ }
92
+ /**
93
+ * Factory form of {@link useMcpUseHostBridge} for symmetry with the other
94
+ * adapters. Because the `mcp-use` bridge is hook-driven (it reads live host
95
+ * context), the "factory" is really the hook itself — call it from a component.
96
+ *
97
+ * @example
98
+ * function MyWidget() {
99
+ * const bridge = createMcpUseHostBridge() // === useMcpUseHostBridge()
100
+ * // …or rely on useHostBridge()'s default and skip the provider entirely.
101
+ * }
102
+ */
103
+ export const createMcpUseHostBridge = useMcpUseHostBridge;
104
+ /**
105
+ * Resolve the `window.openai` object, or `null` outside a browser / when the SDK
106
+ * is absent. Pulled out so the no-SDK fallback path is unit-testable by passing
107
+ * an explicit object (or `null`).
108
+ */
109
+ function resolveOpenAi(explicit) {
110
+ if (explicit !== undefined)
111
+ return explicit;
112
+ if (typeof window === "undefined")
113
+ return null;
114
+ const candidate = window.openai;
115
+ return candidate && typeof candidate === "object" ? candidate : null;
116
+ }
117
+ /**
118
+ * Build a {@link HostBridge} for the OpenAI Apps SDK (ChatGPT). Reads the host's
119
+ * `window.openai` object and maps the bridge verbs onto it **defensively** —
120
+ * every method is probed before use, and a missing one degrades to a logged
121
+ * no-op (or, for `callTool`, a rejected promise) instead of crashing the widget.
122
+ * This is what lets the *same* hand-built widget run in ChatGPT with no code
123
+ * change, even across Apps SDK versions whose surface drifts.
124
+ *
125
+ * Pass an explicit `sdk` to test the guards without a real `window.openai`
126
+ * (passing `null` exercises the fully-absent path). See {@link OpenAiAppsSdk}
127
+ * for the documented assumptions about the SDK shape.
128
+ */
129
+ export function createChatGptHostBridge(sdk) {
130
+ const openai = resolveOpenAi(sdk);
131
+ return {
132
+ callTool: (name, args) => {
133
+ if (typeof openai?.callTool !== "function") {
134
+ console.warn("[host-bridge] window.openai.callTool unavailable — cannot call", name);
135
+ return Promise.reject(new Error(`[host-bridge] OpenAI Apps SDK callTool is unavailable; cannot invoke "${name}".`));
136
+ }
137
+ return Promise.resolve(openai.callTool(name, args));
138
+ },
139
+ sendFollowup: (prompt) => {
140
+ const fn = openai?.sendFollowUpMessage ?? openai?.sendFollowupMessage;
141
+ if (typeof fn !== "function") {
142
+ console.warn("[host-bridge] window.openai.sendFollowUpMessage unavailable — no-op");
143
+ return;
144
+ }
145
+ try {
146
+ // Newer builds take `{ prompt }`; try that first, then a bare string.
147
+ const result = fn({ prompt });
148
+ if (result instanceof Promise) {
149
+ result.catch((err) => {
150
+ console.warn("[host-bridge] sendFollowUpMessage rejected:", err);
151
+ });
152
+ }
153
+ }
154
+ catch {
155
+ try {
156
+ fn(prompt);
157
+ }
158
+ catch (err) {
159
+ console.warn("[host-bridge] sendFollowUpMessage failed:", err);
160
+ }
161
+ }
162
+ },
163
+ openExternal: (url) => {
164
+ if (typeof openai?.openExternal === "function") {
165
+ try {
166
+ openai.openExternal({ href: url });
167
+ return;
168
+ }
169
+ catch (err) {
170
+ console.warn("[host-bridge] window.openai.openExternal failed:", err);
171
+ }
172
+ }
173
+ if (typeof window !== "undefined")
174
+ window.open(url, "_blank", "noopener");
175
+ },
176
+ getWidgetData: () => {
177
+ const data = openai?.toolOutput ?? openai?.toolResponseMetadata;
178
+ return data ?? null;
179
+ },
180
+ setModelContext: (text) => {
181
+ if (typeof openai?.setWidgetState !== "function") {
182
+ console.warn("[host-bridge] window.openai.setWidgetState unavailable — model context no-op");
183
+ return;
184
+ }
185
+ try {
186
+ openai.setWidgetState({ __model_context: text });
187
+ }
188
+ catch (err) {
189
+ console.warn("[host-bridge] setWidgetState failed:", err);
190
+ }
191
+ },
192
+ theme: openai?.theme === "dark" ? "dark" : openai?.theme === "light" ? "light" : undefined,
193
+ };
194
+ }
195
+ /**
196
+ * Build a {@link HostBridge} for a standalone web app driven against an existing
197
+ * MCP server — no toolkit host, no `createFrameworkApp`. You inject `callTool`
198
+ * (usually a thin wrapper over a `@modelcontextprotocol/sdk` client); the
199
+ * conversation-shaped verbs (`sendFollowup`, `setModelContext`) are no-ops
200
+ * unless you wire handlers, and `openExternal` defaults to `window.open`.
201
+ *
202
+ * This is the decoupling layer that turns the toolkit's hand-built widgets into
203
+ * a reusable UI kit for *any* MCP server: render `<HostBridgeProvider bridge=…>`
204
+ * once at the app root and every portable widget below works. The widget fixture
205
+ * harness also builds on this factory so host simulation has a single source.
206
+ *
207
+ * @example
208
+ * const client = new Client(…) // @modelcontextprotocol/sdk
209
+ * const bridge = createStandaloneHostBridge({
210
+ * callTool: (name, args) => client.callTool({ name, arguments: args }),
211
+ * getData: () => currentRecord,
212
+ * })
213
+ */
214
+ export function createStandaloneHostBridge(options) {
215
+ const { callTool, getData, onFollowup, onOpenExternal, onModelContext, theme } = options;
216
+ return {
217
+ callTool: (name, args) => callTool(name, args),
218
+ sendFollowup: (prompt) => {
219
+ if (onFollowup) {
220
+ onFollowup(prompt);
221
+ return;
222
+ }
223
+ console.warn("[host-bridge] standalone bridge has no onFollowup handler — prompt dropped");
224
+ },
225
+ openExternal: (url) => {
226
+ if (onOpenExternal) {
227
+ onOpenExternal(url);
228
+ return;
229
+ }
230
+ if (typeof window !== "undefined")
231
+ window.open(url, "_blank", "noopener");
232
+ },
233
+ getWidgetData: () => {
234
+ const data = typeof getData === "function" ? getData() : getData;
235
+ return data ?? null;
236
+ },
237
+ setModelContext: (text) => {
238
+ if (onModelContext) {
239
+ onModelContext(text);
240
+ return;
241
+ }
242
+ console.warn("[host-bridge] standalone bridge has no onModelContext handler — context dropped");
243
+ },
244
+ theme,
245
+ };
246
+ }
247
+ //# sourceMappingURL=host-bridge.js.map