@rainbow-robotics/muscat-plugin-kit 0.1.2-dev.44 → 0.1.2-dev.46

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 (240) hide show
  1. package/README.md +1 -1
  2. package/cli/README.md +184 -0
  3. package/cli/bin/muscat-pk.mjs +13 -0
  4. package/cli/prepack.mjs +10 -0
  5. package/cli/src/build.mjs +2 -29
  6. package/cli/src/dev.mjs +10 -2
  7. package/cli/src/devBack.mjs +54 -11
  8. package/cli/src/devUi.mjs +100 -34
  9. package/cli/src/manifest.mjs +15 -0
  10. package/cli/src/mcp.mjs +534 -0
  11. package/cli/src/new.mjs +16 -1
  12. package/cli/src/pluginDevServer.mjs +113 -0
  13. package/cli/src/ports.mjs +160 -0
  14. package/cli/src/sdk.mjs +11 -9
  15. package/cli/src/storybook.mjs +168 -0
  16. package/cli/src/templates-embedded.mjs +1 -1
  17. package/cli/src/util.mjs +29 -0
  18. package/cli/storybook-dist/_design-tokens.css +4957 -0
  19. package/cli/storybook-dist/_stories-src/NxAvatar.stories.tsx +27 -0
  20. package/cli/storybook-dist/_stories-src/NxPagination.stories.tsx +28 -0
  21. package/cli/storybook-dist/_stories-src/RBAccordion/RBAccordion.stories.tsx +46 -0
  22. package/cli/storybook-dist/_stories-src/RBAccordion/RBAccordionGroup.stories.tsx +73 -0
  23. package/cli/storybook-dist/_stories-src/RBBadge/RBBadge.stories.tsx +93 -0
  24. package/cli/storybook-dist/_stories-src/RBBattery/RBBattery.stories.tsx +74 -0
  25. package/cli/storybook-dist/_stories-src/RBButton/RBCheckIconButton.stories.tsx +28 -0
  26. package/cli/storybook-dist/_stories-src/RBButton/RBCheckLabelButton.stories.tsx +84 -0
  27. package/cli/storybook-dist/_stories-src/RBButton/RBIconButton.stories.tsx +57 -0
  28. package/cli/storybook-dist/_stories-src/RBButton/RBInlineLabelButton.stories.tsx +41 -0
  29. package/cli/storybook-dist/_stories-src/RBButton/RBLabelButton.stories.tsx +60 -0
  30. package/cli/storybook-dist/_stories-src/RBDatePicker/RBDateInput.stories.tsx +44 -0
  31. package/cli/storybook-dist/_stories-src/RBDatePicker/RBRangeDateInput.stories.tsx +44 -0
  32. package/cli/storybook-dist/_stories-src/RBDialog/RBAlert.stories.tsx +51 -0
  33. package/cli/storybook-dist/_stories-src/RBDialog/RBConfirm.stories.tsx +55 -0
  34. package/cli/storybook-dist/_stories-src/RBDialog/RBPrompt.stories.tsx +52 -0
  35. package/cli/storybook-dist/_stories-src/RBDivider/RBDivider.stories.tsx +93 -0
  36. package/cli/storybook-dist/_stories-src/RBEmptyView/RBEmptyView.stories.tsx +49 -0
  37. package/cli/storybook-dist/_stories-src/RBIcons/RBColorIcons.stories.tsx +108 -0
  38. package/cli/storybook-dist/_stories-src/RBIcons/RBIcons.stories.tsx +106 -0
  39. package/cli/storybook-dist/_stories-src/RBIcons/RBMenuTreeIcons.stories.tsx +108 -0
  40. package/cli/storybook-dist/_stories-src/RBIcons/RBProgramIcons.stories.tsx +116 -0
  41. package/cli/storybook-dist/_stories-src/RBInput/RBCheckBox.stories.tsx +89 -0
  42. package/cli/storybook-dist/_stories-src/RBInput/RBMultiRangeInput.stories.tsx +64 -0
  43. package/cli/storybook-dist/_stories-src/RBInput/RBRadioBox.stories.tsx +65 -0
  44. package/cli/storybook-dist/_stories-src/RBInput/RBRadioButton.stories.tsx +68 -0
  45. package/cli/storybook-dist/_stories-src/RBInput/RBSelectBox.stories.tsx +119 -0
  46. package/cli/storybook-dist/_stories-src/RBInput/RBSideNumberInput.stories.tsx +90 -0
  47. package/cli/storybook-dist/_stories-src/RBInput/RBText/RBTextArea.stories.tsx +45 -0
  48. package/cli/storybook-dist/_stories-src/RBInput/RBText/RBTextInput.stories.tsx +50 -0
  49. package/cli/storybook-dist/_stories-src/RBInput/RBTextField.stories.tsx +102 -0
  50. package/cli/storybook-dist/_stories-src/RBJoyStick/RBJoyStick.stories.tsx +31 -0
  51. package/cli/storybook-dist/_stories-src/RBLight/RBLight.stories.tsx +36 -0
  52. package/cli/storybook-dist/_stories-src/RBPagination/RBPagination.stories.tsx +49 -0
  53. package/cli/storybook-dist/_stories-src/RBShadcn/RBCard/RBCard.stories.tsx +89 -0
  54. package/cli/storybook-dist/_stories-src/RBShadcn/RBCommand/RBCommand.stories.tsx +116 -0
  55. package/cli/storybook-dist/_stories-src/RBShadcn/RBDialog/RBDialog.stories.tsx +74 -0
  56. package/cli/storybook-dist/_stories-src/RBShadcn/RBDrawer/RBDrawer.stories.tsx +99 -0
  57. package/cli/storybook-dist/_stories-src/RBShadcn/RBDropdownMenu/RBDropdownMenu.stories.tsx +123 -0
  58. package/cli/storybook-dist/_stories-src/RBShadcn/RBMenubar/RBMenubar.stories.tsx +135 -0
  59. package/cli/storybook-dist/_stories-src/RBShadcn/RBPopover/RBPopover.stories.tsx +69 -0
  60. package/cli/storybook-dist/_stories-src/RBShadcn/RBResizable/RBResizable.stories.tsx +49 -0
  61. package/cli/storybook-dist/_stories-src/RBShadcn/RBSheet/RBSheet.stories.tsx +91 -0
  62. package/cli/storybook-dist/_stories-src/RBShadcn/RBSlider/RBSlider.stories.tsx +38 -0
  63. package/cli/storybook-dist/_stories-src/RBShadcn/RBSwitch/RBSwitch.stories.tsx +112 -0
  64. package/cli/storybook-dist/_stories-src/RBShadcn/RBTabs/RBTabs.stories.tsx +75 -0
  65. package/cli/storybook-dist/_stories-src/RBShadcn/RBToggle/RBToggle.stories.tsx +51 -0
  66. package/cli/storybook-dist/_stories-src/RBShadcn/RBToggleGroup/RBToggleGroup.stories.tsx +84 -0
  67. package/cli/storybook-dist/_stories-src/RBTab/RBChipTab.stories.tsx +102 -0
  68. package/cli/storybook-dist/_stories-src/RBTab/RBChipsBoxTab.stories.tsx +78 -0
  69. package/cli/storybook-dist/_stories-src/RBTab/RBTab.stories.tsx +57 -0
  70. package/cli/storybook-dist/_stories-src/RBTable/RBTable.stories.tsx +177 -0
  71. package/cli/storybook-dist/_stories-src/RBTable/RBTableRow.stories.tsx +64 -0
  72. package/cli/storybook-dist/_stories-src/RBToast/RBToast.stories.tsx +117 -0
  73. package/cli/storybook-dist/_stories-src/RBTooltip/RBTooltip.stories.tsx +50 -0
  74. package/cli/storybook-dist/_stories-src/loading/RBSpinner.stories.tsx +30 -0
  75. package/cli/storybook-dist/_stories-src/nx-button/NxButton.stories.tsx +54 -0
  76. package/cli/storybook-dist/_stories-src/nx-button/NxPointerHoldButton.stories.tsx +57 -0
  77. package/cli/storybook-dist/_stories-src/nx-icons/NxIcons.stories.tsx +48 -0
  78. package/cli/storybook-dist/_stories-src/nx-inputs/NxNumberInput.stories.tsx +103 -0
  79. package/cli/storybook-dist/_stories-src/nx-inputs/NxRangeInput.stories.tsx +27 -0
  80. package/cli/storybook-dist/_stories-src/nx-inputs/NxSelectBox.stories.tsx +67 -0
  81. package/cli/storybook-dist/_stories-src/nx-inputs/NxSlideRange.stories.tsx +45 -0
  82. package/cli/storybook-dist/_stories-src/nx-inputs/NxSwitch.stories.tsx +27 -0
  83. package/cli/storybook-dist/_stories-src/nx-inputs/NxTextArea.stories.tsx +48 -0
  84. package/cli/storybook-dist/_stories-src/nx-inputs/NxTextInput.stories.tsx +46 -0
  85. package/cli/storybook-dist/assets/Color-YHDXOIA2-BjuzF3Je.js +1 -0
  86. package/cli/storybook-dist/assets/Docs-BAFZYTMR.js +12 -0
  87. package/cli/storybook-dist/assets/Docs-BQesYW-Q.js +8 -0
  88. package/cli/storybook-dist/assets/Docs-BsMEe093.js +7 -0
  89. package/cli/storybook-dist/assets/Docs-By6k6vcM.js +20 -0
  90. package/cli/storybook-dist/assets/Docs-D1J63cJc.js +7 -0
  91. package/cli/storybook-dist/assets/Docs-GoNbntAU.js +8 -0
  92. package/cli/storybook-dist/assets/DocsRenderer-CFRXHY34-BwY_WiM7.js +2 -0
  93. package/cli/storybook-dist/assets/NxAvatar.stories-CvzBHfYa.js +13 -0
  94. package/cli/storybook-dist/assets/NxButton.stories-B83PesgN.js +20 -0
  95. package/cli/storybook-dist/assets/NxIcons.stories-Ca7qpAaO.js +3 -0
  96. package/cli/storybook-dist/assets/NxNumberInput.stories-DpNcCG6B.js +26 -0
  97. package/cli/storybook-dist/assets/NxPagination.stories-Xnvd3xhH.js +11 -0
  98. package/cli/storybook-dist/assets/NxPointerHoldButton.stories-C3YSIpM0.js +14 -0
  99. package/cli/storybook-dist/assets/NxRangeInput.stories-DIhaNZig.js +17 -0
  100. package/cli/storybook-dist/assets/NxSelectBox.stories-BGwO2mYJ.js +17 -0
  101. package/cli/storybook-dist/assets/NxSlideRange.stories-BXlt5Bgt.js +14 -0
  102. package/cli/storybook-dist/assets/NxSwitch.stories-C5ZqIRtw.js +11 -0
  103. package/cli/storybook-dist/assets/NxTextArea.stories-hm_ycALo.js +11 -0
  104. package/cli/storybook-dist/assets/NxTextInput.stories-DkZAySr_.js +11 -0
  105. package/cli/storybook-dist/assets/PretendardVariable-CJuje-Rk.woff2 +0 -0
  106. package/cli/storybook-dist/assets/RBAccordion.stories--bY36GZY.js +17 -0
  107. package/cli/storybook-dist/assets/RBAccordionGroup.stories-BVr1ccI4.js +33 -0
  108. package/cli/storybook-dist/assets/RBAlert.stories-CkjFBEkv.js +17 -0
  109. package/cli/storybook-dist/assets/RBBadge.stories-CNXILDPh.js +1 -0
  110. package/cli/storybook-dist/assets/RBBattery.stories-AokMv8ZY.js +10 -0
  111. package/cli/storybook-dist/assets/RBCard.stories-CX1sLKB2.js +45 -0
  112. package/cli/storybook-dist/assets/RBCheckBox.stories-By3QHBFm.js +1 -0
  113. package/cli/storybook-dist/assets/RBCheckIconButton.stories-Dud1uK3X.js +1 -0
  114. package/cli/storybook-dist/assets/RBCheckLabelButton.stories-C8iBkZxY.js +24 -0
  115. package/cli/storybook-dist/assets/RBChipTab.stories-DsgbiS2U.js +21 -0
  116. package/cli/storybook-dist/assets/RBChipsBoxTab.stories-C3DZGmq0.js +1 -0
  117. package/cli/storybook-dist/assets/RBColorIcons.stories-CusR20qk.js +3 -0
  118. package/cli/storybook-dist/assets/RBCommand.stories-DhJNgaLZ.js +73 -0
  119. package/cli/storybook-dist/assets/RBConfirm.stories-B6LKpCDa.js +20 -0
  120. package/cli/storybook-dist/assets/RBDateInput.stories-PEEhQ1wJ.js +15 -0
  121. package/cli/storybook-dist/assets/RBDialog.stories-CAtOdRen.js +38 -0
  122. package/cli/storybook-dist/assets/RBDivider.stories-0zpIUlXT.js +1 -0
  123. package/cli/storybook-dist/assets/RBDrawer.stories-CWMG4glY.js +14 -0
  124. package/cli/storybook-dist/assets/RBDropdownMenu.stories-6fbEYZfk.js +86 -0
  125. package/cli/storybook-dist/assets/RBEmptyView.stories-BRDZHjn4.js +12 -0
  126. package/cli/storybook-dist/assets/RBIconButton.stories-sYrRLYob.js +1 -0
  127. package/cli/storybook-dist/assets/RBIcons.stories-DFe8O1_g.js +3 -0
  128. package/cli/storybook-dist/assets/RBInlineLabelButton.stories-DX4VdUfk.js +1 -0
  129. package/cli/storybook-dist/assets/RBJoyStick.stories-SA2Foelf.js +11 -0
  130. package/cli/storybook-dist/assets/RBLabelButton.stories-CicBns_Y.js +1 -0
  131. package/cli/storybook-dist/assets/RBLight.stories-WlP3oEmY.js +1 -0
  132. package/cli/storybook-dist/assets/RBMenuTreeIcons.stories-CrWjPfxj.js +3 -0
  133. package/cli/storybook-dist/assets/RBMenubar.stories-Di4phWw7.js +3 -0
  134. package/cli/storybook-dist/assets/RBMultiRangeInput.stories-DS3wrR3l.js +14 -0
  135. package/cli/storybook-dist/assets/RBPagination.stories-BDVPAUVD.js +17 -0
  136. package/cli/storybook-dist/assets/RBPopover.stories-DL9b_iX9.js +11 -0
  137. package/cli/storybook-dist/assets/RBProgramIcons.stories-ByRVx-on.js +3 -0
  138. package/cli/storybook-dist/assets/RBPrompt.stories-vTmKWyA5.js +20 -0
  139. package/cli/storybook-dist/assets/RBRadioBox.stories-C9WHt4jb.js +1 -0
  140. package/cli/storybook-dist/assets/RBRadioButton.stories-D8KYq63j.js +11 -0
  141. package/cli/storybook-dist/assets/RBRangeDateInput.stories-Bvcf4Su7.js +15 -0
  142. package/cli/storybook-dist/assets/RBResizable.stories-3O2OMuH_.js +20 -0
  143. package/cli/storybook-dist/assets/RBSelectBox.stories-CKZLmPzX.js +6 -0
  144. package/cli/storybook-dist/assets/RBSheet.stories-Dko0It1W.js +39 -0
  145. package/cli/storybook-dist/assets/RBSideNumberInput.stories-CUvqVtId.js +5 -0
  146. package/cli/storybook-dist/assets/RBSlider.stories-CcbaKRYo.js +5 -0
  147. package/cli/storybook-dist/assets/RBSpinner.stories-D15e_JlE.js +14 -0
  148. package/cli/storybook-dist/assets/RBSwitch.stories-C4JRsYJ6.js +65 -0
  149. package/cli/storybook-dist/assets/RBTab.stories-BPvzQSM-.js +1 -0
  150. package/cli/storybook-dist/assets/RBTable.stories-nr8OS1mV.js +62 -0
  151. package/cli/storybook-dist/assets/RBTableRow.stories-rI0rK8Ci.js +11 -0
  152. package/cli/storybook-dist/assets/RBTabs.stories-CxMtHGWA.js +21 -0
  153. package/cli/storybook-dist/assets/RBTextArea.stories-Bru4AhJ3.js +5 -0
  154. package/cli/storybook-dist/assets/RBTextField.stories-Ah3D9lto.js +45 -0
  155. package/cli/storybook-dist/assets/RBTextInput.stories-C3qAVngJ.js +5 -0
  156. package/cli/storybook-dist/assets/RBToast.stories-C1occsvf.js +11 -0
  157. package/cli/storybook-dist/assets/RBToggle.stories-BNrNERc7.js +12 -0
  158. package/cli/storybook-dist/assets/RBToggleGroup.stories-D_RRBwxY.js +17 -0
  159. package/cli/storybook-dist/assets/RBTooltip.stories-DuyOQqrB.js +9 -0
  160. package/cli/storybook-dist/assets/RainbowUiProvider-BYlbsa69.css +1 -0
  161. package/cli/storybook-dist/assets/RainbowUiProvider-B_piZBLb.js +31 -0
  162. package/cli/storybook-dist/assets/browserUtils-DeopUpDy.js +1 -0
  163. package/cli/storybook-dist/assets/chunk-XP5HYGXS-BHXC9YeQ.js +1 -0
  164. package/cli/storybook-dist/assets/client-DTf7SId2.js +1 -0
  165. package/cli/storybook-dist/assets/createConveyorBeltLayer-Cn41pFRH.js +6210 -0
  166. package/cli/storybook-dist/assets/createConveyorBeltLayer-Ds5AOper.css +21 -0
  167. package/cli/storybook-dist/assets/entry-preview-D-mLV0cS.js +2 -0
  168. package/cli/storybook-dist/assets/entry-preview-docs-b8bpVBXy.js +46 -0
  169. package/cli/storybook-dist/assets/iframe-DNru2eN7.js +211 -0
  170. package/cli/storybook-dist/assets/index-B4FGfHer.js +1 -0
  171. package/cli/storybook-dist/assets/index-BRq5TIsn.js +24 -0
  172. package/cli/storybook-dist/assets/index-C1OzuK6-.js +240 -0
  173. package/cli/storybook-dist/assets/index-CT3U1fyk.js +1 -0
  174. package/cli/storybook-dist/assets/index-ChsGqxH_.js +9 -0
  175. package/cli/storybook-dist/assets/index-Cwr2bQOB.js +575 -0
  176. package/cli/storybook-dist/assets/index-DKFBREX_.js +1 -0
  177. package/cli/storybook-dist/assets/index-DgH-xKnr.js +11 -0
  178. package/cli/storybook-dist/assets/index-Dmy2JGbm.js +1 -0
  179. package/cli/storybook-dist/assets/index-DrFu-skq.js +6 -0
  180. package/cli/storybook-dist/assets/jsx-runtime-BTJTZTIL.js +9 -0
  181. package/cli/storybook-dist/assets/keymapTileIndex.worker-BsNYNbqs.js +1 -0
  182. package/cli/storybook-dist/assets/preview-B8lJiyuQ.js +34 -0
  183. package/cli/storybook-dist/assets/preview-BBWR9nbA.js +1 -0
  184. package/cli/storybook-dist/assets/preview-BWzBA1C2.js +396 -0
  185. package/cli/storybook-dist/assets/preview-CILRoSnB.js +1 -0
  186. package/cli/storybook-dist/assets/preview-CVgpLj3b.js +1 -0
  187. package/cli/storybook-dist/assets/preview-CvbIS5ZJ.js +1 -0
  188. package/cli/storybook-dist/assets/preview-DD_OYowb.js +1 -0
  189. package/cli/storybook-dist/assets/preview-DGUiP6tS.js +7 -0
  190. package/cli/storybook-dist/assets/preview-DHQbi4pV.js +1 -0
  191. package/cli/storybook-dist/assets/preview-DUTcCPBe.css +1 -0
  192. package/cli/storybook-dist/assets/preview-QAsoD6Sa.js +2 -0
  193. package/cli/storybook-dist/assets/preview-rcRMbKPr.js +3 -0
  194. package/cli/storybook-dist/assets/react-18-hB3smqWJ.js +1 -0
  195. package/cli/storybook-dist/assets/react-resizable-panels.browser-CvAJUcrm.js +72 -0
  196. package/cli/storybook-dist/assets/test-utils-BQudk2xt.js +9 -0
  197. package/cli/storybook-dist/favicon.svg +1 -0
  198. package/cli/storybook-dist/iframe.html +666 -0
  199. package/cli/storybook-dist/index.html +190 -0
  200. package/cli/storybook-dist/index.json +1 -0
  201. package/cli/storybook-dist/nunito-sans-bold-italic.woff2 +0 -0
  202. package/cli/storybook-dist/nunito-sans-bold.woff2 +0 -0
  203. package/cli/storybook-dist/nunito-sans-italic.woff2 +0 -0
  204. package/cli/storybook-dist/nunito-sans-regular.woff2 +0 -0
  205. package/cli/storybook-dist/project.json +1 -0
  206. package/cli/storybook-dist/sb-addons/chromatic-com-storybook-10/manager-bundle.js +331 -0
  207. package/cli/storybook-dist/sb-addons/chromatic-com-storybook-10/manager-bundle.js.LEGAL.txt +51 -0
  208. package/cli/storybook-dist/sb-addons/essentials-actions-3/manager-bundle.js +3 -0
  209. package/cli/storybook-dist/sb-addons/essentials-backgrounds-5/manager-bundle.js +12 -0
  210. package/cli/storybook-dist/sb-addons/essentials-controls-2/manager-bundle.js +405 -0
  211. package/cli/storybook-dist/sb-addons/essentials-docs-4/manager-bundle.js +245 -0
  212. package/cli/storybook-dist/sb-addons/essentials-measure-8/manager-bundle.js +3 -0
  213. package/cli/storybook-dist/sb-addons/essentials-outline-9/manager-bundle.js +3 -0
  214. package/cli/storybook-dist/sb-addons/essentials-toolbars-7/manager-bundle.js +3 -0
  215. package/cli/storybook-dist/sb-addons/essentials-viewport-6/manager-bundle.js +3 -0
  216. package/cli/storybook-dist/sb-addons/links-1/manager-bundle.js +3 -0
  217. package/cli/storybook-dist/sb-addons/storybook-13/manager-bundle.js +3 -0
  218. package/cli/storybook-dist/sb-addons/storybook-core-core-server-presets-0/common-manager-bundle.js +3 -0
  219. package/cli/storybook-dist/sb-addons/storybook-experimental-addon-test-12/manager-bundle.js +223 -0
  220. package/cli/storybook-dist/sb-addons/themes-11/manager-bundle.js +3 -0
  221. package/cli/storybook-dist/sb-common-assets/favicon.svg +1 -0
  222. package/cli/storybook-dist/sb-common-assets/nunito-sans-bold-italic.woff2 +0 -0
  223. package/cli/storybook-dist/sb-common-assets/nunito-sans-bold.woff2 +0 -0
  224. package/cli/storybook-dist/sb-common-assets/nunito-sans-italic.woff2 +0 -0
  225. package/cli/storybook-dist/sb-common-assets/nunito-sans-regular.woff2 +0 -0
  226. package/cli/storybook-dist/sb-manager/globals-module-info.js +1052 -0
  227. package/cli/storybook-dist/sb-manager/globals-runtime.js +41775 -0
  228. package/cli/storybook-dist/sb-manager/globals.js +48 -0
  229. package/cli/storybook-dist/sb-manager/runtime.js +12048 -0
  230. package/cli/templates/common/.mcp.json +8 -0
  231. package/cli/templates/common/README.md +467 -53
  232. package/cli/templates/common/assets/icon.svg +44 -2
  233. package/cli/templates/common/package.json +4 -0
  234. package/cli/templates/common/ui/content.tsx +209 -26
  235. package/cli/templates/common/ui/style.css +6 -0
  236. package/cli/templates/common/vite.config.ts +6 -34
  237. package/cli/templates/cpp/cpp/main.cpp +1 -0
  238. package/cli/vite.d.mts +25 -0
  239. package/cli/vite.mjs +271 -0
  240. package/package.json +31 -4
package/README.md CHANGED
@@ -121,7 +121,7 @@ muscat-pk pack # 배포용 ZIP 생성
121
121
 
122
122
  | 패키지 | 역할 |
123
123
  |---|---|
124
- | `@rainbow-robotics/plugin-ui` | UI 런타임 계약: rb-* 엘리먼트, React 바인딩, sandbox connect |
124
+ | `@rainbow-robotics/plugin-ui` | UI 런타임 계약: React direct mount, `useRb()` context, host services |
125
125
  | `@rainbow-robotics/muscat-plugin-kit` | CLI, 템플릿, 빌드/팩, 미리보기 호스트 |
126
126
 
127
127
  플러그인 ZIP에는 플러그인 코드와 에셋만 포함됩니다. `@rainbow-robotics/plugin-ui`, `react`, `react-dom`은 호스트(Muscat/로봇)의 import map에서 제공됩니다.
package/cli/README.md CHANGED
@@ -20,6 +20,190 @@ muscat-pk uninstall # remove muscat-pk itself (npm global or S3 binary)
20
20
  muscat-pk sdk list | sdk update [version] # manage rainbow-rb-sdk (python)
21
21
  ```
22
22
 
23
+ ## Backend ports
24
+
25
+ If a plugin backend opens a TCP server, declare it in `manifest.json`:
26
+
27
+ ```json
28
+ {
29
+ "ports": [28600, 28601]
30
+ }
31
+ ```
32
+
33
+ `ports` is optional and accepts only `number[]`; ranges or objects are not
34
+ accepted. External plugin backend ports are reserved for `28600-28999`.
35
+ `muscat-pk dev` and `muscat-pk dev:back` validate the manifest before start and
36
+ stop the backend if it opens an undeclared managed TCP listen port.
37
+
38
+ Known robot/industrial/internal ports such as `502`, `4840`, `5170-5179`,
39
+ `8000-8999`, `10000`, `2222`, `30004`, `34964`, `44818`, `50000-50005`,
40
+ and `50051` are reserved and must not be used by external plugins.
41
+
42
+ ## Backend runtimes
43
+
44
+ `manifest.json` selects one runtime:
45
+
46
+ | runtime | source | notes |
47
+ |---|---|---|
48
+ | `{ "type": "none" }` | — | UI-only plugin; no backend container |
49
+ | `{ "type": "python", "entry": "main.py" }` | `py/` | Uses `rainbow.rb_sdk.RBPluginCall` for UI/backend messaging |
50
+ | `{ "type": "cpp", "entry": "<executable name>" }` | `cpp/` | Built with CMake in Docker; current template is a run skeleton |
51
+ | `{ "type": "ros2", "rosClient": "rclpy", ... }` | `ros2_ws/` | ROS2 Python node; may use Python SDK alongside ROS2 APIs |
52
+ | `{ "type": "ros2", "rosClient": "rclcpp", ... }` | `ros2_ws/` | ROS2 C++ node built with colcon/CMake |
53
+
54
+ All non-`none` runtimes run in Docker during `muscat-pk dev:back`, `muscat-pk
55
+ dev`, and build/export flows so development matches the robot environment.
56
+
57
+ ## JavaScript dependencies
58
+
59
+ `muscat-pk build` runs the plugin project's own Vite build. Vite resolves imports
60
+ from installed `node_modules`; it does not care whether a package is listed under
61
+ `dependencies` or `devDependencies`, but the package must be installed.
62
+
63
+ Do not run a production-only install such as `npm install --omit=dev` before
64
+ building a plugin UI, because build tools like `vite`, `typescript`,
65
+ `tailwindcss`, `@tailwindcss/vite`, `sass`, or `less` are usually
66
+ `devDependencies`.
67
+
68
+ The scaffold keeps this split:
69
+
70
+ | package kind | examples | why |
71
+ |---|---|---|
72
+ | `dependencies` | `@rainbow-robotics/plugin-ui`, UI libraries imported by plugin source | Author-facing APIs used by `ui/*.tsx` |
73
+ | `devDependencies` | `vite`, `typescript`, `tailwindcss`, `@tailwindcss/vite`, `sass`, `less` | Build/dev tools needed before `dist/*.js` is produced |
74
+
75
+ The built plugin ZIP does not include `package.json` or `node_modules`. For
76
+ production, Muscat provides `@rainbow-robotics/plugin-ui`, React, and ReactDOM
77
+ through the host import map; plugin UI build output imports those as host
78
+ externals.
79
+
80
+ ## Plugin styles
81
+
82
+ `muscat()` auto-loads plugin styles from `ui/style.{css,scss,sass,less}` or
83
+ `ui/styles.{css,scss,sass,less}` for every UI entry, and from
84
+ `ui/{entry}.{css,scss,sass,less}` for a matching entry-specific file. Authors do
85
+ not need to import CSS from every `.tsx` entry.
86
+
87
+ The scaffold enables Tailwind in the plugin's own `vite.config.ts`; those
88
+ Tailwind dependencies live in the plugin package, while `muscat()` injects the
89
+ generated CSS into the plugin JS bundle so dynamic host imports do not need a
90
+ separate CSS file.
91
+
92
+ Built CSS selectors are scoped under the current plugin id
93
+ (`[data-muscat-plugin-id="..."]`), so Tailwind utilities or plugin styles do not
94
+ rewrite the host page or another plugin. CSS-in-JS libraries are allowed too,
95
+ but global styles (for example Emotion `Global`) remain the author's
96
+ responsibility to scope.
97
+
98
+ ### Tailwind
99
+
100
+ New plugins include Tailwind by default:
101
+
102
+ ```ts
103
+ import { defineConfig } from "vite";
104
+ import tailwindcss from "@tailwindcss/vite";
105
+ import { muscat } from "@rainbow-robotics/muscat-plugin-kit/vite";
106
+
107
+ export default defineConfig({
108
+ plugins: [tailwindcss(), muscat()],
109
+ });
110
+ ```
111
+
112
+ The default `ui/style.css` uses Tailwind theme/utilities only, not preflight:
113
+
114
+ ```css
115
+ @layer theme, utilities;
116
+
117
+ @import "tailwindcss/theme.css" layer(theme);
118
+ @import "tailwindcss/utilities.css" layer(utilities);
119
+
120
+ @source "./**/*.{ts,tsx}";
121
+ ```
122
+
123
+ ### SCSS, Sass, and Less
124
+
125
+ Install the preprocessor package in the plugin project, then create one of the
126
+ auto-loaded style files.
127
+
128
+ ```bash
129
+ npm i -D sass
130
+ ```
131
+
132
+ ```scss
133
+ /* ui/style.scss */
134
+ $accent: #3b82f6;
135
+
136
+ .panel {
137
+ border: 1px solid color-mix(in srgb, $accent 40%, transparent);
138
+
139
+ &__title {
140
+ color: $accent;
141
+ }
142
+ }
143
+ ```
144
+
145
+ For Less, install `less` and use `ui/style.less`.
146
+
147
+ ### Emotion
148
+
149
+ Emotion dependencies may be in `dependencies` or `devDependencies`; Vite can
150
+ bundle them when they are installed and imported by the plugin.
151
+
152
+ For `styled`, no Vite config change is needed:
153
+
154
+ ```bash
155
+ npm i @emotion/react @emotion/styled
156
+ ```
157
+
158
+ ```tsx
159
+ import styled from "@emotion/styled";
160
+
161
+ const Panel = styled.div({
162
+ display: "grid",
163
+ gap: 12,
164
+ });
165
+ ```
166
+
167
+ For Emotion's `css` prop, pass React plugin options through `muscat()` and add
168
+ `jsxImportSource` to `tsconfig.json`:
169
+
170
+ ```bash
171
+ npm i @emotion/react @emotion/styled
172
+ npm i -D @emotion/babel-plugin
173
+ ```
174
+
175
+ ```ts
176
+ // vite.config.ts
177
+ import { defineConfig } from "vite";
178
+ import tailwindcss from "@tailwindcss/vite";
179
+ import { muscat } from "@rainbow-robotics/muscat-plugin-kit/vite";
180
+
181
+ export default defineConfig({
182
+ plugins: [
183
+ tailwindcss(),
184
+ muscat({
185
+ react: {
186
+ jsxImportSource: "@emotion/react",
187
+ babel: {
188
+ plugins: ["@emotion/babel-plugin"],
189
+ },
190
+ },
191
+ }),
192
+ ],
193
+ });
194
+ ```
195
+
196
+ ```json
197
+ {
198
+ "compilerOptions": {
199
+ "jsxImportSource": "@emotion/react"
200
+ }
201
+ }
202
+ ```
203
+
204
+ Emotion `Global` writes global CSS at runtime, so scope it manually or avoid it
205
+ inside plugins.
206
+
23
207
  ## How it fits together
24
208
 
25
209
  - **Install/CLI package** is `@rainbow-robotics/muscat-plugin-kit`.
@@ -11,6 +11,11 @@ import { runUpdate } from "../src/update.mjs";
11
11
  import { runUninstall } from "../src/uninstall.mjs";
12
12
  import { runSdk } from "../src/sdk.mjs";
13
13
  import { runType } from "../src/type.mjs";
14
+ import { runStorybook } from "../src/storybook.mjs";
15
+ // mcp.mjs is dynamically imported below — it pulls in the MCP SDK + a full
16
+ // TypeScript program, and every other command would pay that cold-start cost
17
+ // on every invocation otherwise (see ros2.mjs/python.mjs/cpp.mjs for the same
18
+ // pattern in build.mjs).
14
19
 
15
20
  const [, , cmd, ...args] = process.argv;
16
21
 
@@ -25,6 +30,8 @@ Commands:
25
30
  dev Run Socket.IO bridge, dev:ui, and dev:back together
26
31
  dev:ui Preview the plugin in a mini-Muscat (preview-host)
27
32
  dev:back Run the plugin back end (python: watchfiles reload / ros2: Docker)
33
+ storybook Browse the bundled rb-components Storybook (--port <n>, --rebuild)
34
+ mcp Start an MCP server (stdio) exposing rb-components/rb SDK docs to AI agents
28
35
  update Update @rainbow-robotics/muscat-plugin-kit and @rainbow-robotics/plugin-ui
29
36
  uninstall Remove the installed muscat-pk CLI (npm global or S3 binary)
30
37
  sdk <list|update [version]> Manage the python rainbow-rb-sdk version
@@ -46,6 +53,12 @@ async function main() {
46
53
  return await runDevUi(args);
47
54
  case "dev:back":
48
55
  return await runDevBack(args);
56
+ case "storybook":
57
+ return await runStorybook(args);
58
+ case "mcp": {
59
+ const { runMcp } = await import("../src/mcp.mjs");
60
+ return await runMcp(args);
61
+ }
49
62
  case "update":
50
63
  return await runUpdate(args);
51
64
  case "uninstall":
@@ -0,0 +1,10 @@
1
+ // Runs on `npm publish` / `yarn npm publish` (and `npm pack`) via the "prepack"
2
+ // lifecycle hook. Builds the bundled Storybook (foundations + muscat) and stages
3
+ // it into cli/storybook-dist so it ships inside the published muscat-pk and
4
+ // `muscat-pk storybook` works from an external install.
5
+ //
6
+ // In the monorepo this runs the real build; outside it (re-packing an already
7
+ // published copy) buildStorybook() no-ops and the pre-staged dist is used.
8
+ import { buildStorybook } from "./src/storybook.mjs";
9
+
10
+ buildStorybook();
package/cli/src/build.mjs CHANGED
@@ -223,32 +223,6 @@ export async function pinRequirements(root, { stableOnly = false } = {}) {
223
223
  if (pinned > 0) writeFileSync(reqPath, out.join("\n"));
224
224
  }
225
225
 
226
- export const SANDBOX_HTML = `<!doctype html>
227
- <html lang="en">
228
- <head>
229
- <meta charset="UTF-8" />
230
- <title>plugin sandbox</title>
231
- <script type="importmap">
232
- {
233
- "imports": {
234
- "@rainbow-robotics/plugin-ui/connect": "/plugin-runtime/@rainbow-robotics/plugin-ui/connect.js",
235
- "@rainbow-robotics/plugin-ui/react": "/plugin-runtime/@rainbow-robotics/plugin-ui/react.js",
236
- "@rainbow-robotics/plugin-ui/sdk": "/plugin-runtime/@rainbow-robotics/plugin-ui/sdk.js",
237
- "@rainbow-robotics/plugin-ui/elements": "/plugin-runtime/@rainbow-robotics/plugin-ui/elements.js",
238
- "react": "/plugin-runtime/vendor/react.js",
239
- "react/jsx-runtime": "/plugin-runtime/vendor/react-jsx-runtime.js",
240
- "react/jsx-dev-runtime": "/plugin-runtime/vendor/react-jsx-dev-runtime.js",
241
- "react-dom/client": "/plugin-runtime/vendor/react-dom-client.js"
242
- }
243
- }
244
- </script>
245
- </head>
246
- <body>
247
- <script type="module" src="./content.js"></script>
248
- </body>
249
- </html>
250
- `;
251
-
252
226
  export async function buildPlugin({ root, minify = false } = {}) {
253
227
  const pluginRoot = root ?? findPluginRoot();
254
228
  assertManifest(pluginRoot);
@@ -280,9 +254,8 @@ export async function buildPlugin({ root, minify = false } = {}) {
280
254
  const manifestSrc = resolve(pluginRoot, "manifest.json");
281
255
  if (existsSync(manifestSrc)) copyFileSync(manifestSrc, resolve(distDir, "manifest.json"));
282
256
 
283
- // Generate sandbox.html — plugin authors don't manage this file.
284
- writeFileSync(resolve(distDir, "sandbox.html"), SANDBOX_HTML, "utf8");
285
- log.step("generated dist/sandbox.html");
257
+ // No sandbox.html: the host dynamically imports dist/{ui}.js directly as a
258
+ // plain ESM module (see @rainbow-robotics/plugin-ui/host) — no iframe.
286
259
 
287
260
  const assetsSrc = resolve(pluginRoot, "assets");
288
261
  if (existsSync(assetsSrc)) {
package/cli/src/dev.mjs CHANGED
@@ -2,12 +2,20 @@
2
2
  import { runDevUi } from "./devUi.mjs";
3
3
  import { runDevBack } from "./devBack.mjs";
4
4
  import { startBridge, stopBridge, BRIDGE_CONTAINER, BRIDGE_PORT } from "./bridge.mjs";
5
- import { ensureDocker, log, prompt, promptRobotConnection } from "./util.mjs";
5
+ import { assertManifestPorts } from "./manifest.mjs";
6
+ import { formatPortRanges } from "./ports.mjs";
7
+ import { ensureDocker, findPluginRoot, log, prompt, promptRobotConnection } from "./util.mjs";
6
8
 
7
9
  export async function runDev(args = []) {
10
+ const root = findPluginRoot();
11
+ const portRanges = assertManifestPorts(root);
12
+ if (portRanges.length > 0) {
13
+ log.step(`plugin backend ports declared: ${formatPortRanges(portRanges)}`);
14
+ process.env.MUSCAT_PK_PORTS_PRECHECKED = "1";
15
+ }
8
16
  ensureDocker();
9
17
  const { robotIp, robotToken } = await promptRobotConnection(args);
10
- if (robotIp) process.env.MUSCAT_ROBOT_HOST = robotIp;
18
+ process.env.MUSCAT_ROBOT_HOST = robotIp;
11
19
  if (robotToken) process.env.MUSCAT_ROBOT_TOKEN = robotToken;
12
20
  log.step("starting Socket.IO bridge (Docker) + dev:ui + dev:back");
13
21
  const bridgeStarted = await startBridge();
@@ -10,8 +10,13 @@
10
10
  import { spawn, spawnSync } from "node:child_process";
11
11
  import { existsSync, watch } from "node:fs";
12
12
  import { resolve } from "node:path";
13
- import { ensureDocker, findPluginRoot, log, promptRobotConnection } from "./util.mjs";
14
- import { manifestRuntime, readManifest, validateManifest } from "./manifest.mjs";
13
+ import { ensureDocker, ensureIdeVenv, findPluginRoot, log, promptRobotConnection } from "./util.mjs";
14
+ import { assertManifestPorts, manifestRuntime, readManifest, validateManifest } from "./manifest.mjs";
15
+ import {
16
+ formatPortRanges,
17
+ portEnvFlags,
18
+ startPortContractMonitor,
19
+ } from "./ports.mjs";
15
20
  import {
16
21
  PYTHON_DEV_IMAGE,
17
22
  assertDockerReady as pyAssertDockerReady,
@@ -29,11 +34,32 @@ import {
29
34
  ensureImage as cppEnsureImage,
30
35
  } from "./cpp.mjs";
31
36
 
37
+ // ── IDE tooling venv (best-effort, non-blocking) ────────────────────────────
38
+ // `muscat-pk new` already creates this up front (see new.mjs); this just
39
+ // refreshes it on every `dev`/`dev:back` in case requirements.txt changed.
40
+ // Docker remains the actual execution environment — this never affects it.
41
+ // Runs in the background so it never delays `dev:back` starting, and any
42
+ // failure here (no local Python toolchain, offline, ...) is silent.
43
+ function syncIdeVenv(root) {
44
+ setImmediate(() => {
45
+ try {
46
+ if (ensureIdeVenv(root)) {
47
+ log.info("IDE venv ready → .venv (point your editor's Python interpreter there for pylint/pyright)");
48
+ }
49
+ } catch {
50
+ /* best-effort only */
51
+ }
52
+ });
53
+ }
54
+
32
55
  // ── python ────────────────────────────────────────────────────────────────────
33
56
  // Runs in a warm Ubuntu 24.04 + Python 3.12 container (matches the robot).
34
57
  // Under `muscat-pk dev`, it shares the bridge container's netns, so the SDK
35
58
  // reaches the Socket.IO bridge at the default localhost:10000.
36
- async function runPython(root) {
59
+ async function runPython(root, portRanges) {
60
+ // Independent of Docker readiness — must still happen if Docker isn't
61
+ // installed/running, since that's exactly when local IDE tooling matters most.
62
+ syncIdeVenv(root);
37
63
  pyAssertDockerReady();
38
64
  await pyEnsureImage();
39
65
 
@@ -46,6 +72,7 @@ async function runPython(root) {
46
72
  ...(pluginId ? ["-e", `RB_PLUGIN_ID=${pluginId}`] : []),
47
73
  ...(robotIp ? ["-e", `MUSCAT_ROBOT_HOST=${robotIp}`] : []),
48
74
  ...(robotToken ? ["-e", `MUSCAT_ROBOT_TOKEN=${robotToken}`] : []),
75
+ ...portEnvFlags(portRanges),
49
76
  ];
50
77
  // Share the bridge container's network namespace so localhost:10000 is the
51
78
  // bridge (set by `muscat-pk dev`). Standalone dev:back has no bridge to join.
@@ -64,6 +91,7 @@ async function runPython(root) {
64
91
  { stdio: "inherit" },
65
92
  );
66
93
  if (up.status !== 0) throw new Error("failed to start dev container.");
94
+ const stopPortMonitor = startPortContractMonitor({ container, ranges: portRanges, log });
67
95
 
68
96
  log.step("pip install requirements + watchfiles (in container)…");
69
97
  docker(["exec", container, "bash", "-lc",
@@ -87,11 +115,13 @@ async function runPython(root) {
87
115
  });
88
116
 
89
117
  const cleanup = () => {
118
+ stopPortMonitor();
90
119
  if (!child.killed) child.kill();
91
120
  spawnSync("docker", ["rm", "-f", container], { stdio: "ignore" });
92
121
  process.exit(0);
93
122
  };
94
123
  child.on("exit", (code) => {
124
+ stopPortMonitor();
95
125
  spawnSync("docker", ["rm", "-f", container], { stdio: "ignore" });
96
126
  process.exit(code ?? 0);
97
127
  });
@@ -100,16 +130,20 @@ async function runPython(root) {
100
130
  }
101
131
 
102
132
  // ── ros2 ───────────────────────────────────────────────────────────────────────
103
- async function runRos2(root) {
133
+ async function runRos2(root, portRanges) {
134
+ const manifest = readManifest(root);
135
+ const isRclcpp = manifest.runtime?.rosClient === "rclcpp";
136
+ // Independent of Docker readiness — must still happen if Docker isn't
137
+ // installed/running, since that's exactly when local IDE tooling matters most.
138
+ if (!isRclcpp) syncIdeVenv(root); // rclpy is plain Python — rclcpp is C++, no venv needed
139
+
104
140
  assertDockerReady();
105
141
  const pkg = ros2PackageName(root);
106
142
  if (!pkg) throw new Error("no ROS2 package found under ros2_ws/src.");
107
143
 
108
144
  await ensureImage();
109
145
 
110
- const manifest = readManifest(root);
111
146
  const pluginId = manifest.id ?? "";
112
- const isRclcpp = manifest.runtime?.rosClient === "rclcpp";
113
147
  const container = `${ROS2_DEV_IMAGE}-run`;
114
148
  const robotIp = process.env.MUSCAT_ROBOT_HOST ?? "";
115
149
  const robotToken = process.env.MUSCAT_ROBOT_TOKEN ?? "";
@@ -117,6 +151,7 @@ async function runRos2(root) {
117
151
  ...(pluginId ? ["-e", `RB_PLUGIN_ID=${pluginId}`] : []),
118
152
  ...(robotIp ? ["-e", `MUSCAT_ROBOT_HOST=${robotIp}`] : []),
119
153
  ...(robotToken ? ["-e", `MUSCAT_ROBOT_TOKEN=${robotToken}`] : []),
154
+ ...portEnvFlags(portRanges),
120
155
  ];
121
156
  const docker = (args, opts = {}) =>
122
157
  spawnSync("docker", args, { cwd: root, stdio: "inherit", ...opts });
@@ -129,6 +164,7 @@ async function runRos2(root) {
129
164
  { stdio: "inherit" },
130
165
  );
131
166
  if (up.status !== 0) throw new Error("failed to start dev container.");
167
+ const stopPortMonitor = startPortContractMonitor({ container, ranges: portRanges, log });
132
168
 
133
169
  // one-time deps + symlink build (edits to .py reflect without rebuilding)
134
170
  log.step("pip install + colcon build --symlink-install (once)…");
@@ -170,6 +206,7 @@ async function runRos2(root) {
170
206
  }
171
207
 
172
208
  const cleanup = () => {
209
+ stopPortMonitor();
173
210
  if (child) child.kill();
174
211
  spawnSync("docker", ["rm", "-f", container], { stdio: "ignore" });
175
212
  process.exit(0);
@@ -179,7 +216,7 @@ async function runRos2(root) {
179
216
  }
180
217
 
181
218
  // ── cpp ──────────────────────────────────────────────────────────────────────
182
- async function runCpp(root) {
219
+ async function runCpp(root, portRanges) {
183
220
  cppAssertDockerReady();
184
221
  const manifest = readManifest(root);
185
222
  const entry = manifest.runtime?.entry;
@@ -195,6 +232,7 @@ async function runCpp(root) {
195
232
  ...(pluginId ? ["-e", `RB_PLUGIN_ID=${pluginId}`] : []),
196
233
  ...(robotIp ? ["-e", `MUSCAT_ROBOT_HOST=${robotIp}`] : []),
197
234
  ...(robotToken ? ["-e", `MUSCAT_ROBOT_TOKEN=${robotToken}`] : []),
235
+ ...portEnvFlags(portRanges),
198
236
  ];
199
237
  const docker = (args, opts = {}) =>
200
238
  spawnSync("docker", args, { cwd: root, stdio: "inherit", ...opts });
@@ -207,6 +245,7 @@ async function runCpp(root) {
207
245
  { stdio: "inherit" },
208
246
  );
209
247
  if (up.status !== 0) throw new Error("failed to start dev container.");
248
+ const stopPortMonitor = startPortContractMonitor({ container, ranges: portRanges, log });
210
249
 
211
250
  const build = () => {
212
251
  log.step("cmake build…");
@@ -243,6 +282,7 @@ async function runCpp(root) {
243
282
  if (existsSync(cppDir)) watch(cppDir, { recursive: true }, onChange);
244
283
 
245
284
  const cleanup = () => {
285
+ stopPortMonitor();
246
286
  if (child) child.kill();
247
287
  spawnSync("docker", ["rm", "-f", container], { stdio: "ignore" });
248
288
  process.exit(0);
@@ -259,14 +299,17 @@ function warnManifest(root) {
259
299
  }
260
300
 
261
301
  export async function runDevBack(args = []) {
262
- ensureDocker();
263
302
  const root = findPluginRoot();
264
303
  warnManifest(root);
304
+ const portRanges = assertManifestPorts(root);
305
+ if (portRanges.length > 0 && process.env.MUSCAT_PK_PORTS_PRECHECKED !== "1")
306
+ log.step(`plugin backend ports declared: ${formatPortRanges(portRanges)}`);
307
+ ensureDocker();
265
308
  const { robotIp, robotToken } = await promptRobotConnection(args);
266
309
  if (robotIp) process.env.MUSCAT_ROBOT_HOST = robotIp;
267
310
  if (robotToken) process.env.MUSCAT_ROBOT_TOKEN = robotToken;
268
311
  const type = manifestRuntime(root);
269
- if (type === "ros2") return await runRos2(root);
270
- if (type === "cpp") return await runCpp(root);
271
- return await runPython(root);
312
+ if (type === "ros2") return await runRos2(root, portRanges);
313
+ if (type === "cpp") return await runCpp(root, portRanges);
314
+ return await runPython(root, portRanges);
272
315
  }