@rainbow-robotics/muscat-plugin-kit 0.1.2-dev.9 → 0.10.1-dev.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.
- package/README.ko.md +1188 -0
- package/README.md +1139 -57
- package/cli/README.md +239 -7
- package/cli/bin/create-muscat-plugin.mjs +1 -1
- package/cli/bin/muscat-pk.mjs +123 -27
- package/cli/bundle-templates.mjs +31 -0
- package/cli/docker/Dockerfile.cpp +28 -0
- package/cli/docker/Dockerfile.dev +17 -0
- package/cli/docker/Dockerfile.python +21 -0
- package/cli/prepack.mjs +12 -0
- package/cli/program-commands.json +2079 -0
- package/cli/src/__pycache__/host_agent.cpython-37.pyc +0 -0
- package/cli/src/ai-rules.mjs +108 -0
- package/cli/src/build.mjs +333 -93
- package/cli/src/check-package.mjs +8 -23
- package/cli/src/completion.mjs +168 -0
- package/cli/src/cpp.mjs +78 -0
- package/cli/src/cppIde.mjs +76 -0
- package/cli/src/dev.mjs +195 -6
- package/cli/src/devBack.mjs +671 -60
- package/cli/src/devId.mjs +54 -0
- package/cli/src/devSession.mjs +67 -0
- package/cli/src/devUi.mjs +218 -25
- package/cli/src/esbuild.mjs +27 -10
- package/cli/src/host_agent.py +223 -0
- package/cli/src/manifest.mjs +288 -0
- package/cli/src/mcp.mjs +1232 -0
- package/cli/src/mcpProxy.mjs +110 -0
- package/cli/src/muscatLocal.mjs +292 -0
- package/cli/src/new.mjs +205 -68
- package/cli/src/pluginDevServer.mjs +111 -0
- package/cli/src/ports.mjs +193 -0
- package/cli/src/programCommands.mjs +327 -0
- package/cli/src/projectCheck.mjs +102 -0
- package/cli/src/python.mjs +112 -0
- package/cli/src/ros2.mjs +62 -18
- package/cli/src/sdk.mjs +74 -24
- package/cli/src/sim.mjs +177 -0
- package/cli/src/storybook.mjs +150 -0
- package/cli/src/templates-embedded.mjs +4 -0
- package/cli/src/type.mjs +93 -34
- package/cli/src/uninstall.mjs +81 -0
- package/cli/src/update.mjs +364 -35
- package/cli/src/util.mjs +341 -11
- package/cli/src/zenohDev.mjs +83 -0
- package/cli/src/zip.mjs +121 -0
- package/cli/storybook-dist/_design-tokens.css +4957 -0
- package/cli/storybook-dist/_stories-src/NxAvatar.stories.tsx +27 -0
- package/cli/storybook-dist/_stories-src/NxPagination.stories.tsx +28 -0
- package/cli/storybook-dist/_stories-src/RBAccordion/RBAccordion.stories.tsx +46 -0
- package/cli/storybook-dist/_stories-src/RBAccordion/RBAccordionGroup.stories.tsx +73 -0
- package/cli/storybook-dist/_stories-src/RBBadge/RBBadge.stories.tsx +93 -0
- package/cli/storybook-dist/_stories-src/RBBattery/RBBattery.stories.tsx +74 -0
- package/cli/storybook-dist/_stories-src/RBButton/RBCheckIconButton.stories.tsx +28 -0
- package/cli/storybook-dist/_stories-src/RBButton/RBCheckLabelButton.stories.tsx +84 -0
- package/cli/storybook-dist/_stories-src/RBButton/RBIconButton.stories.tsx +57 -0
- package/cli/storybook-dist/_stories-src/RBButton/RBInlineLabelButton.stories.tsx +41 -0
- package/cli/storybook-dist/_stories-src/RBButton/RBLabelButton.stories.tsx +60 -0
- package/cli/storybook-dist/_stories-src/RBDatePicker/RBDateInput.stories.tsx +44 -0
- package/cli/storybook-dist/_stories-src/RBDatePicker/RBRangeDateInput.stories.tsx +56 -0
- package/cli/storybook-dist/_stories-src/RBDialog/RBAlert.stories.tsx +51 -0
- package/cli/storybook-dist/_stories-src/RBDialog/RBConfirm.stories.tsx +55 -0
- package/cli/storybook-dist/_stories-src/RBDialog/RBPrompt.stories.tsx +52 -0
- package/cli/storybook-dist/_stories-src/RBDivider/RBDivider.stories.tsx +93 -0
- package/cli/storybook-dist/_stories-src/RBEmptyView/RBEmptyView.stories.tsx +49 -0
- package/cli/storybook-dist/_stories-src/RBIcons/RBColorIcons.stories.tsx +108 -0
- package/cli/storybook-dist/_stories-src/RBIcons/RBIcons.stories.tsx +106 -0
- package/cli/storybook-dist/_stories-src/RBInput/RBCheckBox.stories.tsx +89 -0
- package/cli/storybook-dist/_stories-src/RBInput/RBMultiRangeInput.stories.tsx +64 -0
- package/cli/storybook-dist/_stories-src/RBInput/RBRadioBox.stories.tsx +65 -0
- package/cli/storybook-dist/_stories-src/RBInput/RBRadioButton.stories.tsx +68 -0
- package/cli/storybook-dist/_stories-src/RBInput/RBSelectBox.stories.tsx +216 -0
- package/cli/storybook-dist/_stories-src/RBInput/RBSideNumberInput.stories.tsx +90 -0
- package/cli/storybook-dist/_stories-src/RBInput/RBText/RBTextArea.stories.tsx +45 -0
- package/cli/storybook-dist/_stories-src/RBInput/RBText/RBTextInput.stories.tsx +50 -0
- package/cli/storybook-dist/_stories-src/RBInput/RBTextField.stories.tsx +102 -0
- package/cli/storybook-dist/_stories-src/RBJoyStick/RBJoyStick.stories.tsx +31 -0
- package/cli/storybook-dist/_stories-src/RBLight/RBLight.stories.tsx +36 -0
- package/cli/storybook-dist/_stories-src/RBPagination/RBPagination.stories.tsx +49 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBCard/RBCard.stories.tsx +89 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBCommand/RBCommand.stories.tsx +116 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBDialog/RBDialog.stories.tsx +74 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBDrawer/RBDrawer.stories.tsx +99 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBDropdownMenu/RBDropdownMenu.stories.tsx +123 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBMenubar/RBMenubar.stories.tsx +135 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBPopover/RBPopover.stories.tsx +69 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBResizable/RBResizable.stories.tsx +49 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBSheet/RBSheet.stories.tsx +91 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBSlider/RBSlider.stories.tsx +38 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBSwitch/RBSwitch.stories.tsx +112 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBTabs/RBTabs.stories.tsx +75 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBToggle/RBToggle.stories.tsx +51 -0
- package/cli/storybook-dist/_stories-src/RBShadcn/RBToggleGroup/RBToggleGroup.stories.tsx +84 -0
- package/cli/storybook-dist/_stories-src/RBTab/RBChipTab.stories.tsx +102 -0
- package/cli/storybook-dist/_stories-src/RBTab/RBChipsBoxTab.stories.tsx +78 -0
- package/cli/storybook-dist/_stories-src/RBTab/RBTab.stories.tsx +57 -0
- package/cli/storybook-dist/_stories-src/RBTable/RBTable.stories.tsx +177 -0
- package/cli/storybook-dist/_stories-src/RBTable/RBTableRow.stories.tsx +64 -0
- package/cli/storybook-dist/_stories-src/RBToast/RBToast.stories.tsx +117 -0
- package/cli/storybook-dist/_stories-src/RBTooltip/RBTooltip.stories.tsx +50 -0
- package/cli/storybook-dist/_stories-src/loading/RBSpinner.stories.tsx +30 -0
- package/cli/storybook-dist/_stories-src/nx-button/NxButton.stories.tsx +54 -0
- package/cli/storybook-dist/_stories-src/nx-button/NxPointerHoldButton.stories.tsx +57 -0
- package/cli/storybook-dist/_stories-src/nx-icons/NxIcons.stories.tsx +48 -0
- package/cli/storybook-dist/_stories-src/nx-inputs/NxNumberInput.stories.tsx +103 -0
- package/cli/storybook-dist/_stories-src/nx-inputs/NxRangeInput.stories.tsx +27 -0
- package/cli/storybook-dist/_stories-src/nx-inputs/NxSelectBox.stories.tsx +67 -0
- package/cli/storybook-dist/_stories-src/nx-inputs/NxSlideRange.stories.tsx +45 -0
- package/cli/storybook-dist/_stories-src/nx-inputs/NxSwitch.stories.tsx +27 -0
- package/cli/storybook-dist/_stories-src/nx-inputs/NxTextArea.stories.tsx +48 -0
- package/cli/storybook-dist/_stories-src/nx-inputs/NxTextInput.stories.tsx +46 -0
- package/cli/storybook-dist/assets/Color-YHDXOIA2-pCKrjUal.js +1 -0
- package/cli/storybook-dist/assets/Docs-B-Y7I1GA.js +7 -0
- package/cli/storybook-dist/assets/Docs-BFJcE_VS.js +8 -0
- package/cli/storybook-dist/assets/Docs-B_QaTtz8.js +8 -0
- package/cli/storybook-dist/assets/Docs-CryDGmfh.js +20 -0
- package/cli/storybook-dist/assets/Docs-Cw2AVNKx.js +7 -0
- package/cli/storybook-dist/assets/Docs-Q6r1fBeL.js +12 -0
- package/cli/storybook-dist/assets/DocsRenderer-CFRXHY34-_OmZBCn8.js +2 -0
- package/cli/storybook-dist/assets/NxAvatar.stories-Ctf5G2FQ.js +13 -0
- package/cli/storybook-dist/assets/NxButton.stories-DeLObVSj.js +20 -0
- package/cli/storybook-dist/assets/NxIcons.stories-DeqrVzVs.js +3 -0
- package/cli/storybook-dist/assets/NxNumberInput.stories-LqoY0ed1.js +26 -0
- package/cli/storybook-dist/assets/NxPagination.stories-DI6bXuJM.js +11 -0
- package/cli/storybook-dist/assets/NxPointerHoldButton.stories-3HSV1XmN.js +14 -0
- package/cli/storybook-dist/assets/NxRangeInput.stories-1pjgQVaG.js +17 -0
- package/cli/storybook-dist/assets/NxSelectBox.stories-bcQPZEuF.js +17 -0
- package/cli/storybook-dist/assets/NxSlideRange.stories-BosX4axk.js +14 -0
- package/cli/storybook-dist/assets/NxSwitch.stories-DxV6dS33.js +11 -0
- package/cli/storybook-dist/assets/NxTextArea.stories-CO545-LP.js +11 -0
- package/cli/storybook-dist/assets/NxTextInput.stories-BP0npai1.js +11 -0
- package/cli/storybook-dist/assets/PretendardVariable-CJuje-Rk.woff2 +0 -0
- package/cli/storybook-dist/assets/RBAccordion.stories-fVR4Va2a.js +17 -0
- package/cli/storybook-dist/assets/RBAccordionGroup.stories-Du5bsckD.js +33 -0
- package/cli/storybook-dist/assets/RBAlert.stories-DNkMXUu6.js +17 -0
- package/cli/storybook-dist/assets/RBBadge.stories-C44pXt8D.js +1 -0
- package/cli/storybook-dist/assets/RBBattery.stories-DE2JHvfL.js +10 -0
- package/cli/storybook-dist/assets/RBCard.stories-CuIda7NI.js +45 -0
- package/cli/storybook-dist/assets/RBCheckBox.stories-D1qM1ayr.js +1 -0
- package/cli/storybook-dist/assets/RBCheckIconButton.stories-e4gkliBO.js +1 -0
- package/cli/storybook-dist/assets/RBCheckLabelButton.stories-CDzCtsMI.js +24 -0
- package/cli/storybook-dist/assets/RBChipTab.stories-DBrc_3Mp.js +21 -0
- package/cli/storybook-dist/assets/RBChipsBoxTab.stories-hlrsHjKY.js +1 -0
- package/cli/storybook-dist/assets/RBColorIcons.stories-BHUvpkdu.js +3 -0
- package/cli/storybook-dist/assets/RBCommand.stories-azAF41NP.js +73 -0
- package/cli/storybook-dist/assets/RBConfirm.stories-BMNjwbmT.js +20 -0
- package/cli/storybook-dist/assets/RBDateInput.stories-D0VezDzv.js +15 -0
- package/cli/storybook-dist/assets/RBDialog.stories-AOJ975Fy.js +38 -0
- package/cli/storybook-dist/assets/RBDivider.stories-NSvnj43Z.js +1 -0
- package/cli/storybook-dist/assets/RBDrawer.stories-Du0oTvD1.js +14 -0
- package/cli/storybook-dist/assets/RBDropdownMenu.stories-Hsxve4PW.js +86 -0
- package/cli/storybook-dist/assets/RBEmptyView.stories-BlwHx3zp.js +12 -0
- package/cli/storybook-dist/assets/RBIconButton.stories-DAPDY63x.js +1 -0
- package/cli/storybook-dist/assets/RBIcons.stories-W5ZUV2L1.js +3 -0
- package/cli/storybook-dist/assets/RBInlineLabelButton.stories-C99j0Y3g.js +1 -0
- package/cli/storybook-dist/assets/RBJoyStick.stories-Du0H1iAS.js +11 -0
- package/cli/storybook-dist/assets/RBLabelButton.stories-BlvHaU_Z.js +1 -0
- package/cli/storybook-dist/assets/RBLight.stories-BY6DKrre.js +1 -0
- package/cli/storybook-dist/assets/RBMenubar.stories-D2PEGpM9.js +3 -0
- package/cli/storybook-dist/assets/RBMultiRangeInput.stories-Bm2qSmjq.js +14 -0
- package/cli/storybook-dist/assets/RBPagination.stories-DDleJa5N.js +17 -0
- package/cli/storybook-dist/assets/RBPopover.stories-27YxPSFG.js +11 -0
- package/cli/storybook-dist/assets/RBPrompt.stories-BFaIOctr.js +20 -0
- package/cli/storybook-dist/assets/RBRadioBox.stories-BroDar0t.js +1 -0
- package/cli/storybook-dist/assets/RBRadioButton.stories-M3O-wX7V.js +11 -0
- package/cli/storybook-dist/assets/RBRangeDateInput.stories-CWlM_D5X.js +15 -0
- package/cli/storybook-dist/assets/RBResizable.stories-ui8X1qnc.js +20 -0
- package/cli/storybook-dist/assets/RBSelectBox.stories-C8T6cfA0.js +74 -0
- package/cli/storybook-dist/assets/RBSheet.stories-BCOo_Zcc.js +39 -0
- package/cli/storybook-dist/assets/RBSideNumberInput.stories-CU2_MVlJ.js +5 -0
- package/cli/storybook-dist/assets/RBSlider.stories-DgOp1TFc.js +5 -0
- package/cli/storybook-dist/assets/RBSpinner.stories-qLScY3zZ.js +14 -0
- package/cli/storybook-dist/assets/RBSwitch.stories-SXSY1QMb.js +65 -0
- package/cli/storybook-dist/assets/RBTab.stories-BzXXTsXP.js +1 -0
- package/cli/storybook-dist/assets/RBTable.stories-DHTeRNVk.js +62 -0
- package/cli/storybook-dist/assets/RBTableRow.stories-DRNRsd15.js +11 -0
- package/cli/storybook-dist/assets/RBTabs.stories-DP0noBLp.js +21 -0
- package/cli/storybook-dist/assets/RBTextArea.stories-TkaejfxJ.js +5 -0
- package/cli/storybook-dist/assets/RBTextField.stories-B6VpCGyt.js +45 -0
- package/cli/storybook-dist/assets/RBTextInput.stories-D3hZ08e-.js +5 -0
- package/cli/storybook-dist/assets/RBToast.stories-BQ2wS2U0.js +11 -0
- package/cli/storybook-dist/assets/RBToggle.stories-GVOjGqo3.js +12 -0
- package/cli/storybook-dist/assets/RBToggleGroup.stories-pzx0btOD.js +17 -0
- package/cli/storybook-dist/assets/RBTooltip.stories-jufB6fa1.js +9 -0
- package/cli/storybook-dist/assets/SideNumberInput-BYlmNHEw.js +1109 -0
- package/cli/storybook-dist/assets/SideNumberInput-SAkhydsn.css +21 -0
- package/cli/storybook-dist/assets/browserUtils-CQM9Za7e.js +1 -0
- package/cli/storybook-dist/assets/chunk-XP5HYGXS-BHXC9YeQ.js +1 -0
- package/cli/storybook-dist/assets/client-DTf7SId2.js +1 -0
- package/cli/storybook-dist/assets/entry-preview-CAkU-e0D.js +2 -0
- package/cli/storybook-dist/assets/entry-preview-docs-b8bpVBXy.js +46 -0
- package/cli/storybook-dist/assets/iframe-B-BmTsxV.js +211 -0
- package/cli/storybook-dist/assets/index-B4FGfHer.js +1 -0
- package/cli/storybook-dist/assets/index-BRq5TIsn.js +24 -0
- package/cli/storybook-dist/assets/index-CT3U1fyk.js +1 -0
- package/cli/storybook-dist/assets/index-ChsGqxH_.js +9 -0
- package/cli/storybook-dist/assets/index-CkB0GfaI.js +575 -0
- package/cli/storybook-dist/assets/index-ClAc6FBW.js +240 -0
- package/cli/storybook-dist/assets/index-DKFBREX_.js +1 -0
- package/cli/storybook-dist/assets/index-DgH-xKnr.js +11 -0
- package/cli/storybook-dist/assets/index-Dmy2JGbm.js +1 -0
- package/cli/storybook-dist/assets/index-DrFu-skq.js +6 -0
- package/cli/storybook-dist/assets/jsx-runtime-BTJTZTIL.js +9 -0
- package/cli/storybook-dist/assets/preview-B8lJiyuQ.js +34 -0
- package/cli/storybook-dist/assets/preview-BBWR9nbA.js +1 -0
- package/cli/storybook-dist/assets/preview-BVJwlGUF.js +1 -0
- package/cli/storybook-dist/assets/preview-BWzBA1C2.js +396 -0
- package/cli/storybook-dist/assets/preview-CVgpLj3b.js +1 -0
- package/cli/storybook-dist/assets/preview-CvbIS5ZJ.js +1 -0
- package/cli/storybook-dist/assets/preview-CznQwwbo.js +3 -0
- package/cli/storybook-dist/assets/preview-DD_OYowb.js +1 -0
- package/cli/storybook-dist/assets/preview-DGUiP6tS.js +7 -0
- package/cli/storybook-dist/assets/preview-DHQbi4pV.js +1 -0
- package/cli/storybook-dist/assets/preview-M77JRg1A.js +2 -0
- package/cli/storybook-dist/assets/preview-kTZPgP6D.css +1 -0
- package/cli/storybook-dist/assets/react-18-hB3smqWJ.js +1 -0
- package/cli/storybook-dist/assets/react-resizable-panels-HsFbxPbn.css +1 -0
- package/cli/storybook-dist/assets/react-resizable-panels.browser-DuxpZLkF.js +120 -0
- package/cli/storybook-dist/assets/test-utils-BQudk2xt.js +9 -0
- package/cli/storybook-dist/favicon.svg +1 -0
- package/cli/storybook-dist/iframe.html +666 -0
- package/cli/storybook-dist/index.html +190 -0
- package/cli/storybook-dist/index.json +1 -0
- package/cli/storybook-dist/nunito-sans-bold-italic.woff2 +0 -0
- package/cli/storybook-dist/nunito-sans-bold.woff2 +0 -0
- package/cli/storybook-dist/nunito-sans-italic.woff2 +0 -0
- package/cli/storybook-dist/nunito-sans-regular.woff2 +0 -0
- package/cli/storybook-dist/project.json +1 -0
- package/cli/storybook-dist/sb-addons/chromatic-com-storybook-10/manager-bundle.js +331 -0
- package/cli/storybook-dist/sb-addons/chromatic-com-storybook-10/manager-bundle.js.LEGAL.txt +51 -0
- package/cli/storybook-dist/sb-addons/essentials-actions-3/manager-bundle.js +3 -0
- package/cli/storybook-dist/sb-addons/essentials-backgrounds-5/manager-bundle.js +12 -0
- package/cli/storybook-dist/sb-addons/essentials-controls-2/manager-bundle.js +405 -0
- package/cli/storybook-dist/sb-addons/essentials-docs-4/manager-bundle.js +245 -0
- package/cli/storybook-dist/sb-addons/essentials-measure-8/manager-bundle.js +3 -0
- package/cli/storybook-dist/sb-addons/essentials-outline-9/manager-bundle.js +3 -0
- package/cli/storybook-dist/sb-addons/essentials-toolbars-7/manager-bundle.js +3 -0
- package/cli/storybook-dist/sb-addons/essentials-viewport-6/manager-bundle.js +3 -0
- package/cli/storybook-dist/sb-addons/links-1/manager-bundle.js +3 -0
- package/cli/storybook-dist/sb-addons/storybook-13/manager-bundle.js +3 -0
- package/cli/storybook-dist/sb-addons/storybook-core-core-server-presets-0/common-manager-bundle.js +3 -0
- package/cli/storybook-dist/sb-addons/storybook-experimental-addon-test-12/manager-bundle.js +223 -0
- package/cli/storybook-dist/sb-addons/themes-11/manager-bundle.js +3 -0
- package/cli/storybook-dist/sb-common-assets/favicon.svg +1 -0
- package/cli/storybook-dist/sb-common-assets/nunito-sans-bold-italic.woff2 +0 -0
- package/cli/storybook-dist/sb-common-assets/nunito-sans-bold.woff2 +0 -0
- package/cli/storybook-dist/sb-common-assets/nunito-sans-italic.woff2 +0 -0
- package/cli/storybook-dist/sb-common-assets/nunito-sans-regular.woff2 +0 -0
- package/cli/storybook-dist/sb-manager/globals-module-info.js +1052 -0
- package/cli/storybook-dist/sb-manager/globals-runtime.js +41775 -0
- package/cli/storybook-dist/sb-manager/globals.js +48 -0
- package/cli/storybook-dist/sb-manager/runtime.js +12048 -0
- package/cli/templates/common/README.md +1070 -83
- package/cli/templates/common/assets/icon.svg +44 -2
- package/cli/templates/common/manifest.json +14 -13
- package/cli/templates/common/package.json +11 -4
- package/cli/templates/common/py/main.py +125 -0
- package/cli/templates/common/requirements.txt +4 -3
- package/cli/templates/common/tsconfig.json +1 -1
- package/cli/templates/common/ui/content.tsx +216 -0
- package/cli/templates/common/ui/style.css +6 -0
- package/cli/templates/common/vite.config.ts +6 -25
- package/cli/templates/cpp/cpp/CMakeLists.txt +14 -0
- package/cli/templates/cpp/cpp/main.cpp +73 -0
- package/cli/templates/readme-cpp/README.md +1012 -0
- package/cli/templates/ros2/ros2_ws/src/__PLUGIN_SLUG__/__PLUGIN_SLUG__/node.py +12 -1
- package/cli/templates/ros2-cpp/ros2_ws/src/__PLUGIN_SLUG__/CMakeLists.txt +22 -0
- package/cli/templates/ros2-cpp/ros2_ws/src/__PLUGIN_SLUG__/package.xml +11 -0
- package/cli/templates/ros2-cpp/ros2_ws/src/__PLUGIN_SLUG__/src/node.cpp +41 -0
- package/cli/vite.d.mts +25 -0
- package/cli/vite.mjs +292 -0
- package/package.json +34 -7
- package/cli/src/pack.mjs +0 -61
- package/cli/src/preview.mjs +0 -91
- package/cli/templates/common/main.py +0 -114
- package/cli/templates/common/src/content.tsx +0 -33
package/cli/src/type.mjs
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
// muscat-pk type change — switch an existing plugin's backend type.
|
|
2
|
-
// python
|
|
3
|
-
// the
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
2
|
+
// python | cpp | ros2 (rclpy) | ros2-cpp (rclcpp).
|
|
3
|
+
// Adds the matching backend overlay; never deletes existing user code
|
|
4
|
+
// (e.g. ros2_ws/ or cpp/ are left in place when switching away).
|
|
5
|
+
import { copyFileSync, existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import { basename, join, resolve } from "node:path";
|
|
8
|
+
import { findPluginRoot, log, prompt, templatesDir } from "./util.mjs";
|
|
9
|
+
import {
|
|
10
|
+
TYPE_CHOICES,
|
|
11
|
+
applyTokens,
|
|
12
|
+
copyTemplate,
|
|
13
|
+
deriveNames,
|
|
14
|
+
overlayCpp,
|
|
15
|
+
overlayRos2,
|
|
16
|
+
prepareCppIde,
|
|
17
|
+
runtimeForChoice,
|
|
18
|
+
} from "./new.mjs";
|
|
9
19
|
|
|
10
|
-
const TYPES =
|
|
11
|
-
|
|
12
|
-
async function prompt(question, fallback) {
|
|
13
|
-
if (!process.stdin.isTTY) return fallback;
|
|
14
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
15
|
-
const answer = (await rl.question(question)).trim();
|
|
16
|
-
rl.close();
|
|
17
|
-
return answer || fallback;
|
|
18
|
-
}
|
|
20
|
+
const TYPES = Object.keys(TYPE_CHOICES);
|
|
19
21
|
|
|
20
22
|
function readManifest(root) {
|
|
21
23
|
const path = resolve(root, "manifest.json");
|
|
@@ -23,45 +25,77 @@ function readManifest(root) {
|
|
|
23
25
|
return { path, json: JSON.parse(readFileSync(path, "utf8")) };
|
|
24
26
|
}
|
|
25
27
|
|
|
28
|
+
// Derive the current `--type`-style key from a manifest runtime block.
|
|
29
|
+
function currentTypeKey(runtime) {
|
|
30
|
+
if (runtime?.type === "ros2") return runtime.rosClient === "rclcpp" ? "ros2-cpp" : "ros2";
|
|
31
|
+
return runtime?.type ?? "python";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const isCpp = (key) => key === "cpp" || key === "ros2-cpp";
|
|
35
|
+
|
|
36
|
+
async function offerReadme(root, toCpp, force, tokens) {
|
|
37
|
+
const lang = toCpp ? "C++" : "Python";
|
|
38
|
+
const answer = force ? "y" : await prompt(`Replace README.md with the ${lang} backend version? (current file kept as README.md.bak) [y/N]: `, "n");
|
|
39
|
+
if (!/^y/i.test(answer)) {
|
|
40
|
+
log.info(`README.md kept — to swap it later: muscat-pk type change --to <type> --readme`);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const tmp = mkdtempSync(join(tmpdir(), "muscat-pk-readme-"));
|
|
44
|
+
try {
|
|
45
|
+
await copyTemplate(resolve(templatesDir, toCpp ? "readme-cpp" : "common"), tmp);
|
|
46
|
+
applyTokens(tmp, tokens);
|
|
47
|
+
const readme = resolve(root, "README.md");
|
|
48
|
+
if (existsSync(readme)) copyFileSync(readme, resolve(root, "README.md.bak"));
|
|
49
|
+
copyFileSync(join(tmp, "README.md"), readme);
|
|
50
|
+
log.ok(`README.md → ${lang} version${existsSync(resolve(root, "README.md.bak")) ? " (previous file: README.md.bak)" : ""}`);
|
|
51
|
+
} finally {
|
|
52
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
26
56
|
export async function runType(args) {
|
|
27
|
-
// accept `type change`, `type`, `type --to ros2`
|
|
57
|
+
// accept `type change`, `type`, `type --to ros2-cpp`
|
|
28
58
|
const sub = args[0];
|
|
29
59
|
const toFlagIdx = args.indexOf("--to");
|
|
30
60
|
let to = toFlagIdx >= 0 ? args[toFlagIdx + 1] : undefined;
|
|
31
61
|
|
|
32
62
|
const root = findPluginRoot();
|
|
33
63
|
const { path, json } = readManifest(root);
|
|
34
|
-
const current = json.runtime
|
|
64
|
+
const current = currentTypeKey(json.runtime);
|
|
35
65
|
|
|
36
66
|
if (sub && sub !== "change") {
|
|
37
|
-
log.warn(`unknown subcommand '${sub}'. Usage: muscat-pk type change [--to python|ros2]`);
|
|
67
|
+
log.warn(`unknown subcommand '${sub}'. Usage: muscat-pk type change [--to python|cpp|ros2|ros2-cpp] [--readme]`);
|
|
38
68
|
}
|
|
39
69
|
|
|
40
70
|
if (!to) {
|
|
41
|
-
console.log(`\
|
|
42
|
-
console.log("
|
|
71
|
+
console.log(`\nCurrent type: ${current}`);
|
|
72
|
+
console.log("Select the new type:");
|
|
43
73
|
console.log(" 1) Python");
|
|
44
|
-
console.log(" 2)
|
|
45
|
-
|
|
46
|
-
|
|
74
|
+
console.log(" 2) C++");
|
|
75
|
+
console.log(" 3) ROS2 (rclpy / Python)");
|
|
76
|
+
console.log(" 4) ROS2 (rclcpp / C++)");
|
|
77
|
+
const choice = await prompt("\nChoice [1/2/3/4]: ", "");
|
|
78
|
+
to = { "1": "python", "2": "cpp", "3": "ros2", "4": "ros2-cpp" }[choice];
|
|
47
79
|
}
|
|
48
80
|
|
|
49
81
|
if (!TYPES.includes(to)) {
|
|
50
|
-
throw new Error(`invalid type. choose python
|
|
82
|
+
throw new Error(`invalid type. choose python | cpp | ros2 | ros2-cpp.`);
|
|
51
83
|
}
|
|
52
84
|
if (to === current) {
|
|
53
85
|
log.info(`already '${current}' — nothing to change.`);
|
|
54
86
|
return;
|
|
55
87
|
}
|
|
56
88
|
|
|
57
|
-
|
|
58
|
-
|
|
89
|
+
const runtimeChoice = TYPE_CHOICES[to];
|
|
90
|
+
const { dir, slug, pluginName, pluginClass, pluginId } = deriveNames(root);
|
|
91
|
+
|
|
92
|
+
if (runtimeChoice.type === "ros2") {
|
|
59
93
|
if (existsSync(resolve(root, "ros2_ws"))) {
|
|
60
94
|
log.warn("ros2_ws/ already exists — keeping it, only flipping manifest type.");
|
|
61
95
|
} else {
|
|
62
|
-
log.step(
|
|
63
|
-
overlayRos2(root, slug);
|
|
64
|
-
applyTokens(root, {
|
|
96
|
+
log.step(`adding ros2_ws/ overlay (${runtimeChoice.rosClient})`);
|
|
97
|
+
await overlayRos2(root, slug, runtimeChoice.rosClient);
|
|
98
|
+
applyTokens(resolve(root, "ros2_ws"), {
|
|
65
99
|
__PLUGIN_ID__: pluginId,
|
|
66
100
|
__PLUGIN_NAME__: pluginName,
|
|
67
101
|
__PLUGIN_SLUG__: slug,
|
|
@@ -69,14 +103,39 @@ export async function runType(args) {
|
|
|
69
103
|
__RUNTIME_TYPE__: "ros2",
|
|
70
104
|
});
|
|
71
105
|
}
|
|
106
|
+
} else if (runtimeChoice.type === "cpp") {
|
|
107
|
+
if (existsSync(resolve(root, "cpp"))) {
|
|
108
|
+
log.warn("cpp/ already exists — keeping it, only flipping manifest type.");
|
|
109
|
+
} else {
|
|
110
|
+
log.step("adding cpp/ overlay");
|
|
111
|
+
await overlayCpp(root);
|
|
112
|
+
applyTokens(resolve(root, "cpp"), {
|
|
113
|
+
__PLUGIN_ID__: pluginId,
|
|
114
|
+
__PLUGIN_NAME__: pluginName,
|
|
115
|
+
__PLUGIN_SLUG__: slug,
|
|
116
|
+
__PLUGIN_CLASS__: pluginClass,
|
|
117
|
+
__RUNTIME_TYPE__: "cpp",
|
|
118
|
+
});
|
|
119
|
+
}
|
|
72
120
|
} else {
|
|
73
|
-
//
|
|
74
|
-
if (existsSync(resolve(root, "ros2_ws"))) {
|
|
75
|
-
log.warn("
|
|
121
|
+
// → python. Leave any ros2_ws/ or cpp/ in place (never delete user code).
|
|
122
|
+
if (existsSync(resolve(root, "ros2_ws")) || existsSync(resolve(root, "cpp"))) {
|
|
123
|
+
log.warn("existing backend dir left in place (not deleted). Remove it manually if unused.");
|
|
76
124
|
}
|
|
77
125
|
}
|
|
78
126
|
|
|
79
|
-
json.runtime =
|
|
127
|
+
json.runtime = runtimeForChoice(runtimeChoice, slug);
|
|
80
128
|
writeFileSync(path, JSON.stringify(json, null, 2) + "\n");
|
|
81
129
|
log.ok(`${basename(root)} type: ${current} → ${to}`);
|
|
130
|
+
if (isCpp(to)) await prepareCppIde(root, runtimeChoice);
|
|
131
|
+
|
|
132
|
+
if (isCpp(current) !== isCpp(to)) {
|
|
133
|
+
await offerReadme(root, isCpp(to), args.includes("--readme"), {
|
|
134
|
+
__PLUGIN_ID__: pluginId,
|
|
135
|
+
__PLUGIN_NAME__: pluginName,
|
|
136
|
+
__PLUGIN_DIR__: dir,
|
|
137
|
+
__PLUGIN_SLUG__: slug,
|
|
138
|
+
__PLUGIN_CLASS__: pluginClass,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
82
141
|
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// muscat-pk uninstall - remove the installed CLI, whether npm-global or S3 binary.
|
|
2
|
+
import { execSync, spawn, spawnSync } from "node:child_process";
|
|
3
|
+
import { existsSync, rmSync } from "node:fs";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { KIT_PUBLISHED_NAME, isNpmGlobalInstall, log, parseArgs } from "./util.mjs";
|
|
6
|
+
|
|
7
|
+
const isBinaryMode = typeof Bun !== "undefined";
|
|
8
|
+
|
|
9
|
+
function uninstallNpmGlobal() {
|
|
10
|
+
log.step(`npm uninstall -g ${KIT_PUBLISHED_NAME}`);
|
|
11
|
+
execSync(`npm uninstall -g ${KIT_PUBLISHED_NAME}`, { stdio: "inherit" });
|
|
12
|
+
log.ok("Global npm package removed.");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function uninstallBinary() {
|
|
16
|
+
const execPath = process.execPath;
|
|
17
|
+
log.step(`Removing binary: ${execPath}`);
|
|
18
|
+
|
|
19
|
+
if (process.platform === "win32") {
|
|
20
|
+
const ps = `Start-Sleep -Milliseconds 500; Remove-Item -Force '${execPath}'`;
|
|
21
|
+
spawn("powershell", ["-NoProfile", "-Command", ps], {
|
|
22
|
+
detached: true,
|
|
23
|
+
stdio: "ignore",
|
|
24
|
+
}).unref();
|
|
25
|
+
log.ok("Binary will be removed after this process exits.");
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
rmSync(execPath, { force: true });
|
|
31
|
+
} catch (err) {
|
|
32
|
+
if (err?.code !== "EACCES" && err?.code !== "EPERM") throw err;
|
|
33
|
+
log.info(" sudo is required...");
|
|
34
|
+
const result = spawnSync("sudo", ["rm", "-f", execPath], { stdio: "inherit" });
|
|
35
|
+
if (result.status !== 0) throw new Error(`sudo rm failed: ${execPath}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const parent = dirname(execPath);
|
|
39
|
+
for (const shim of ["muscat-pk.cmd", "muscat-pk.ps1"]) {
|
|
40
|
+
rmSync(join(parent, shim), { force: true });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
log.ok("Binary removed.");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function runUninstall(args = []) {
|
|
47
|
+
const opts = parseArgs(args, { booleans: ["help"] });
|
|
48
|
+
|
|
49
|
+
if (opts.help) {
|
|
50
|
+
log.info(
|
|
51
|
+
[
|
|
52
|
+
"Usage: muscat-pk uninstall",
|
|
53
|
+
"",
|
|
54
|
+
"Removes the installed muscat-pk CLI.",
|
|
55
|
+
" npm global install -> npm uninstall -g @rainbow-robotics/muscat-plugin-kit",
|
|
56
|
+
" S3 binary install -> remove the muscat-pk executable",
|
|
57
|
+
].join("\n"),
|
|
58
|
+
);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (isBinaryMode) {
|
|
63
|
+
uninstallBinary();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (isNpmGlobalInstall()) {
|
|
68
|
+
uninstallNpmGlobal();
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const localBin = process.argv[1] || "";
|
|
73
|
+
if (localBin.includes(`${join("node_modules", ".bin")}`) || existsSync(join(process.cwd(), "package.json"))) {
|
|
74
|
+
log.warn("This muscat-pk appears to be running from a project/local install.");
|
|
75
|
+
log.warn("Remove it from the project package manager instead, for example:");
|
|
76
|
+
log.warn(` npm uninstall ${KIT_PUBLISHED_NAME}`);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
throw new Error("Could not determine install mode. Remove muscat-pk manually from your PATH.");
|
|
81
|
+
}
|
package/cli/src/update.mjs
CHANGED
|
@@ -1,52 +1,381 @@
|
|
|
1
|
-
// muscat-pk update — update the
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
// muscat-pk update — update the CLI itself AND the plugin project's JS deps.
|
|
2
|
+
//
|
|
3
|
+
// Three install modes are handled:
|
|
4
|
+
// binary : Bun self-contained binary downloaded from S3
|
|
5
|
+
// → re-download from S3, replace process.execPath
|
|
6
|
+
// npm -g : globally installed Node.js package
|
|
7
|
+
// → npm install -g @rainbow-robotics/muscat-plugin-kit@<tag>
|
|
8
|
+
// local : plugin project's node_modules (fallback)
|
|
9
|
+
// → <pm> add @rainbow-robotics/muscat-plugin-kit@<tag>
|
|
10
|
+
//
|
|
11
|
+
// After updating the CLI itself, also bumps the plugin project's local deps
|
|
12
|
+
// and migrates the project structure if it's outdated (src/ → ui/, root main.py → py/).
|
|
13
|
+
import { execSync, spawn, spawnSync } from "node:child_process";
|
|
14
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
15
|
+
import { join, resolve } from "node:path";
|
|
16
|
+
import { agentsMd, CLAUDE_MD, MCP_JSON } from "./ai-rules.mjs";
|
|
17
|
+
import { checkProject, formatProjectCheck } from "./projectCheck.mjs";
|
|
18
|
+
import {
|
|
19
|
+
compareKitVersions, findPluginRoot, isLocalKitInstall, KIT_PUBLISHED_NAME, kitVersion, log, parseArgs, prompt,
|
|
20
|
+
resolveLocalCliBin,
|
|
21
|
+
} from "./util.mjs";
|
|
6
22
|
|
|
7
23
|
const PLUGIN_UI_PACKAGE = "@rainbow-robotics/plugin-ui";
|
|
24
|
+
const PREVIEW_HOST_PACKAGE = "@rainbow-robotics/preview-host";
|
|
25
|
+
const S3_BASE = "https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit";
|
|
26
|
+
|
|
27
|
+
const isBinaryMode = typeof Bun !== "undefined";
|
|
28
|
+
|
|
29
|
+
// ── helpers ───────────────────────────────────────────────────────────────────
|
|
8
30
|
|
|
9
31
|
function detectPm(root) {
|
|
10
32
|
try {
|
|
11
33
|
const pkg = JSON.parse(readFileSync(resolve(root, "package.json"), "utf8"));
|
|
12
34
|
if (pkg.packageManager) return pkg.packageManager.split("@")[0];
|
|
13
|
-
} catch {
|
|
14
|
-
/* ignore */
|
|
15
|
-
}
|
|
35
|
+
} catch { /* ignore */ }
|
|
16
36
|
if (existsSync(resolve(root, "pnpm-lock.yaml"))) return "pnpm";
|
|
17
37
|
if (existsSync(resolve(root, "yarn.lock"))) return "yarn";
|
|
18
38
|
if (existsSync(resolve(root, "bun.lockb"))) return "bun";
|
|
19
39
|
return "npm";
|
|
20
40
|
}
|
|
21
41
|
|
|
22
|
-
|
|
23
|
-
const
|
|
42
|
+
async function fetchText(url) {
|
|
43
|
+
const res = await fetch(url);
|
|
44
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}: ${url}`);
|
|
45
|
+
return (await res.text()).trim();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function fetchBinary(url) {
|
|
49
|
+
const res = await fetch(url);
|
|
50
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}: ${url}`);
|
|
51
|
+
return Buffer.from(await res.arrayBuffer());
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function s3BinaryName() {
|
|
55
|
+
const platform = process.platform;
|
|
56
|
+
const arch = process.arch;
|
|
57
|
+
const plat = platform === "win32" ? "win" : platform === "darwin" ? "darwin" : "linux";
|
|
58
|
+
const cpu = arch === "arm64" ? "arm64" : "x64";
|
|
59
|
+
const ext = platform === "win32" ? ".exe" : "";
|
|
60
|
+
return `muscat-pk-${plat}-${cpu}${ext}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function resolveS3Version(tag) {
|
|
64
|
+
const pointer = tag === "dev" ? "dev-version.txt" : "latest-version.txt";
|
|
65
|
+
return fetchText(`${S3_BASE}/${pointer}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ── self-update: binary ───────────────────────────────────────────────────────
|
|
69
|
+
|
|
70
|
+
async function updateBinary(tag) {
|
|
71
|
+
const version = await resolveS3Version(tag);
|
|
72
|
+
const current = kitVersion();
|
|
73
|
+
if (version === current) {
|
|
74
|
+
log.ok(`Already up to date (v${current})`);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const binaryName = s3BinaryName();
|
|
79
|
+
const url = `${S3_BASE}/v${version}/${binaryName}`;
|
|
80
|
+
log.step(`Downloading binary: v${current} → v${version}`);
|
|
81
|
+
|
|
82
|
+
const data = await fetchBinary(url);
|
|
83
|
+
const execPath = process.execPath;
|
|
84
|
+
|
|
85
|
+
if (process.platform === "win32") {
|
|
86
|
+
// Windows: cannot overwrite a running .exe — write .new then schedule replacement
|
|
87
|
+
const newPath = execPath + ".new";
|
|
88
|
+
writeFileSync(newPath, data);
|
|
89
|
+
|
|
90
|
+
// PowerShell snippet that waits for this process to exit, then renames
|
|
91
|
+
const ps = `Start-Sleep -Milliseconds 500; Move-Item -Force '${newPath}' '${execPath}'`;
|
|
92
|
+
spawn("powershell", ["-NoProfile", "-Command", ps], {
|
|
93
|
+
detached: true,
|
|
94
|
+
stdio: "ignore",
|
|
95
|
+
}).unref();
|
|
96
|
+
|
|
97
|
+
log.ok(`v${version} will be applied on next run.`);
|
|
98
|
+
} else {
|
|
99
|
+
// macOS / Linux: 실행 중인 파일에 덮어쓰면 Linux 는 ETXTBSY. 같은 디렉토리에 쓰고 rename 으로 바꿔치기한다.
|
|
100
|
+
const newPath = execPath + ".new";
|
|
101
|
+
writeFileSync(newPath, data);
|
|
102
|
+
chmodSync(newPath, 0o755);
|
|
103
|
+
try {
|
|
104
|
+
renameSync(newPath, execPath);
|
|
105
|
+
} catch (err) {
|
|
106
|
+
if (err?.code !== "EACCES" && err?.code !== "EPERM") throw err;
|
|
107
|
+
log.info(" sudo is required...");
|
|
108
|
+
const r = spawnSync("sudo", ["mv", "-f", newPath, execPath], { stdio: "inherit" });
|
|
109
|
+
if (r.status !== 0) throw new Error(`sudo mv failed: ${execPath}`);
|
|
110
|
+
}
|
|
111
|
+
log.ok(`Updated to v${version}.`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// ── self-update: npm global ───────────────────────────────────────────────────
|
|
116
|
+
|
|
117
|
+
function updateNpmGlobal(tag) {
|
|
118
|
+
log.step(`npm install -g ${KIT_PUBLISHED_NAME}@${tag}`);
|
|
119
|
+
execSync(`npm install -g ${KIT_PUBLISHED_NAME}@${tag}`, { stdio: "inherit" });
|
|
120
|
+
log.ok("Global CLI updated.");
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ── project structure migration ───────────────────────────────────────────────
|
|
124
|
+
|
|
125
|
+
function detectOldStructure(root) {
|
|
126
|
+
const issues = [];
|
|
127
|
+
|
|
128
|
+
// src/ exists (old UI dir) or vite.config references src/content.tsx
|
|
129
|
+
const hasSrcDir = existsSync(resolve(root, "src"));
|
|
130
|
+
const hasUiDir = existsSync(resolve(root, "ui"));
|
|
131
|
+
const viteRef = (() => {
|
|
132
|
+
try {
|
|
133
|
+
return readFileSync(resolve(root, "vite.config.ts"), "utf8").includes("src/content.tsx");
|
|
134
|
+
} catch { return false; }
|
|
135
|
+
})();
|
|
136
|
+
if ((hasSrcDir || viteRef) && !hasUiDir) {
|
|
137
|
+
issues.push({ kind: "src→ui", desc: "src/ → ui/ (+ vite.config.ts, tsconfig.json)" });
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (existsSync(resolve(root, "main.py")) && !existsSync(resolve(root, "py"))) {
|
|
141
|
+
issues.push({ kind: "main→py", desc: "main.py → py/main.py" });
|
|
142
|
+
}
|
|
143
|
+
if (existsSync(resolve(root, "backend"))) {
|
|
144
|
+
issues.push({ kind: "backend→py", desc: "backend/ → py/" });
|
|
145
|
+
}
|
|
146
|
+
return issues;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function migrateStructure(root, issues) {
|
|
150
|
+
log.warn("This plugin project's structure is outdated:");
|
|
151
|
+
for (const issue of issues) log.info(" • " + issue.desc);
|
|
152
|
+
log.warn("Files will be moved and modified. Back up or commit your work before proceeding.");
|
|
153
|
+
|
|
154
|
+
const answer = await prompt("Migrate project structure? [y/N] ");
|
|
155
|
+
if (answer.toLowerCase() !== "y") {
|
|
156
|
+
log.info("Structure migration skipped.");
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
for (const issue of issues) {
|
|
161
|
+
if (issue.kind === "src→ui") {
|
|
162
|
+
if (existsSync(resolve(root, "src"))) {
|
|
163
|
+
renameSync(resolve(root, "src"), resolve(root, "ui"));
|
|
164
|
+
log.ok("src/ → ui/");
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const vitePath = resolve(root, "vite.config.ts");
|
|
168
|
+
if (existsSync(vitePath)) {
|
|
169
|
+
writeFileSync(vitePath, readFileSync(vitePath, "utf8").replace(/["']src\/content\.tsx["']/g, '"ui/content.tsx"'));
|
|
170
|
+
log.ok("vite.config.ts entry updated");
|
|
171
|
+
}
|
|
172
|
+
const tscPath = resolve(root, "tsconfig.json");
|
|
173
|
+
if (existsSync(tscPath)) {
|
|
174
|
+
writeFileSync(tscPath, readFileSync(tscPath, "utf8").replace(/"src"/g, '"ui"'));
|
|
175
|
+
log.ok("tsconfig.json include updated");
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (issue.kind === "main→py") {
|
|
180
|
+
mkdirSync(resolve(root, "py"), { recursive: true });
|
|
181
|
+
renameSync(resolve(root, "main.py"), resolve(root, "py", "main.py"));
|
|
182
|
+
log.ok("main.py → py/main.py");
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (issue.kind === "backend→py") {
|
|
186
|
+
renameSync(resolve(root, "backend"), resolve(root, "py"));
|
|
187
|
+
log.ok("backend/ → py/");
|
|
188
|
+
const pyReqs = resolve(root, "py", "requirements.txt");
|
|
189
|
+
const rootReqs = resolve(root, "requirements.txt");
|
|
190
|
+
if (existsSync(pyReqs) && !existsSync(rootReqs)) {
|
|
191
|
+
renameSync(pyReqs, rootReqs);
|
|
192
|
+
log.ok("py/requirements.txt → requirements.txt (project root)");
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
log.ok("Migration complete. Run `muscat-pk build` to verify.");
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ── plugin project local deps ─────────────────────────────────────────────────
|
|
201
|
+
|
|
202
|
+
// The three packages are released together on one version, so preview-host moves with the other
|
|
203
|
+
// two — left behind, an old pin keeps serving a preview that no longer matches plugin-ui.
|
|
204
|
+
function updateLocalDeps(root, tag) {
|
|
24
205
|
const pm = detectPm(root);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
`${
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
execSync(cmd, { cwd: root, stdio: "inherit" });
|
|
48
|
-
log.ok("kit packages updated");
|
|
206
|
+
let pkg = {};
|
|
207
|
+
try {
|
|
208
|
+
pkg = JSON.parse(readFileSync(resolve(root, "package.json"), "utf8"));
|
|
209
|
+
} catch { /* ignore */ }
|
|
210
|
+
const listed = (name) => Boolean(pkg.dependencies?.[name] || pkg.devDependencies?.[name]);
|
|
211
|
+
const names = [KIT_PUBLISHED_NAME, PLUGIN_UI_PACKAGE, ...(listed(PREVIEW_HOST_PACKAGE) ? [PREVIEW_HOST_PACKAGE] : [])];
|
|
212
|
+
const isDev = (name) => Boolean(pkg.devDependencies?.[name]);
|
|
213
|
+
const add = (list, dev) => {
|
|
214
|
+
const flag = dev ? " -D" : "";
|
|
215
|
+
return pm === "npm" ? `npm install${flag} ${list.join(" ")}` : `${pm} add${flag} ${list.join(" ")}`;
|
|
216
|
+
};
|
|
217
|
+
// Keep each package in the section it is already in (yarn/pnpm `add` would move devDeps).
|
|
218
|
+
const cmds = [false, true]
|
|
219
|
+
.map((dev) => [names.filter((n) => isDev(n) === dev).map((n) => `${n}@${tag}`), dev])
|
|
220
|
+
.filter(([list]) => list.length)
|
|
221
|
+
.map(([list, dev]) => add(list, dev));
|
|
222
|
+
|
|
223
|
+
log.step(`Updating plugin local deps (${pm}): ${names.map((n) => `${n}@${tag}`).join(", ")}`);
|
|
224
|
+
try {
|
|
225
|
+
for (const cmd of cmds) execSync(cmd, { cwd: root, stdio: "inherit" });
|
|
226
|
+
log.ok("Local deps updated.");
|
|
49
227
|
} catch {
|
|
50
|
-
log.warn("update failed (offline?). Run manually:\n " +
|
|
228
|
+
log.warn("Local deps update failed (offline?). Run manually:\n " + cmds.join("\n "));
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const PROJECT_CHECK_HEADER = "This project needs changes for the updated plugin-ui. Fix these before `muscat-pk dev` / `build`:";
|
|
233
|
+
|
|
234
|
+
function reportProject(root) {
|
|
235
|
+
const lines = formatProjectCheck(checkProject(root));
|
|
236
|
+
if (!lines.length) return;
|
|
237
|
+
log.warn(PROJECT_CHECK_HEADER);
|
|
238
|
+
for (const l of lines) log.info(l);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** `muscat-pk update:check` — the post-update project check, run by the freshly installed kit. */
|
|
242
|
+
export async function runUpdateCheck() {
|
|
243
|
+
reportProject(findPluginRoot());
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Prefer the kit update just installed: it knows the plugin-ui it shipped with, this process may not.
|
|
247
|
+
function checkProjectAfterUpdate(root) {
|
|
248
|
+
const localBin = resolveLocalCliBin(root);
|
|
249
|
+
let localVersion = "";
|
|
250
|
+
try {
|
|
251
|
+
localVersion = JSON.parse(readFileSync(resolve(localBin, "../../../package.json"), "utf8")).version;
|
|
252
|
+
} catch { /* no local kit */ }
|
|
253
|
+
if (localBin && localVersion && compareKitVersions(localVersion, kitVersion()) >= 0) {
|
|
254
|
+
const runtime = isBinaryMode ? "node" : process.execPath;
|
|
255
|
+
const r = spawnSync(runtime, [localBin, "update:check"], { cwd: root, stdio: "inherit" });
|
|
256
|
+
if (!r.error && r.status === 0) return;
|
|
257
|
+
}
|
|
258
|
+
reportProject(root);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// ── AI agent files ────────────────────────────────────────────────────────────
|
|
262
|
+
// Projects made before `new` scaffolded these have no MCP server or agent rules, so an agent asked
|
|
263
|
+
// to fix the update can't call check_project. Only missing files are written; edited ones stay.
|
|
264
|
+
|
|
265
|
+
function pluginNameOf(root) {
|
|
266
|
+
try {
|
|
267
|
+
const { name } = JSON.parse(readFileSync(resolve(root, "manifest.json"), "utf8"));
|
|
268
|
+
if (typeof name === "string") return name;
|
|
269
|
+
if (name && typeof name === "object") return name.en ?? Object.values(name)[0] ?? "";
|
|
270
|
+
} catch { /* fall through */ }
|
|
271
|
+
return "";
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function ensureAiFiles(root) {
|
|
275
|
+
const files = {
|
|
276
|
+
".mcp.json": () => MCP_JSON,
|
|
277
|
+
"AGENTS.md": () => agentsMd({ pluginName: pluginNameOf(root) || "Plugin" }),
|
|
278
|
+
"CLAUDE.md": () => CLAUDE_MD,
|
|
279
|
+
};
|
|
280
|
+
for (const [file, content] of Object.entries(files)) {
|
|
281
|
+
if (existsSync(resolve(root, file))) continue;
|
|
282
|
+
writeFileSync(resolve(root, file), content());
|
|
283
|
+
log.ok(`${file} added (MCP server / AI agent rules)`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// ── main ─────────────────────────────────────────────────────────────────────
|
|
288
|
+
|
|
289
|
+
async function resolveTag(explicitTag) {
|
|
290
|
+
if (explicitTag) return explicitTag;
|
|
291
|
+
|
|
292
|
+
const current = kitVersion();
|
|
293
|
+
const isDevVersion = current.includes("-dev.");
|
|
294
|
+
|
|
295
|
+
if (!isDevVersion) return "latest";
|
|
296
|
+
|
|
297
|
+
const answer = await prompt(
|
|
298
|
+
`You are on a dev version (v${current}).\n` +
|
|
299
|
+
` [1] Stay on dev — update to latest dev build\n` +
|
|
300
|
+
` [2] Switch to stable — update to latest stable release\n` +
|
|
301
|
+
`Choice [1/2, default: 1]: `
|
|
302
|
+
);
|
|
303
|
+
return answer.trim() === "2" ? "latest" : "dev";
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export async function runUpdate(args = []) {
|
|
307
|
+
const opts = parseArgs(args, { booleans: ["global"] });
|
|
308
|
+
const explicitTag = opts._[0] || opts.version || opts.tag || "";
|
|
309
|
+
const tag = await resolveTag(explicitTag);
|
|
310
|
+
|
|
311
|
+
// 지금 도는 게 프로젝트의 로컬 설치면 그 프로젝트만 건드린다. 이 머신의 다른
|
|
312
|
+
// 프로젝트들이 쓰는 글로벌 CLI까지 같이 올리려면 --global을 명시해야 한다.
|
|
313
|
+
const runningLocal = isLocalKitInstall() || process.env.MUSCAT_PK_UPDATE_PROJECT_ONLY === "1";
|
|
314
|
+
|
|
315
|
+
// 1. Update the CLI itself
|
|
316
|
+
if (!runningLocal || opts.global) {
|
|
317
|
+
if (isBinaryMode) {
|
|
318
|
+
log.step("Updating binary…");
|
|
319
|
+
try {
|
|
320
|
+
await updateBinary(tag);
|
|
321
|
+
} catch (err) {
|
|
322
|
+
log.warn(`Binary update failed: ${err.message}`);
|
|
323
|
+
}
|
|
324
|
+
} else {
|
|
325
|
+
const isGlobal = (() => {
|
|
326
|
+
try {
|
|
327
|
+
const prefix = execSync("npm prefix -g", { encoding: "utf8" }).trim();
|
|
328
|
+
return (
|
|
329
|
+
// Unix: {prefix}/bin/muscat-pk
|
|
330
|
+
existsSync(join(prefix, "bin", "muscat-pk")) ||
|
|
331
|
+
// Windows npm: {prefix}/muscat-pk.cmd (no bin/ subdir)
|
|
332
|
+
existsSync(join(prefix, "muscat-pk.cmd")) ||
|
|
333
|
+
existsSync(join(prefix, "bin", "muscat-pk.cmd"))
|
|
334
|
+
);
|
|
335
|
+
} catch { return false; }
|
|
336
|
+
})();
|
|
337
|
+
|
|
338
|
+
if (isGlobal) {
|
|
339
|
+
try {
|
|
340
|
+
updateNpmGlobal(tag);
|
|
341
|
+
} catch (err) {
|
|
342
|
+
log.warn(`Global CLI update failed: ${err.message}`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
} else {
|
|
347
|
+
log.info("Local install detected — updating this project only. Pass --global to also update the global CLI.");
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// 2. Plugin project: structure migration + local deps
|
|
351
|
+
let root;
|
|
352
|
+
try {
|
|
353
|
+
root = findPluginRoot();
|
|
354
|
+
} catch {
|
|
355
|
+
// Not inside a plugin project — skip
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
try {
|
|
360
|
+
const structureIssues = detectOldStructure(root);
|
|
361
|
+
if (structureIssues.length > 0) {
|
|
362
|
+
await migrateStructure(root, structureIssues);
|
|
363
|
+
}
|
|
364
|
+
} catch (err) {
|
|
365
|
+
log.warn(`Structure check failed: ${err.message}`);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
try {
|
|
369
|
+
ensureAiFiles(root);
|
|
370
|
+
} catch (err) {
|
|
371
|
+
log.warn(`AI agent files: ${err.message}`);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
updateLocalDeps(root, tag);
|
|
375
|
+
|
|
376
|
+
try {
|
|
377
|
+
checkProjectAfterUpdate(root);
|
|
378
|
+
} catch (err) {
|
|
379
|
+
log.warn(`Project check failed: ${err.message}`);
|
|
51
380
|
}
|
|
52
381
|
}
|