@runeya/runeya 2.0.137 → 2.0.139

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 (402) hide show
  1. package/agent/index.js +36 -10
  2. package/agent/index.js.map +1 -1
  3. package/agent-manager-NAGIMH2T.js +11 -0
  4. package/chat-Q2UMYXQL.js +21 -0
  5. package/{chunk-ZFELQG4B.js → chunk-EV3TBM7E.js} +78 -5
  6. package/chunk-EV3TBM7E.js.map +1 -0
  7. package/{chunk-FJLMXLMK.js → chunk-GLIU3J47.js} +354 -128
  8. package/chunk-GLIU3J47.js.map +1 -0
  9. package/{chunk-BDQOBEZ3.js → chunk-GOMF7NWS.js} +2 -2
  10. package/{desktop-launcher-3COY6F6H.js → chunk-GWQV5KKU.js} +193 -13
  11. package/chunk-GWQV5KKU.js.map +1 -0
  12. package/{chunk-5EMEJNVU.js → chunk-LE6XQ3OV.js} +13 -1
  13. package/chunk-LE6XQ3OV.js.map +1 -0
  14. package/{chunk-J4GLFY7G.js → chunk-MSICJEZD.js} +5 -5
  15. package/{chunk-NURPXHLB.js → chunk-OZBSOSAS.js} +26 -12
  16. package/chunk-OZBSOSAS.js.map +1 -0
  17. package/{chunk-P65BO7WZ.js → chunk-WNCXZ6E7.js} +165 -125
  18. package/chunk-WNCXZ6E7.js.map +1 -0
  19. package/{chunk-I7JHF5FE.js → chunk-XHGJHYDC.js} +4 -4
  20. package/chunk-YSYLL57J.js +87 -0
  21. package/chunk-YSYLL57J.js.map +1 -0
  22. package/{companion-Q67RAO3N.js → companion-MGX62L4T.js} +9 -7
  23. package/desktop-installer-page-OJTOKP7V.js +598 -0
  24. package/desktop-installer-page-OJTOKP7V.js.map +1 -0
  25. package/desktop-launcher-HKXP4LRI.js +43 -0
  26. package/desktop-wizard-XIDDAG7L.js +15 -0
  27. package/index.js +30 -21
  28. package/index.js.map +1 -1
  29. package/mcp-server/index.js +49 -1
  30. package/mcp-server/index.js.map +1 -1
  31. package/{node-4UUJN2WG.js → node-RN4URNZ5.js} +4 -4
  32. package/package.json +1 -1
  33. package/settings-manager-BBNCDDQJ.js +10 -0
  34. package/settings-manager-BBNCDDQJ.js.map +1 -0
  35. package/{src-7O3GCEIB.js → src-KWLVQD36.js} +193 -92
  36. package/src-KWLVQD36.js.map +1 -0
  37. package/{vault-resolver-57Q2DVOR.js → vault-resolver-B5P2OUI5.js} +20 -2
  38. package/vault-resolver-B5P2OUI5.js.map +1 -0
  39. package/web/assets/AgentScalarChatInterface.vue-CqGVVIo8.js +13 -0
  40. package/web/assets/AgentTerminalPage-mVD1jsWC.js +1 -0
  41. package/web/assets/AiChatPage-J-JAXhoT.js +1 -0
  42. package/web/assets/AppLayout-6eKmu_TP.css +1 -0
  43. package/web/assets/AppLayout-CsUnvWA0.js +1 -0
  44. package/web/assets/AuditPage-gzMJbY4c.js +1 -0
  45. package/web/assets/CloudAccountPage-CIUmdyoI.js +1 -0
  46. package/web/assets/CloudAccountPage-Cm1ibhZY.js +1 -0
  47. package/web/assets/CloudAccountPage-eoNciq1Q.css +1 -0
  48. package/web/assets/CloudMessagingPage-EV4MwYrk.js +2 -0
  49. package/web/assets/DashboardPage-CrMccWRA.js +1 -0
  50. package/web/assets/DirectoryPickerDialog-Cnr4SkLc.js +1 -0
  51. package/web/assets/DirectoryPickerDialog-D1lQ83i5.css +1 -0
  52. package/web/assets/{EditorIcon-DXYoMZnL.js → EditorIcon-Dlr9ami0.js} +2 -2
  53. package/web/assets/{EnvironmentForm-D3pZuxVn.js → EnvironmentForm-NiG4dzT9.js} +2 -2
  54. package/web/assets/EnvironmentFormPage-TJzOWwS7.js +1 -0
  55. package/web/assets/EnvironmentListPage-oR335kl1.js +1 -0
  56. package/web/assets/KanbanBoardPage-Cta-iCIL.css +1 -0
  57. package/web/assets/KanbanBoardPage-Dol6K6rI.js +4 -0
  58. package/web/assets/KanbanListPage-C2yhMB2L.js +1 -0
  59. package/web/assets/{KanbanListPage-DxJFx6A6.css → KanbanListPage-CEJ9Vluh.css} +1 -1
  60. package/web/assets/LaunchProjectPage-BGIRMKdM.js +1 -0
  61. package/web/assets/LaunchProjectPage-CU2iF25_.css +1 -0
  62. package/web/assets/LaunchServicesPage-9aAno4Gc.css +1 -0
  63. package/web/assets/LaunchServicesPage-DqIG8ZDk.js +1 -0
  64. package/web/assets/LaunchShell-C7RrqA4k.js +1 -0
  65. package/web/assets/LaunchShell-CGtjrl6_.css +1 -0
  66. package/web/assets/LogViewer-BWtCyqa4.js +3 -0
  67. package/web/assets/OrgKeyPrompt-B343sYVi.css +1 -0
  68. package/web/assets/OrgKeyPrompt-IjlZPHOI.js +1 -0
  69. package/web/assets/OrgLogo-B0TayK5W.js +1 -0
  70. package/web/assets/ProcessControls-Bw28Duzs.js +1 -0
  71. package/web/assets/ProcessDetailPage-CVYQJ4aI.js +1 -0
  72. package/web/assets/{ProcessMetrics-CdQc_8Z0.js → ProcessMetrics-D0HzDnGO.js} +3 -3
  73. package/web/assets/ProjectCreateDialog-CLFPf8ds.js +1 -0
  74. package/web/assets/ProjectCreateDialog-UEIYMerY.css +1 -0
  75. package/web/assets/ProjectLocationGate-D68jdBcV.js +1 -0
  76. package/web/assets/ProjectPublishDialog-CDpS6xcQ.css +1 -0
  77. package/web/assets/ProjectPublishDialog-Cvvjeuyq.js +1 -0
  78. package/web/assets/RandomJobTestPage-CuUJfwwb.js +2 -0
  79. package/web/assets/ScenarioEditorPage-Ckq6XNl2.js +14 -0
  80. package/web/assets/SendToChatDialog-4a4_2amD.js +1 -0
  81. package/web/assets/ServiceControlsBar-OC7cDCM7.js +1 -0
  82. package/web/assets/ServiceDetailPage-BMlS1q4i.js +2 -0
  83. package/web/assets/ServiceFormPage-CozmJNy1.js +1 -0
  84. package/web/assets/{SettingsPage-DA7lVKfg.css → SettingsPage-CF548HPl.css} +1 -1
  85. package/web/assets/SettingsPage-CkJQwWCW.js +2063 -0
  86. package/web/assets/UnlockPage-94m6Ap-H.js +1 -0
  87. package/web/assets/VaultMigrationPage-Bj6KgIUi.js +1 -0
  88. package/web/assets/VersionBadge-DjTAz-tn.js +1 -0
  89. package/web/assets/WikiPage-n_vxXevo.js +1 -0
  90. package/web/assets/WikiView-lxEITfCa.js +1 -0
  91. package/web/assets/add-scalar-classes-lFkCrmFv.js +387 -0
  92. package/web/assets/{autocomplete-DobAPPYJ.js → autocomplete-bClqtFV-.js} +3 -3
  93. package/web/assets/{basic-shape-diamond.svg-FbeAPLc-.js → basic-shape-diamond.svg-DFdUK3gN.js} +1 -1
  94. package/web/assets/{basic-shape-hexagon.svg-CtwcdpTe.js → basic-shape-hexagon.svg-BKiT9xxU.js} +1 -1
  95. package/web/assets/{basic-shape-primary-circle-ellipse-round.svg-DsSs3S2_.js → basic-shape-primary-circle-ellipse-round.svg-tmXcRxRQ.js} +1 -1
  96. package/web/assets/{basic-shape-primary-square-rectangle.svg-CNe1RNx8.js → basic-shape-primary-square-rectangle.svg-C9duFSNc.js} +1 -1
  97. package/web/assets/{basic-shape-shield.svg-DwZMLfah.js → basic-shape-shield.svg-CLzO94DF.js} +1 -1
  98. package/web/assets/{browser-Dz1gvldT.js → browser-BEDlGGfe.js} +1 -1
  99. package/web/assets/{browser-DsZ9HxVm.js → browser-CivlztYP.js} +1 -1
  100. package/web/assets/card-wcTFC8yG.js +32 -0
  101. package/web/assets/{checkbox-DPknldTJ.js → checkbox-TtO_mmrY.js} +2 -2
  102. package/web/assets/{chevronup-D2Lr2GiV.js → chevronup-Cd93cHVj.js} +4 -4
  103. package/web/assets/{chip-Caiakd-N.js → chip-omKmLLWH.js} +2 -2
  104. package/web/assets/client-BKIls6aD.js +24 -0
  105. package/web/assets/cloud-chat.store-Bskr_EXO.js +1 -0
  106. package/web/assets/cloud-client-rcfqjfUK.js +1 -0
  107. package/web/assets/cloud-session-CycNU7YV.js +1 -0
  108. package/web/assets/cloud-session-DiaAeCJI.js +2 -0
  109. package/web/assets/column-DgtEciO-.js +763 -0
  110. package/web/assets/composables-Ce8WccBy.js +1 -0
  111. package/web/assets/{computer-device-desktop-monitor.svg-CwiGN14T.js → computer-device-desktop-monitor.svg-D3YaocxY.js} +1 -1
  112. package/web/assets/{computer-device-desktop.svg-BC2VdXDZ.js → computer-device-desktop.svg-lnn_cyCx.js} +1 -1
  113. package/web/assets/{computer-device-laptop.svg-BOp8AKN6.js → computer-device-laptop.svg-9f5_Ipnq.js} +1 -1
  114. package/web/assets/{computer-device-mobile-phone-android-samsung-back.svg-CmbpPX1u.js → computer-device-mobile-phone-android-samsung-back.svg-DxHwZI5u.js} +1 -1
  115. package/web/assets/{computer-device-mobile-phone-android-samsung.svg-_WGKWVtZ.js → computer-device-mobile-phone-android-samsung.svg-CnYqoXt4.js} +1 -1
  116. package/web/assets/{computer-device-mobile-phone-iphone-x-back.svg-DmLh97KG.js → computer-device-mobile-phone-iphone-x-back.svg-D8JfsF_0.js} +1 -1
  117. package/web/assets/{computer-device-mobile-phone-iphone-x.svg-C7-5mdyV.js → computer-device-mobile-phone-iphone-x.svg-CUbRWc7v.js} +1 -1
  118. package/web/assets/{computer-device-mobile-tablet-touch.svg-DiUaSnhU.js → computer-device-mobile-tablet-touch.svg-CBX2kbI1.js} +1 -1
  119. package/web/assets/{computer-device-mobile-tablet.svg-B6nfbYm_.js → computer-device-mobile-tablet.svg-CIn05KEg.js} +1 -1
  120. package/web/assets/{computer-device-network-ethernet-cat6.svg-DwtVKy79.js → computer-device-network-ethernet-cat6.svg-Dj0GRqXd.js} +1 -1
  121. package/web/assets/{computer-device-network-lan-www.svg-vQKfG3Xz.js → computer-device-network-lan-www.svg-D-G7js6t.js} +1 -1
  122. package/web/assets/{computer-device-network-wifi-connection.svg-DhHaOUge.js → computer-device-network-wifi-connection.svg-JnvMwBMA.js} +1 -1
  123. package/web/assets/{computer-device-network-wifi-router.svg-1dQS4k4J.js → computer-device-network-wifi-router.svg--XxSrk_J.js} +1 -1
  124. package/web/assets/{cssMode-CdQL22W5.js → cssMode-C3gHbz_w.js} +1 -1
  125. package/web/assets/{divider-DhYR4BAO.js → divider-eMI33mv1.js} +2 -2
  126. package/web/assets/{docx-preview-D-jP_CCs.js → docx-preview-CTkzTOcl.js} +1 -1
  127. package/web/assets/{ecology-science-erlenmeyer-flask.svg-D76wQVA2.js → ecology-science-erlenmeyer-flask.svg-DrHKX7bH.js} +1 -1
  128. package/web/assets/{fieldset-BtOjs_Hh.js → fieldset-CiIJH8Xe.js} +2 -2
  129. package/web/assets/{freemarker2-BADW9vhy.js → freemarker2-DWxB7Wcd.js} +1 -1
  130. package/web/assets/{handlebars-CwWQD_C8.js → handlebars-CWUdFsNH.js} +1 -1
  131. package/web/assets/{html-y87CEbe3.js → html-DhvF7iHg.js} +1 -1
  132. package/web/assets/{htmlMode-CVagtvVh.js → htmlMode-CIuDa6YW.js} +1 -1
  133. package/web/assets/{image-flash-lightning.svg-OvpKi3a3.js → image-flash-lightning.svg-qFK_1eYx.js} +1 -1
  134. package/web/assets/{image-picture-flower.svg-DLOePozT.js → image-picture-flower.svg-qAmkHnOu.js} +1 -1
  135. package/web/assets/{index-CcIrffU_.js → index-CzSAFmCu.js} +363 -363
  136. package/web/assets/index-D0IPNhsg.css +1 -0
  137. package/web/assets/{interface-alert-exclamation-diamond.svg-4Vk7SoQ1.js → interface-alert-exclamation-diamond.svg-Dugh0ymo.js} +1 -1
  138. package/web/assets/{interface-alert-exclamation-triangle-warning.svg-BLAvc4am.js → interface-alert-exclamation-triangle-warning.svg-8neoRFVP.js} +1 -1
  139. package/web/assets/{interface-alert-information-circle.svg-CaAXpDAI.js → interface-alert-information-circle.svg-DM9S7DBv.js} +1 -1
  140. package/web/assets/{interface-award-crown.svg-CW7XG0wx.js → interface-award-crown.svg--68HCcUG.js} +1 -1
  141. package/web/assets/{interface-bookmark.svg-BpLEuOv2.js → interface-bookmark-tag.svg-BESGrlZw.js} +1 -1
  142. package/web/assets/{interface-bookmark-tag.svg-DPWVVeZU.js → interface-bookmark.svg-CVadIwuA.js} +1 -1
  143. package/web/assets/{interface-calendar-date-one.svg-DbBgvI4W.js → interface-calendar-date-one.svg-D9XP9Dv_.js} +1 -1
  144. package/web/assets/{interface-content-book-open-pages.svg-BbsuvPZM.js → interface-content-book-open-pages.svg-DMI3yFmk.js} +1 -1
  145. package/web/assets/{interface-content-book-page.svg-DbRPz1j8.js → interface-content-book-page.svg-BPxSHq3g.js} +1 -1
  146. package/web/assets/{interface-content-file.svg-OJPKABxS.js → interface-content-file.svg-D0Mbjb8x.js} +1 -1
  147. package/web/assets/interface-content-folder.svg-D3wbwhAD.js +1 -0
  148. package/web/assets/{interface-content-folder.svg-3D_5OE_-.js → interface-content-folder.svg-EUO1l7Mn.js} +1 -1
  149. package/web/assets/{interface-copy-clipboard.svg-DqthVh9J.js → interface-copy-clipboard.svg-DI-wp72J.js} +1 -1
  150. package/web/assets/{interface-edit-attachment.svg-BAPCnZ0B.js → interface-edit-attachment.svg-CrWbaWn_.js} +1 -1
  151. package/web/assets/{interface-edit-binocular.svg-BoV39ouF.js → interface-edit-binocular.svg-BzUDq1Il.js} +1 -1
  152. package/web/assets/{interface-edit-magic-wand.svg-Cz36nKVn.js → interface-edit-magic-wand.svg-DaAdEL5x.js} +1 -1
  153. package/web/assets/{interface-edit-tool-paint-roller.svg-DZUQotD5.js → interface-edit-tool-paint-roller.svg-C972BXSM.js} +1 -1
  154. package/web/assets/{interface-edit-tool-pencil.svg-DBf1Y9Tj.js → interface-edit-tool-pencil.svg-47QCYH9f.js} +1 -1
  155. package/web/assets/{interface-favorite-award.svg-B93sRjxf.js → interface-favorite-award.svg-DROP-rzN.js} +1 -1
  156. package/web/assets/{interface-favorite-flag.svg-DKHuT11J.js → interface-favorite-flag.svg-B1gpMdkg.js} +1 -1
  157. package/web/assets/{interface-favorite-heart.svg-Bw5FZQ7d.js → interface-favorite-heart.svg-Dc0MMGJl.js} +1 -1
  158. package/web/assets/{interface-favorite-star.svg-CgLbct_b.js → interface-favorite-star.svg-D6A5KWft.js} +1 -1
  159. package/web/assets/{interface-favorite-stars-sparkles.svg-B7cYS4ef.js → interface-favorite-stars-sparkles.svg-CpEr4y41.js} +1 -1
  160. package/web/assets/{interface-hierarchy-flowchart.svg-zwuaRdWq.js → interface-hierarchy-flowchart.svg-DjvgRFcZ.js} +1 -1
  161. package/web/assets/{interface-home-house.svg-B85yMFCe.js → interface-home-house.svg-BMmVKlSc.js} +1 -1
  162. package/web/assets/{interface-hyperlink.svg-US6b-Svn.js → interface-hyperlink.svg-BewFXeyZ.js} +1 -1
  163. package/web/assets/{interface-lighting-brightness.svg-mZWkhb7f.js → interface-lighting-brightness.svg-B74_Fwt9.js} +1 -1
  164. package/web/assets/{interface-lock-closed.svg-9oHuNwuY.js → interface-lock-closed.svg-B_kTyHSd.js} +1 -1
  165. package/web/assets/{interface-lock-open-unlock.svg-DBetdJny.js → interface-lock-open-unlock.svg-BpmOnQWL.js} +1 -1
  166. package/web/assets/{interface-login-key.svg-BZnZTYd1.js → interface-login-key.svg-CjYpI4bh.js} +1 -1
  167. package/web/assets/{interface-search.svg-CMXAOoam.js → interface-search.svg-FJmFWdB4.js} +1 -1
  168. package/web/assets/{interface-setting-cog.svg-CKckatt7.js → interface-setting-cog.svg-CfzSne-G.js} +1 -1
  169. package/web/assets/{interface-share-megaphone-bullhorn.svg-DH7kVqN-.js → interface-share-megaphone-bullhorn.svg-CIIzDsMB.js} +1 -1
  170. package/web/assets/{interface-share-rocket.svg-BNXcMugi.js → interface-share-rocket.svg-DqTBI7lO.js} +1 -1
  171. package/web/assets/{interface-share-satellite.svg-Bb8t607w.js → interface-share-satellite.svg-nJfwIxpE.js} +1 -1
  172. package/web/assets/{interface-share-space-ship.svg-Dk4rbLtF.js → interface-share-space-ship.svg-hSmFC9Bt.js} +1 -1
  173. package/web/assets/{interface-share.svg-CtX8dq5i.js → interface-share.svg-DW5W5LS6.js} +1 -1
  174. package/web/assets/{interface-signal-square.svg-DmUIlYTd.js → interface-signal-square.svg-CxjWE1n9.js} +1 -1
  175. package/web/assets/{interface-time-clock-circle.svg-D2ZNaXT3.js → interface-time-clock-circle.svg-OliTsm3U.js} +1 -1
  176. package/web/assets/{interface-time-hour-glass.svg-Ddo-8hHe.js → interface-time-hour-glass.svg-Cq5G77ft.js} +1 -1
  177. package/web/assets/{interface-users-multiple.svg-Jh7S0sT4.js → interface-users-multiple.svg-BZxMlLou.js} +1 -1
  178. package/web/assets/{interface-weather-moon.svg-DbdQFgL2.js → interface-weather-moon.svg-lFXrwEyz.js} +1 -1
  179. package/web/assets/{javascript-BVGFyXBk.js → javascript-BVZ1omk1.js} +1 -1
  180. package/web/assets/{jsonMode-vnFlxYl9.js → jsonMode-CiBARvaV.js} +2 -2
  181. package/web/assets/{liquid-DieKMEvN.js → liquid-CUYREU3G.js} +1 -1
  182. package/web/assets/{lspLanguageFeatures-DoeI-8Y7.js → lspLanguageFeatures-BCfkeNgB.js} +3 -3
  183. package/web/assets/{mail-chat-bubble-square.svg-CApdU2ea.js → mail-chat-bubble-square.svg-DbOh-u2f.js} +1 -1
  184. package/web/assets/{mail-send-email-paper-airplane.svg-jjZ0KB32.js → mail-send-email-paper-airplane.svg-Ci3654Ap.js} +1 -1
  185. package/web/assets/{mail-send-envelope.svg-B6Tsoh-8.js → mail-send-envelope.svg-BUCSUoVb.js} +1 -1
  186. package/web/assets/{mdx-BCkszXid.js → mdx-GNBOgT3C.js} +1 -1
  187. package/web/assets/{minus-DfLQX3s2.js → minus-qBqqwoxz.js} +2 -2
  188. package/web/assets/modal-CsKPvO45.js +5 -0
  189. package/web/assets/modal-E9FRG--u.js +1 -0
  190. package/web/assets/{money-cashier-receipt.svg-DM-I8Snr.js → money-cashier-receipt.svg-qOZhZZs2.js} +1 -1
  191. package/web/assets/{money-currency-dollar-pay.svg-CkDRewrV.js → money-currency-dollar-pay.svg-WYlopKIm.js} +1 -1
  192. package/web/assets/{money-graph-arrow-increase.svg-BT4KLHWz.js → money-graph-arrow-increase.svg-DAcyYWIw.js} +1 -1
  193. package/web/assets/{money-graph-bar-chart-increase.svg-EvyIJ3Uu.js → money-graph-bar-chart-increase.svg-Bcjxz1Kd.js} +1 -1
  194. package/web/assets/multiselect-DiGSzibm.js +251 -0
  195. package/web/assets/{nature-ecology-leaf.svg-uZBwXdg9.js → nature-ecology-leaf.svg-d0AKmyxH.js} +1 -1
  196. package/web/assets/{password-D1R5w1qL.js → password-BwMjgK0Q.js} +4 -4
  197. package/web/assets/{phone-telephone.svg-BSvOskIB.js → phone-telephone.svg-BzKK2wbN.js} +1 -1
  198. package/web/assets/{plus-CNGSRnxy.js → plus-D6Rlmwbp.js} +6 -6
  199. package/web/assets/process.store-I5VZVT0x.js +1 -0
  200. package/web/assets/{programming-bug.svg-CLnGs4K-.js → programming-bug.svg-BtSROvd5.js} +1 -1
  201. package/web/assets/{programming-cloud.svg-CxBovXBR.js → programming-cloud.svg-YDPFJdYt.js} +1 -1
  202. package/web/assets/{programming-computer-database-server.svg-C1JmOyio.js → programming-computer-database-server.svg-C_7cgE9Q.js} +1 -1
  203. package/web/assets/{programming-computer-database.svg-BRjyOzP4.js → programming-computer-database.svg-CLw76mik.js} +1 -1
  204. package/web/assets/{programming-module-four-layout.svg-Blwzw6Qz.js → programming-module-four-layout.svg-BsoC5ySI.js} +1 -1
  205. package/web/assets/{programming-module-three.svg-6bkrmWsU.js → programming-module-three.svg-CThoMoAk.js} +1 -1
  206. package/web/assets/{programming-module.svg-CBS9xKxX.js → programming-module.svg-BQ1YjjAj.js} +1 -1
  207. package/web/assets/{programming-script-code.svg-BVhyoAD3.js → programming-script-code.svg-BKT_wilO.js} +1 -1
  208. package/web/assets/project-launch.store-CBnJKGQe.js +1 -0
  209. package/web/assets/project.store-JIcOcKSg.js +1 -0
  210. package/web/assets/{python-CiPYtj_d.js → python-BXwGt-Ip.js} +1 -1
  211. package/web/assets/{radiobutton--KWBHcDP.js → radiobutton-D20sH1UN.js} +3 -3
  212. package/web/assets/{razor-CSoWGP30.js → razor-RXambmP2.js} +1 -1
  213. package/web/assets/router-BXj_oCbf.js +1 -0
  214. package/web/assets/{selectbutton-C0NL5n4w.js → selectbutton-rLcf19Xf.js} +4 -4
  215. package/web/assets/settings-scope-Cy_9OGE1.js +1 -0
  216. package/web/assets/settings.store-DrKeFdgW.js +1 -0
  217. package/web/assets/{shopping-cart.svg-C-8NG_Po.js → shopping-cart.svg-EjTn3XQF.js} +1 -1
  218. package/web/assets/{shopping-gift-present.svg-Bp6q5VzJ.js → shopping-gift-present.svg-AQNlzazh.js} +1 -1
  219. package/web/assets/{shopping-shipping-box-parcel-package.svg-DeWaEIwm.js → shopping-shipping-box-parcel-package.svg-VB9n6UNi.js} +1 -1
  220. package/web/assets/src-ByEHJyfr.js +1 -0
  221. package/web/assets/{src-BHR3l7pa.js → src-CUwD1xPP.js} +35 -35
  222. package/web/assets/src-C_auNJtg.css +1 -0
  223. package/web/assets/{tag-new-circle.svg-CTljXsqE.js → tag-new-circle.svg-BllOd5JW.js} +1 -1
  224. package/web/assets/theme-DuAHBQRP.js +1 -0
  225. package/web/assets/{toggleswitch-d41l5g27.js → toggleswitch-C-88_GnB.js} +2 -2
  226. package/web/assets/{travel-map-earth-globe.svg-BUkcntCp.js → travel-map-earth-globe.svg-ChLDmmU9.js} +1 -1
  227. package/web/assets/trpc-BoKwANhj.js +1 -0
  228. package/web/assets/{tsMode-B2c-rCAa.js → tsMode-CIN3QIw8.js} +6 -6
  229. package/web/assets/{typescript-CmW4u_GQ.js → typescript-wXu_7Eym.js} +1 -1
  230. package/web/assets/useAiChatDrawer-Bs1Gxhn2.js +1 -0
  231. package/web/assets/{useCloudOrg-E4l-99WA.js → useCloudOrg-0AZ58M3V.js} +1 -1
  232. package/web/assets/useEnvVarAutocomplete-BXC_JUF7.js +102 -0
  233. package/web/assets/{useEnvVarAutocomplete-DsxEF6Ya.css → useEnvVarAutocomplete-dxAmKsn7.css} +1 -1
  234. package/web/assets/useProjectCloudOrg-UIfVePy9.js +1 -0
  235. package/web/assets/useServiceUrlHost-BXbIxPaT.js +1 -0
  236. package/web/assets/{xml-BxMqu3hT.js → xml-FTYGqn2R.js} +1 -1
  237. package/web/assets/{yaml-Djx7E3R1.js → yaml-DQEEK2dU.js} +1 -1
  238. package/web/index.html +2 -2
  239. package/agent-manager-FUU72VGH.js +0 -11
  240. package/chat-C26CBAZX.js +0 -21
  241. package/chunk-5EMEJNVU.js.map +0 -1
  242. package/chunk-FJLMXLMK.js.map +0 -1
  243. package/chunk-NURPXHLB.js.map +0 -1
  244. package/chunk-P65BO7WZ.js.map +0 -1
  245. package/chunk-ZFELQG4B.js.map +0 -1
  246. package/desktop-launcher-3COY6F6H.js.map +0 -1
  247. package/desktop-wizard-4CYANX2O.js +0 -209
  248. package/desktop-wizard-4CYANX2O.js.map +0 -1
  249. package/settings-manager-J4QBIU3T.js +0 -10
  250. package/src-7O3GCEIB.js.map +0 -1
  251. package/web/assets/AgentScalarChatInterface.vue-BGGkpyp3.js +0 -13
  252. package/web/assets/AgentTerminalPage-B8gLray2.js +0 -1
  253. package/web/assets/AiChatPage-BKITsyMx.js +0 -1
  254. package/web/assets/AppLayout-B72S4nTi.css +0 -1
  255. package/web/assets/AppLayout-BYw7v2sp.js +0 -1
  256. package/web/assets/AuditPage-nHTwzyia.js +0 -1
  257. package/web/assets/CloudAccountPage-DYOvfMjD.css +0 -1
  258. package/web/assets/CloudAccountPage-DuaZz2j4.js +0 -1
  259. package/web/assets/CloudAccountPage-XHxI-ixD.js +0 -1
  260. package/web/assets/CloudMessagingPage-B2N5K-Xs.js +0 -2
  261. package/web/assets/DashboardPage-VoWJeWh_.js +0 -1
  262. package/web/assets/DirectoryPickerDialog-B5SuJOhv.js +0 -1
  263. package/web/assets/DirectoryPickerDialog-Ctp1lYoS.css +0 -1
  264. package/web/assets/EnvironmentFormPage-BIXbPTN5.js +0 -1
  265. package/web/assets/EnvironmentListPage-CHa-Ni3w.js +0 -1
  266. package/web/assets/KanbanBoardPage-B46zbE2H.css +0 -1
  267. package/web/assets/KanbanBoardPage-BFTNpm8P.js +0 -4
  268. package/web/assets/KanbanListPage-CYuIrKXH.js +0 -1
  269. package/web/assets/LaunchProjectPage-9hhGBdOh.css +0 -1
  270. package/web/assets/LaunchProjectPage-jy-R3Fiw.js +0 -1
  271. package/web/assets/LaunchServicesPage-BMtm_8yP.css +0 -1
  272. package/web/assets/LaunchServicesPage-DX7nyo36.js +0 -1
  273. package/web/assets/LaunchShell-BHfseuPM.js +0 -1
  274. package/web/assets/LaunchShell-HenrOlHV.css +0 -1
  275. package/web/assets/LogViewer-C-pHXudR.js +0 -3
  276. package/web/assets/OrgKeyPrompt-CrHXZdKL.css +0 -1
  277. package/web/assets/OrgKeyPrompt-OPnK5oPm.js +0 -1
  278. package/web/assets/OrgLogo-Cxa49Tl3.js +0 -1
  279. package/web/assets/ProcessControls-DXDyR6XX.js +0 -1
  280. package/web/assets/ProcessDetailPage-DNKTwgPW.js +0 -1
  281. package/web/assets/RandomJobTestPage-BE8HkgSb.js +0 -2
  282. package/web/assets/ScenarioEditorPage-Coo6ExzZ.js +0 -14
  283. package/web/assets/SendToChatDialog-ClXerpCU.js +0 -1
  284. package/web/assets/ServiceControlsBar-C7HrPjQI.js +0 -1
  285. package/web/assets/ServiceDetailPage-Cxuy0Yix.js +0 -2
  286. package/web/assets/ServiceFormPage-CCOu1h8v.js +0 -1
  287. package/web/assets/SettingsPage-Dt1ViDQe.js +0 -2063
  288. package/web/assets/UnlockPage-C5iEOAKH.js +0 -1
  289. package/web/assets/VaultMigrationPage-CwRWvFY7.js +0 -1
  290. package/web/assets/VersionBadge-Bqb72GXf.js +0 -1
  291. package/web/assets/WikiPage-Bl1jDKKp.js +0 -1
  292. package/web/assets/WikiView-58u6vU3q.js +0 -1
  293. package/web/assets/add-scalar-classes-CT5KQbzH.js +0 -387
  294. package/web/assets/card-46tM5yU0.js +0 -32
  295. package/web/assets/client-KL5c1Dog.js +0 -24
  296. package/web/assets/cloud-chat.store-Belo5SKd.js +0 -1
  297. package/web/assets/cloud-client-Cqa2Udt8.js +0 -1
  298. package/web/assets/cloud-session-56bUtkSL.js +0 -2
  299. package/web/assets/cloud-session-Dqm0C6H5.js +0 -1
  300. package/web/assets/column-DQ53_qc6.js +0 -763
  301. package/web/assets/composables-CHyZa9ag.js +0 -1
  302. package/web/assets/index-CKOtBNaZ.css +0 -1
  303. package/web/assets/interface-content-folder.svg-8mYqkDao.js +0 -1
  304. package/web/assets/modal-CCco27Sn.js +0 -5
  305. package/web/assets/modal-D4J85_wC.js +0 -1
  306. package/web/assets/multiselect-BmjidXlj.js +0 -251
  307. package/web/assets/process.store-p1LqnpY2.js +0 -1
  308. package/web/assets/project-launch.store-BBYtCcv8.js +0 -1
  309. package/web/assets/project.store-D_2v7amt.js +0 -1
  310. package/web/assets/router-CRKT3825.js +0 -1
  311. package/web/assets/settings-scope-DblmUa3N.js +0 -1
  312. package/web/assets/settings.store-DKTQyerJ.js +0 -1
  313. package/web/assets/src-BN5gTC76.css +0 -1
  314. package/web/assets/src-BRLkogf3.js +0 -1
  315. package/web/assets/theme-BZzt_Sgl.js +0 -1
  316. package/web/assets/trpc-Db0Atu8A.js +0 -1
  317. package/web/assets/useAiChatDrawer-0QJJVXul.js +0 -1
  318. package/web/assets/useEnvVarAutocomplete-BDqUWoGr.js +0 -102
  319. package/web/assets/useProjectCatalog-Cxt-hL1H.js +0 -1
  320. package/web/assets/useProjectCloudOrg-CwLTQLIO.js +0 -1
  321. package/web/assets/useServiceUrlHost-VIA3uP5-.js +0 -1
  322. /package/{agent-manager-FUU72VGH.js.map → agent-manager-NAGIMH2T.js.map} +0 -0
  323. /package/{chat-C26CBAZX.js.map → chat-Q2UMYXQL.js.map} +0 -0
  324. /package/{chunk-BDQOBEZ3.js.map → chunk-GOMF7NWS.js.map} +0 -0
  325. /package/{chunk-J4GLFY7G.js.map → chunk-MSICJEZD.js.map} +0 -0
  326. /package/{chunk-I7JHF5FE.js.map → chunk-XHGJHYDC.js.map} +0 -0
  327. /package/{companion-Q67RAO3N.js.map → companion-MGX62L4T.js.map} +0 -0
  328. /package/{node-4UUJN2WG.js.map → desktop-launcher-HKXP4LRI.js.map} +0 -0
  329. /package/{settings-manager-J4QBIU3T.js.map → desktop-wizard-XIDDAG7L.js.map} +0 -0
  330. /package/{vault-resolver-57Q2DVOR.js.map → node-RN4URNZ5.js.map} +0 -0
  331. /package/web/assets/{abap-BwLGULgU.js → abap-CRsXUZTC.js} +0 -0
  332. /package/web/assets/{apex-BmwhxS2n.js → apex-CN6ZSzwM.js} +0 -0
  333. /package/web/assets/{azcli-7RvE_Zal.js → azcli-ULFzG1xV.js} +0 -0
  334. /package/web/assets/{bat-DRPmS6Na.js → bat-BVH8lwB4.js} +0 -0
  335. /package/web/assets/{bicep-BwfkS7ZV.js → bicep-B8jMqZ8i.js} +0 -0
  336. /package/web/assets/{browser-D3d3061H.js → browser-xa0YgePN.js} +0 -0
  337. /package/web/assets/{cameligo-BJ_mdC8E.js → cameligo-DuuRwBiE.js} +0 -0
  338. /package/web/assets/{clojure-CQKq7DWt.js → clojure-DUpiEmPZ.js} +0 -0
  339. /package/web/assets/{coffee-DJRj2iwd.js → coffee-BO4ou798.js} +0 -0
  340. /package/web/assets/{cpp-BC1yJTUW.js → cpp-CHOtY2DW.js} +0 -0
  341. /package/web/assets/{csharp-D6U2fAAT.js → csharp-D3t5O1XD.js} +0 -0
  342. /package/web/assets/{csp-B2Ue_UmV.js → csp-CJpJWgPE.js} +0 -0
  343. /package/web/assets/{css-CEzlcbMY.js → css-CAeYpQS5.js} +0 -0
  344. /package/web/assets/{cypher-D5Sg38Yj.js → cypher-D9-TC6ep.js} +0 -0
  345. /package/web/assets/{dart-BhjKRv6v.js → dart-CYoMdUUD.js} +0 -0
  346. /package/web/assets/{dockerfile-BnivEbtE.js → dockerfile-B2ffS5e2.js} +0 -0
  347. /package/web/assets/{ecl-TS1StLK1.js → ecl-BL_MLv5o.js} +0 -0
  348. /package/web/assets/{elixir-BX9ta6DO.js → elixir-DTTK5HpM.js} +0 -0
  349. /package/web/assets/{flow9-CoOB42ee.js → flow9-CnqIliGA.js} +0 -0
  350. /package/web/assets/{fsharp-DmQslDFn.js → fsharp-BtsygJkw.js} +0 -0
  351. /package/web/assets/{go-BbEGGooY.js → go-DksUoC0w.js} +0 -0
  352. /package/web/assets/{graphql-E24y5sn9.js → graphql-DCtJGb0Q.js} +0 -0
  353. /package/web/assets/{hcl-pBZphP8G.js → hcl-Vm6MaTNZ.js} +0 -0
  354. /package/web/assets/{ini-BSbRgr25.js → ini-DdyyiZLB.js} +0 -0
  355. /package/web/assets/{java-D8KvzsMp.js → java-D9tw0Sq3.js} +0 -0
  356. /package/web/assets/{julia-BDRytf15.js → julia-DsaDhMSi.js} +0 -0
  357. /package/web/assets/{kotlin-CNcQo-uP.js → kotlin-eMyqSg05.js} +0 -0
  358. /package/web/assets/{less-0HRV-2Rz.js → less-BTExquT2.js} +0 -0
  359. /package/web/assets/{lexon-DdJG3_pW.js → lexon-Btiu1CPR.js} +0 -0
  360. /package/web/assets/{lua-Blq8Mukj.js → lua-uIHSqSt_.js} +0 -0
  361. /package/web/assets/{m3-CXbmzr9W.js → m3-DtY-QwwW.js} +0 -0
  362. /package/web/assets/{markdown-DFIISzT8.js → markdown-DalwAnMR.js} +0 -0
  363. /package/web/assets/{mips-C2XSYglv.js → mips-BocGRfi2.js} +0 -0
  364. /package/web/assets/{msdax-D3Jl6oAY.js → msdax-CQFbyz50.js} +0 -0
  365. /package/web/assets/{mysql-mCqxt_Co.js → mysql-BM8uo0J8.js} +0 -0
  366. /package/web/assets/{objective-c-CUKLr4E9.js → objective-c-H3c5-SZb.js} +0 -0
  367. /package/web/assets/{pascal-BpqDI6Ur.js → pascal-BgiV8eY7.js} +0 -0
  368. /package/web/assets/{pascaligo-BVchPyL4.js → pascaligo-DT9ZcxD2.js} +0 -0
  369. /package/web/assets/{perl-Dgc9v23P.js → perl-B0U4-W-w.js} +0 -0
  370. /package/web/assets/{pgsql-Dk9IX1G_.js → pgsql-B6kZRXs9.js} +0 -0
  371. /package/web/assets/{php-XeFLn3yL.js → php-DG9vCwQM.js} +0 -0
  372. /package/web/assets/{pla-DQMfrdXZ.js → pla-B4Y4wk5I.js} +0 -0
  373. /package/web/assets/{postiats-DiKrdL3K.js → postiats-C_eWfeAP.js} +0 -0
  374. /package/web/assets/{powerquery-Cj9Q91Zv.js → powerquery-DfX2HFDF.js} +0 -0
  375. /package/web/assets/{powershell-DxLElnzU.js → powershell-Bxsmga8Z.js} +0 -0
  376. /package/web/assets/{protobuf-7vT2HdZD.js → protobuf-BjgmCR9H.js} +0 -0
  377. /package/web/assets/{pug-oi96TUbQ.js → pug-ryXuxA3i.js} +0 -0
  378. /package/web/assets/{qsharp-DNr9IwS2.js → qsharp-91Kv1jwy.js} +0 -0
  379. /package/web/assets/{r-C-REi_Zk.js → r-j6OkO-Lp.js} +0 -0
  380. /package/web/assets/{redis-BvOCrLoN.js → redis-B2Usw_gW.js} +0 -0
  381. /package/web/assets/{redshift-jNEw-REz.js → redshift-Bl5n-UlH.js} +0 -0
  382. /package/web/assets/{restructuredtext-B9ET-x7N.js → restructuredtext-IIWeXmeu.js} +0 -0
  383. /package/web/assets/{ruby-BIEBiJDZ.js → ruby-DQH1R4pC.js} +0 -0
  384. /package/web/assets/{rust-BnoIVewm.js → rust-BJi0001n.js} +0 -0
  385. /package/web/assets/{sb-Bwvy9clh.js → sb-C34JQX0H.js} +0 -0
  386. /package/web/assets/{scala-DPv5zS47.js → scala-BqHjuqsC.js} +0 -0
  387. /package/web/assets/{scheme-BQqNVxf_.js → scheme-DIfjDH23.js} +0 -0
  388. /package/web/assets/{scss-Ck1AFDEz.js → scss-MxgEDdb7.js} +0 -0
  389. /package/web/assets/{shell-C4IYs9Z7.js → shell-D_SMEq6l.js} +0 -0
  390. /package/web/assets/{solidity-D3bS77xq.js → solidity-CyBHDO6p.js} +0 -0
  391. /package/web/assets/{sophia-BSTVfueD.js → sophia-8_L-7Xrk.js} +0 -0
  392. /package/web/assets/{sparql-BGcXD7s2.js → sparql-CXxyP-1c.js} +0 -0
  393. /package/web/assets/{sql-CIsSgyam.js → sql-DNd4NFJw.js} +0 -0
  394. /package/web/assets/{st-dV1d_AXx.js → st-DPFJcK-4.js} +0 -0
  395. /package/web/assets/{swift-CK8gXWQn.js → swift-DE_LJ5Ub.js} +0 -0
  396. /package/web/assets/{systemverilog-B9tHBIJU.js → systemverilog-IgPgwLQ7.js} +0 -0
  397. /package/web/assets/{tcl-BgRT60RV.js → tcl-Cr-fmmH0.js} +0 -0
  398. /package/web/assets/{twig-CGkLO4Nl.js → twig-Dd_ODPfV.js} +0 -0
  399. /package/web/assets/{typespec-DMP9WuzC.js → typespec-CeK8X8vB.js} +0 -0
  400. /package/web/assets/{uuid-H0yY5A03.js → uuid-6HQMUkhT.js} +0 -0
  401. /package/web/assets/{vb-DfSbhl3d.js → vb-CyLVxxH6.js} +0 -0
  402. /package/web/assets/{wgsl-CaJmoLY5.js → wgsl-CmRFGM3r.js} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../server/src/services/vault-resolver.ts","../../server/src/config/env.ts"],"sourcesContent":["import { join, sep } from 'node:path';\nimport { homedir } from 'node:os';\nimport { readdir, mkdir, access, readFile, writeFile, unlink } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { env } from '../config/env.js';\n\n/**\n * Where a project's files live, and which key protects them.\n *\n * Runeya holds two kinds of projects, and they do not belong in the same place.\n * A local project *is* a directory on this machine: its data belongs next to\n * the code, in `<cwd>/.runeya`. A cloud project belongs to an organization and\n * is materialized from the doc; tying it to whichever directory happened to\n * launch the server is what made the same project look \"already here\" in one\n * folder and \"to download\" in another. Cloud projects therefore live under the\n * user's home, prefixed by organization and by project.\n *\n * A vault holds a project's own data — project.json, services, environments.\n * It does NOT hold the key that protects it: one key answers for the whole\n * machine (see `keyRoot` at the bottom of this file), which is what the cloud's\n * org-wide canary already assumes.\n */\n\nexport interface Vault {\n /** Directory holding this project's own files. */\n root: string;\n}\n\n/** Identifies a project well enough to place it — the stored shape, or the doc's. */\nexport interface VaultTarget {\n id: string;\n orgId?: string | null;\n}\n\n/**\n * Ids reach us from the cloud, and they end up in filesystem paths. Anything\n * outside this alphabet — a separator, a `..`, a NUL — could walk out of the\n * home directory, so it is rejected rather than sanitized: a mangled id would\n * silently point at the wrong vault.\n */\nconst SAFE_ID = /^[A-Za-z0-9._-]{1,128}$/;\n\nfunction assertSafeId(kind: 'organization' | 'project', id: string): void {\n if (!SAFE_ID.test(id) || id === '.' || id === '..') {\n throw new Error(`Invalid ${kind} id for a vault path: ${JSON.stringify(id)}`);\n }\n}\n\n/**\n * Everything that belongs to this machine rather than to a project.\n *\n * Read from `process.env` rather than the parsed config: tests that mock\n * `config/env.js` would otherwise lose the override and write cloud vaults into\n * the developer's real home directory.\n */\nexport function machineRoot(): string {\n const override = process.env['RUNEYA_HOME'];\n return join(override && override.length > 0 ? override : homedir(), '.runeya');\n}\n\n/**\n * The local vault: the `.runeya` of the directory the server was launched in.\n *\n * Kept on `env.DATA_DIR` so `--data-dir` and the tests keep working. That value\n * is already absolute, resolved once at boot — re-resolving it here would make\n * the vault follow the process's cwd, which is exactly what it must not do.\n */\nexport function localVaultRoot(): string {\n return env.DATA_DIR;\n}\n\n/** The vault of an organization: its projects, and its lock. */\nexport function orgVaultRoot(orgId: string): string {\n assertSafeId('organization', orgId);\n return join(machineRoot(), 'orgs', orgId);\n}\n\n/** The vault of one cloud project, under its organization. */\nexport function projectVaultRoot(orgId: string, projectId: string): string {\n assertSafeId('project', projectId);\n return join(orgVaultRoot(orgId), 'projects', projectId);\n}\n\n/**\n * The organization a vault path belongs to, or null for the local vault.\n *\n * The layout is the authority on ownership — `~/.runeya/orgs/<org>/projects/<id>`\n * says both which project and which organization — so an entity read from a\n * vault carries its couple in the path it came from, even though its own file\n * only ever names its project.\n */\nexport function orgIdOfRoot(root: string): string | null {\n const marker = join(machineRoot(), 'orgs') + sep;\n if (!root.startsWith(marker)) return null;\n const [orgId] = root.slice(marker.length).split(sep);\n return orgId && SAFE_ID.test(orgId) ? orgId : null;\n}\n\n/**\n * La clé sous laquelle une donnée de ce coffre est chiffrée.\n *\n * L'identifiant d'organisation quand le coffre lui appartient, `undefined` pour\n * la clé machine. Le rangement décide donc du chiffrement, sans qu'aucune\n * entité ait à porter un champ de plus : le coffre où on l'écrit dit déjà à qui\n * elle est.\n */\nexport function vaultIdOfRoot(root: string): string | undefined {\n return orgIdOfRoot(root) ?? undefined;\n}\n\n/** Where to read and write a given project. */\nexport function vaultFor(target: VaultTarget): Vault {\n if (!target.orgId) return { root: localVaultRoot() };\n return { root: projectVaultRoot(target.orgId, target.id) };\n}\n\n/**\n * Which cloud instance an organization's vault came from.\n *\n * `~/.runeya/orgs/` is machine-global, so a machine that has ever synced against\n * two clouds (a self-hosted or local one and the hosted one) ends up with org\n * ids from both, indistinguishable. Stamping the instance next to the vault is\n * what lets a reader tell \"an org I am not a member of\" from \"an org of a cloud\n * I am simply not signed into\" — and what keeps the sync from offering one\n * cloud's organizations to another.\n */\nconst ORG_CLOUD_FILE = 'cloud.json';\n\nexport async function stampOrgCloud(\n orgId: string,\n cloudUrl: string,\n name?: string,\n accountId?: string,\n): Promise<void> {\n const root = orgVaultRoot(orgId);\n // Not best-effort any more: the stamp is now what tells a later boot which\n // cloud an org's vault came from, and syncing follows those vaults. A stamp\n // silently skipped would leave the org to be claimed by whatever cloud is\n // configured then — so a failure here has to stop the pull it precedes.\n await mkdir(root, { recursive: true });\n // Le nom rejoint le tampon plutôt qu'un fichier à lui : il se connaît au même\n // instant, et une organisation sans nom local n'a plus qu'un hash à montrer\n // dès que la session cloud est éteinte.\n const known = name ?? (await readOrgNames())[orgId];\n // Le compte rejoint le tampon pour la même raison que le cloud : il n'y en a\n // plus un seul sur le poste, et sans lui une organisation serait interrogée\n // avec le token du dernier utilisateur connecté — au mieux un 403, au pire\n // les données d'un homonyme. Un `accountId` omis laisse en place celui qui y\n // était : les appelants qui ne savent pas de quel compte ils parlent ne\n // doivent pas effacer ce que la liaison, elle, savait.\n const kept = accountId ?? (await readOrgAccounts())[orgId];\n const stamp = {\n cloudUrl,\n ...(known ? { name: known } : {}),\n ...(kept ? { accountId: kept } : {}),\n };\n await writeFile(join(root, ORG_CLOUD_FILE), JSON.stringify(stamp, null, 2), 'utf-8');\n}\n\n/**\n * Retenir le compte auquel une organisation appartient.\n *\n * Appelé avec ce que le cloud vient de répondre : une organisation appartient\n * au compte qui la LISTE, et c'est la seule source qui le sache. Le poste, lui,\n * ne peut que deviner — il l'a fait, et il a rangé sous un compte les\n * organisations d'un autre, y compris celles d'un tout autre cloud.\n *\n * Écrase donc le compte déjà tamponné : cette réponse-ci fait autorité, la\n * précédente pouvait être une supposition.\n */\nexport async function rememberOrgAccount(orgId: string, accountId: string): Promise<void> {\n const root = orgVaultRoot(orgId);\n // Aucun coffre : cette organisation n'a rien ici, et lui en créer un pour un\n // simple rattachement rangerait un répertoire vide sous un compte.\n if (!existsSync(root)) return;\n const file = join(root, ORG_CLOUD_FILE);\n let stamp: Record<string, unknown> = {};\n try {\n stamp = JSON.parse(await readFile(file, 'utf-8')) as Record<string, unknown>;\n } catch {\n // Pas de tampon : le rattachement en fonde un.\n }\n if (stamp['accountId'] === accountId) return;\n await writeFile(file, JSON.stringify({ ...stamp, accountId }, null, 2), 'utf-8');\n}\n\n/**\n * Suivre un compte qui change d'identifiant.\n *\n * Un compte lié avant le multicompte n'a pas d'identité : son identifiant est\n * provisoire, fondé sur son seul cloud, et devient définitif au premier appel\n * qui apprend qui il est. Les tampons posés entre-temps nomment l'ancien — et\n * un tampon qui désigne un compte inexistant rend son organisation muette dès\n * qu'il y a plus d'un compte, c'est-à-dire exactement quand on en a besoin.\n */\nexport async function renameOrgAccount(oldId: string, newId: string): Promise<void> {\n if (oldId === newId) return;\n for (const orgId of await listOrgVaults()) {\n const file = join(orgVaultRoot(orgId), ORG_CLOUD_FILE);\n let stamp: Record<string, unknown>;\n try {\n stamp = JSON.parse(await readFile(file, 'utf-8')) as Record<string, unknown>;\n } catch {\n continue;\n }\n if (stamp['accountId'] !== oldId) continue;\n await writeFile(file, JSON.stringify({ ...stamp, accountId: newId }, null, 2), 'utf-8');\n }\n}\n\n/**\n * Le compte dont chaque organisation relève, lu sur le disque.\n *\n * Pendant exact de `readOrgClouds` : le cloud dit *où* frapper, le compte dit\n * *au nom de qui*. Une organisation sans compte tamponné est celle d'un coffre\n * écrit avant le multicompte ; elle retombe sur le compte unique du poste, ce\n * qui est précisément la situation qu'elle décrivait.\n */\nexport async function readOrgAccounts(): Promise<Record<string, string>> {\n const out: Record<string, string> = {};\n for (const orgId of await listOrgVaults()) {\n try {\n const raw = await readFile(join(orgVaultRoot(orgId), ORG_CLOUD_FILE), 'utf-8');\n const id = (JSON.parse(raw) as { accountId?: unknown }).accountId;\n if (typeof id === 'string' && id) out[orgId] = id;\n } catch {\n // Pas de tampon, ou pas de compte : le poste tranchera avec ce qu'il a.\n }\n }\n return out;\n}\n\n/**\n * Retenir le nom d'une organisation déjà présente ici.\n *\n * Appelé quand le cloud vient de le dire, pour qu'il survive à la déconnexion.\n * Aucun COFFRE n'est créé : une organisation dont ce poste n'a rien n'a pas à\n * recevoir un répertoire pour un simple nom.\n *\n * Le tampon, lui, est écrit même s'il manque — c'est la nuance qui manquait.\n * Tous les coffres ne naissent pas d'une synchronisation : un simple\n * `settingsManager.getSettings(orgId)` crée le répertoire sans passer par\n * `stampOrgCloud`. Renoncer faute de fichier condamnait ces coffres-là à\n * n'afficher qu'un hash pour toujours, quel que soit le nombre de fois où le\n * cloud redit leur nom.\n *\n * Le tampon posé ici ne porte pas de `cloudUrl` : personne ici ne sait de quel\n * cloud vient le coffre, et l'inventer rangerait l'organisation sous le mauvais.\n * Un tampon sans cloud se lit exactement comme l'absence de tampon.\n */\nexport async function rememberOrgName(orgId: string, name: string): Promise<void> {\n const root = orgVaultRoot(orgId);\n if (!existsSync(root)) return;\n const file = join(root, ORG_CLOUD_FILE);\n let stamp: Record<string, unknown> = {};\n try {\n stamp = JSON.parse(await readFile(file, 'utf-8')) as Record<string, unknown>;\n } catch {\n // Pas de tampon, ou illisible : le nom en fonde un.\n }\n if (stamp['name'] === name) return;\n await writeFile(file, JSON.stringify({ ...stamp, name }, null, 2), 'utf-8');\n}\n\n/** Le nom de chaque organisation dont le tampon en porte un. */\nexport async function readOrgNames(): Promise<Record<string, string>> {\n const out: Record<string, string> = {};\n for (const orgId of await listOrgVaults()) {\n try {\n const raw = await readFile(join(orgVaultRoot(orgId), ORG_CLOUD_FILE), 'utf-8');\n const name = (JSON.parse(raw) as { name?: unknown }).name;\n if (typeof name === 'string' && name) out[orgId] = name;\n } catch {\n // Pas de tampon, ou pas encore de nom : l'id fera l'affaire.\n }\n }\n return out;\n}\n\n/**\n * Le logo d'une organisation, gardé à côté de son nom.\n *\n * Même raison d'être que le nom recopié dans le tampon : ce que le poste sait\n * de ses organisations ne doit dépendre ni d'une session cloud ni du réseau.\n * Le nom tient dans le tampon ; les octets, eux, méritent leur propre fichier —\n * `cloud.json` est relu et réécrit à chaque pull, et y mêler 40 Ko de base64\n * ferait payer l'image à des lectures qui n'en veulent pas.\n */\nconst ORG_LOGO_FILE = 'logo.json';\n\ninterface StoredLogo {\n contentType: string;\n base64: string;\n fetchedAt: string;\n}\n\n/** Formats matriciels inertes, la même liste que celle acceptée par le cloud. */\nconst LOGO_TYPES = new Set(['image/png', 'image/jpeg', 'image/webp', 'image/gif']);\n\n/** Garder (ou remplacer) le logo d'une organisation présente ici. */\nexport async function rememberOrgLogo(orgId: string, contentType: string, base64: string): Promise<void> {\n if (!LOGO_TYPES.has(contentType)) return;\n const root = orgVaultRoot(orgId);\n const stored: StoredLogo = { contentType, base64, fetchedAt: new Date().toISOString() };\n await mkdir(root, { recursive: true });\n await writeFile(join(root, ORG_LOGO_FILE), JSON.stringify(stored), 'utf-8');\n}\n\n/** Oublier le logo d'une organisation — elle n'en a plus. */\nexport async function forgetOrgLogo(orgId: string): Promise<void> {\n try {\n await unlink(join(orgVaultRoot(orgId), ORG_LOGO_FILE));\n } catch {\n // Il n'y en avait pas : c'est le résultat voulu.\n }\n}\n\n/**\n * Le logo retenu d'une organisation : ses octets et leur type.\n *\n * Le type est revalidé à la lecture — un fichier trafiqué sur le disque ne doit\n * pas pouvoir faire servir un `image/svg+xml`, donc du script, à l'interface.\n */\nexport async function readOrgLogo(orgId: string): Promise<{ contentType: string; bytes: Uint8Array } | null> {\n try {\n const raw = await readFile(join(orgVaultRoot(orgId), ORG_LOGO_FILE), 'utf-8');\n const { contentType, base64 } = JSON.parse(raw) as Partial<StoredLogo>;\n if (typeof contentType !== 'string' || !LOGO_TYPES.has(contentType)) return null;\n if (typeof base64 !== 'string' || !base64) return null;\n return { contentType, bytes: new Uint8Array(Buffer.from(base64, 'base64')) };\n } catch {\n // Pas de logo retenu, ou fichier illisible.\n return null;\n }\n}\n\n/**\n * Les logos retenus, en data URL, prêts pour un `src`.\n *\n * Le type est revalidé à la lecture : un fichier trafiqué sur le disque ne doit\n * pas pouvoir faire servir un `image/svg+xml` — donc du script — à l'interface.\n */\nexport async function readOrgLogos(): Promise<Record<string, string>> {\n const out: Record<string, string> = {};\n for (const orgId of await listOrgVaults()) {\n const logo = await readOrgLogo(orgId);\n // Pas de logo retenu : l'initiale fera l'affaire.\n if (logo) out[orgId] = `data:${logo.contentType};base64,${Buffer.from(logo.bytes).toString('base64')}`;\n }\n return out;\n}\n\n/** The cloud instance of every org vault that carries a stamp. */\nexport async function readOrgClouds(): Promise<Record<string, string>> {\n const orgsDir = join(machineRoot(), 'orgs');\n const out: Record<string, string> = {};\n let orgIds: string[];\n try {\n orgIds = (await readdir(orgsDir, { withFileTypes: true }))\n .filter((e) => e.isDirectory() && SAFE_ID.test(e.name))\n .map((e) => e.name);\n } catch {\n return out;\n }\n for (const orgId of orgIds) {\n try {\n const raw = await readFile(join(orgsDir, orgId, ORG_CLOUD_FILE), 'utf-8');\n const url = (JSON.parse(raw) as { cloudUrl?: unknown }).cloudUrl;\n if (typeof url === 'string' && url) out[orgId] = url;\n } catch {\n // No stamp (older vault, or never linked here) — simply unknown.\n }\n }\n return out;\n}\n\n/**\n * Les organisations présentes sur ce disque, projets ou non.\n *\n * Distinct de `listCloudVaults`, qui ne voit une organisation qu'à travers ses\n * projets matérialisés : une organisation peut porter des données à elle —\n * agents, clés d'API — sans qu'aucun projet n'ait encore été ouvert ici, et\n * l'ignorer alors reviendrait à les perdre au prochain démarrage.\n */\nexport async function listOrgVaults(): Promise<string[]> {\n const orgsDir = join(machineRoot(), 'orgs');\n try {\n return (await readdir(orgsDir, { withFileTypes: true }))\n .filter((e) => e.isDirectory() && SAFE_ID.test(e.name))\n .map((e) => e.name);\n } catch {\n return [];\n }\n}\n\n/** One cloud project vault found on disk. */\nexport interface CloudVault {\n orgId: string;\n projectId: string;\n root: string;\n}\n\n/**\n * Every cloud project vault present on this machine, by walking\n * `~/.runeya/orgs/<orgId>/projects/<projectId>`.\n *\n * Discovery reads the disk rather than an index on purpose: an index is one\n * more thing that can disagree with what is actually there, and a project\n * present on disk but missing from it is precisely the \"already here, still\n * offered as a download\" bug. Unreadable or foreign directories are skipped in\n * silence — a half-written pull must not take a whole load down.\n */\nexport async function listCloudVaults(): Promise<CloudVault[]> {\n const orgsDir = join(machineRoot(), 'orgs');\n const found: CloudVault[] = [];\n\n let orgIds: string[];\n try {\n orgIds = (await readdir(orgsDir, { withFileTypes: true }))\n .filter((e) => e.isDirectory() && SAFE_ID.test(e.name))\n .map((e) => e.name);\n } catch {\n return found;\n }\n\n for (const orgId of orgIds) {\n const projectsDir = join(orgsDir, orgId, 'projects');\n try {\n for (const entry of await readdir(projectsDir, { withFileTypes: true })) {\n if (!entry.isDirectory() || !SAFE_ID.test(entry.name)) continue;\n const root = join(projectsDir, entry.name);\n // Un répertoire n'est pas un projet : il faut qu'il en porte la fiche.\n //\n // Tout ce qui traînait ici était pris pour un coffre — une copie de\n // sauvegarde, un dossier oublié — et les stores le lisaient, le\n // comptaient, pouvaient le réécrire. Une sauvegarde déposée à côté\n // d'un projet s'est ainsi retrouvée annoncée comme dix-neuf\n // conversations illisibles appartenant à l'organisation.\n //\n // `project.json` est déjà ce qui fait foi ailleurs (`isMaterialized`\n // dans org-sync-scope) : la même règle vaut ici, pour tout le monde.\n if (!(await access(join(root, 'project.json')).then(() => true, () => false))) continue;\n found.push({ orgId, projectId: entry.name, root });\n }\n } catch {\n // Org directory without materialized projects yet.\n }\n }\n return found;\n}\n\n/**\n * Every vault holding data, local first — what stores must read to see it all.\n *\n * Derived from the disk, so it needs no store to have loaded beforehand: a\n * content store can resolve where to read without waiting on the project store.\n */\nexport async function allVaultRoots(): Promise<string[]> {\n const cloud = await listCloudVaults();\n return [localVaultRoot(), ...cloud.map((v) => v.root)];\n}\n\n/**\n * A file belonging to the machine rather than to any project.\n *\n * Settings, the audit log, caches: none of them describe a project, and keeping\n * them in the launch directory forced a `.runeya` to exist for someone working\n * only on cloud projects — the very thing vaults remove.\n *\n * For anything ENCRYPTED, use `keyedFilePath` instead.\n */\nexport function machineFilePath(filename: string): string {\n return join(machineRoot(), filename);\n}\n\n/**\n * A machine file whose contents are encrypted.\n *\n * It lives beside the key that opens it, never merely beside the machine. The\n * two are usually the same directory — but a launch directory that owns its own\n * key keeps it (see `keyRoot`), and a file encrypted under that key read from\n * elsewhere would decrypt to blanks, then be saved back blank. Tying the file to\n * its key is what makes that impossible.\n */\nexport async function keyedFilePath(filename: string): Promise<string> {\n return join(await keyRoot(), filename);\n}\n\n/**\n * Where such a file was kept by earlier versions: in the launch directory.\n *\n * Read as a fallback and never written, so a directory shared with an older\n * Runeya keeps working.\n */\nexport function legacyMachineFilePath(filename: string): string {\n return join(localVaultRoot(), filename);\n}\n\n/**\n * Create the local vault, on the way to writing a local project into it.\n *\n * The directory is created here and nowhere else. Runeya no longer makes a\n * `.runeya` just because it was started somewhere: a machine used only for\n * cloud projects should leave the directories it visits untouched, and a\n * `.runeya` appearing in a repository should mean \"there is a local project\n * here\" rather than \"Runeya ran here once\".\n */\nexport async function ensureLocalVault(): Promise<string> {\n const root = localVaultRoot();\n await mkdir(root, { recursive: true });\n return root;\n}\n\n/** Files that mark a directory as already holding an encryption key. */\nconst KEY_FILES = ['.encryption.key.enc', '.runeya-verify'];\n\nlet keyRootPromise: Promise<string> | null = null;\n\n/** True when a directory already holds an encryption key of its own. */\nasync function holdsKey(root: string): Promise<boolean> {\n for (const filename of KEY_FILES) {\n try {\n await access(join(root, filename));\n return true;\n } catch {\n // Not here — keep looking.\n }\n }\n return false;\n}\n\n/**\n * Where this machine's encryption key and its canary live.\n *\n * The key protects everything on the machine — agents, sessions, and the\n * environments of every vault — so there is one, not one per vault, and the\n * machine root is its home.\n *\n * Earlier versions let a launch directory keep a key of its own, which is how a\n * machine ended up with several master passwords and several cloud identities.\n * Such a directory is no longer promoted: the machine key answers as soon as it\n * exists, and the leftover local key is surfaced by `legacyVaultRoot()` so it\n * can be migrated rather than silently obeyed. A machine that has never had a\n * machine key still falls back to the local one, so an un-migrated install\n * keeps opening exactly as before.\n *\n * Resolved once per process: the answer must not change under a running server,\n * and a key written mid-session would otherwise move its own home.\n */\nexport function keyRoot(): Promise<string> {\n keyRootPromise ??= (async () => {\n if (await holdsKey(machineRoot())) return machineRoot();\n return (await holdsKey(localVaultRoot())) ? localVaultRoot() : machineRoot();\n })();\n return keyRootPromise;\n}\n\n/**\n * The launch directory's own key, when the machine key is what we opened.\n *\n * Its presence is the whole trigger for the migration page: this directory\n * holds data encrypted under a key nothing reads any more. Null once migrated,\n * and null too when the local key IS the one in use — there is nothing to\n * migrate then.\n */\nexport async function legacyVaultRoot(): Promise<string | null> {\n const local = localVaultRoot();\n if ((await keyRoot()) === local) return null;\n return (await holdsKey(local)) ? local : null;\n}\n\n/** Test seam: forget the resolved key home. */\nexport function resetKeyRoot(): void {\n keyRootPromise = null;\n}\n","import { z } from 'zod';\nimport { resolve as resolvePath } from 'node:path';\n\n/**\n * Every variable Runeya reads from the process environment is prefixed with\n * `RUNEYA_`. Generic names (PORT, HOST, MODE, DATA_DIR…) are deliberately NOT\n * read: Runeya loads the `.env` of the stack it manages, where those names very\n * often belong to the user's own services.\n *\n * The resolved object keeps short field names (`env.PORT`, `env.HOST`, …) —\n * only the environment keys are prefixed.\n */\n\n// Server port, used to derive the default agent port\nconst serverPort = z.coerce.number().int().min(1).max(65535).default(4000).parse(process.env.RUNEYA_HTTP_PORT);\n\nconst defaultAgentPort = process.env.RUNEYA_AGENT_PORT\n ? z.coerce.number().int().min(1).max(65535).parse(process.env.RUNEYA_AGENT_PORT)\n : serverPort + 1;\n\nconst EnvSchema = z.object({\n RUNEYA_HTTP_PORT: z.coerce.number().int().min(1).max(65535).default(4000),\n RUNEYA_HOST: z.string().default('127.0.0.1'),\n RUNEYA_AGENT_PORT: z.coerce.number().int().min(1).max(65535).default(defaultAgentPort),\n RUNEYA_AGENT_HOST: z.string().default('127.0.0.1'),\n RUNEYA_AGENT_BINARY_PATH: z.string().nullable().default(null),\n RUNEYA_DATA_DIR: z.preprocess((v) => (typeof v === 'string' && v.length > 0 ? v : undefined), z.string().default('.runeya')),\n // Home holding the cloud vaults (`<home>/.runeya/orgs/...`). Defaults to the\n // user's home directory; overridden by tests so they never write to the real\n // one, and usable to relocate the vaults on a shared machine.\n RUNEYA_HOME: z.preprocess((v) => (typeof v === 'string' && v.length > 0 ? v : undefined), z.string().nullable().default(null)),\n RUNEYA_CLOUD_URL: z.string().url().nullable().default(null),\n // Cloud front-end (landing) URL — used by the web app for the registration /\n // onboarding flow. Configured on the server at launch; the web fetches it.\n RUNEYA_CLOUD_APP_URL: z.string().url().nullable().default(null),\n RUNEYA_MODE: z.enum(['local-simple', 'cloud']).default('local-simple'),\n RUNEYA_CORS_ORIGIN: z.string().nullable().default(null),\n RUNEYA_LAN_PROXY: z.preprocess((v) => v === 'true' || v === '1', z.boolean()).default(false),\n // Set by the CLI when it was started from a desktop launcher rather than a\n // terminal. The web app surfaces it so the user knows which Runeya they are\n // looking at when several are running.\n RUNEYA_FROM_DESKTOP: z.preprocess((v) => v === 'true' || v === '1', z.boolean()).default(false),\n // Label shown for this machine in the cloud's \"linked machines\" screen.\n // Defaults to the hostname (see `getDeviceName`); set it explicitly when a\n // single host runs several instances and you want to tell them apart.\n RUNEYA_DEVICE_NAME: z.preprocess(\n (v) => (typeof v === 'string' && v.trim().length > 0 ? v.trim() : undefined),\n z.string().max(64).nullable().default(null),\n ),\n}).transform((data) => ({\n ...data,\n // Short aliases used throughout the server code\n PORT: data.RUNEYA_HTTP_PORT,\n HOST: data.RUNEYA_HOST,\n MODE: data.RUNEYA_MODE,\n /**\n * Absolute from the start, resolved once against the launch directory.\n *\n * It defaults to a relative `.runeya`, and every caller used to re-resolve it\n * against whatever the process's cwd happened to be. A vault that moves when\n * the process changes directory is a vault that can be silently written to the\n * wrong place — so the answer is fixed here, at boot, and never recomputed.\n */\n DATA_DIR: resolvePath(data.RUNEYA_DATA_DIR),\n HOME_DIR: data.RUNEYA_HOME,\n CLOUD_URL: data.RUNEYA_CLOUD_URL,\n CLOUD_APP_URL: data.RUNEYA_CLOUD_APP_URL,\n CORS_ORIGIN: data.RUNEYA_CORS_ORIGIN,\n AGENT_BINARY_PATH: data.RUNEYA_AGENT_BINARY_PATH,\n DEVICE_NAME: data.RUNEYA_DEVICE_NAME,\n FROM_DESKTOP: data.RUNEYA_FROM_DESKTOP,\n}));\n\nexport type Env = z.infer<typeof EnvSchema>;\n\nexport const env = EnvSchema.parse(process.env);\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/desktop-launcher.ts"],"sourcesContent":["/**\n * Cross-platform desktop launcher (`runeya install-desktop`).\n *\n * Deliberately an explicit sub-command rather than a postinstall hook: npm 12\n * blocks lifecycle scripts by default, so a launcher created that way would be\n * silently missing. Here the user asks for it, and gets the paths back.\n *\n * Nothing is embedded — the launcher points at the Node binary and the CLI\n * entry point currently in use. If the user switches Node version manager,\n * re-running the command re-pins the paths.\n */\nimport { mkdir, writeFile, rm, copyFile, access } from 'node:fs/promises';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { homedir } from 'node:os';\nimport { join, dirname } from 'node:path';\n\nimport {\n slugifyLauncherName,\n launcherIdFromName,\n deriveLauncherIdentity,\n} from '@runeya/packages-shared';\n\nconst exec = promisify(execFile);\n\n/**\n * Le nommage d'un lanceur vit dans `packages/shared` : le serveur en a besoin\n * pour proposer le même nom depuis l'interface. Réexporté ici sous les noms\n * locaux, qui sont ceux que le reste du CLI appelle.\n */\nexport {\n slugifyLauncherName as slugify,\n launcherIdFromName as idFromName,\n deriveLauncherIdentity as deriveIdentity,\n};\n\nexport type InstallOptions = {\n /** Absolute path to the Node binary the launcher must use. */\n nodePath: string;\n /** Absolute path to the CLI entry point (dist/index.js). */\n cliEntry: string;\n /** Directory holding the CLI dist — used to find the bundled icons in assets/. */\n distDir: string;\n /** Working directory to pin, or null to let the desktop decide. */\n workingDir: string | null;\n /** Display name, e.g. \"Runeya\" or \"Runeya — my-stack\". */\n name: string;\n /** Filesystem-safe id derived from the name, e.g. \"runeya-my-stack\". */\n id: string;\n /** Port baked into the launcher, or null to follow Runeya's default. */\n port: number | null;\n /** Agent port, or null to let Runeya derive it from `port + 1`. */\n agentPort: number | null;\n};\n\n/**\n * Arguments the launcher passes to the CLI.\n *\n * `--agent-port` is omitted when it is exactly what Runeya would derive on its\n * own, so the command line stays readable and keeps following the derivation\n * if it ever changes.\n */\nexport function launcherArgs(opts: Pick<InstallOptions, 'port' | 'agentPort'>): string[] {\n const args = ['--from-desktop'];\n if (opts.port !== null) args.push('--port', String(opts.port));\n if (opts.agentPort !== null && opts.agentPort !== (opts.port ?? 4000) + 1) {\n args.push('--agent-port', String(opts.agentPort));\n }\n return args;\n}\n\nexport type LauncherResult = {\n /** Files created or removed, for reporting back to the user. */\n paths: string[];\n /** Non-fatal problems (missing icon, desktop database refresh failed…). */\n warnings: string[];\n};\n\n/**\n * Le dossier de travail d'un lanceur, avec un repli qui n'est jamais la racine.\n *\n * Sans dossier épinglé, un lanceur hérite du cwd du système — `/` pour le\n * Finder comme pour systemd — et Runeya y placerait son `.runeya`. La racine\n * est en lecture seule sous macOS et interdite d'écriture sous Linux : le home\n * est le seul repli toujours disponible. Le CLI applique la même garde à\n * l'exécution, pour les lanceurs posés avant ce correctif.\n */\nexport function launcherWorkingDir(workingDir: string | null): string {\n return workingDir ?? homedir();\n}\n\nasync function exists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Best-effort command: never fails the install, just reports a warning. */\nasync function tryExec(file: string, args: string[], warnings: string[]): Promise<void> {\n try {\n await exec(file, args);\n } catch {\n warnings.push(`Commande optionnelle échouée : ${file} (le lanceur est créé, le menu peut mettre un instant à l'afficher)`);\n }\n}\n\n// ─── Linux ───────────────────────────────────────────────────────────────────\n\n/**\n * Quote a value for the `Exec=` key of a .desktop file.\n * Per the Desktop Entry spec, inside a quoted argument the characters\n * `\"`, backtick, `$` and `\\` must each be preceded by a backslash.\n */\nexport function desktopExecQuote(value: string): string {\n return `\"${value.replace(/[\"`$\\\\]/g, (c) => `\\\\${c}`)}\"`;\n}\n\n/** Escape a value for a non-Exec .desktop key (only backslashes are special). */\nfunction desktopValue(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/\\n/g, ' ');\n}\n\nfunction xdgDataHome(): string {\n return process.env['XDG_DATA_HOME'] || join(homedir(), '.local/share');\n}\n\nfunction linuxPaths(id: string) {\n const dataHome = xdgDataHome();\n const appsDir = join(dataHome, 'applications');\n return {\n appsDir,\n entry: join(appsDir, `${id}.desktop`),\n iconDir: join(dataHome, 'icons/hicolor/scalable/apps'),\n icon: join(dataHome, `icons/hicolor/scalable/apps/${id}.svg`),\n };\n}\n\nasync function installLinux(opts: InstallOptions): Promise<LauncherResult> {\n const paths: string[] = [];\n const warnings: string[] = [];\n const p = linuxPaths(opts.id);\n\n // The icon is an SVG, which the scalable hicolor directory takes as-is.\n const sourceIcon = join(opts.distDir, 'assets/icon.svg');\n let iconName = 'application-x-executable';\n if (await exists(sourceIcon)) {\n await mkdir(p.iconDir, { recursive: true });\n await copyFile(sourceIcon, p.icon);\n paths.push(p.icon);\n iconName = opts.id;\n } else {\n warnings.push(`Icône introuvable (${sourceIcon}), icône générique utilisée`);\n }\n\n // --from-desktop: nobody is watching a terminal, so startup failures must be\n // reported in a browser window rather than written to a discarded stderr.\n const exec_ = [opts.nodePath, opts.cliEntry, ...launcherArgs(opts)]\n .map(desktopExecQuote)\n .join(' ');\n const lines = [\n '[Desktop Entry]',\n 'Type=Application',\n `Name=${desktopValue(opts.name)}`,\n 'Comment=Process and service manager',\n `Exec=${exec_}`,\n `Icon=${iconName}`,\n 'Terminal=false',\n 'Categories=Development;',\n 'StartupNotify=true',\n // Marker used by uninstall-desktop to refuse deleting a hand-written entry\n 'X-Runeya-Managed=true',\n ];\n lines.push(`Path=${desktopValue(launcherWorkingDir(opts.workingDir))}`);\n\n await mkdir(p.appsDir, { recursive: true });\n await writeFile(p.entry, lines.join('\\n') + '\\n', { mode: 0o755 });\n paths.push(p.entry);\n\n await tryExec('update-desktop-database', [p.appsDir], warnings);\n\n return { paths, warnings };\n}\n\nasync function uninstallLinux(id: string): Promise<LauncherResult> {\n const paths: string[] = [];\n const warnings: string[] = [];\n const p = linuxPaths(id);\n for (const target of [p.entry, p.icon]) {\n if (await exists(target)) {\n await rm(target, { force: true });\n paths.push(target);\n }\n }\n if (paths.length) await tryExec('update-desktop-database', [p.appsDir], warnings);\n return { paths, warnings };\n}\n\n// ─── macOS ───────────────────────────────────────────────────────────────────\n\n/** Escape a value destined for a <string> node of an Info.plist. */\nfunction plistString(value: string): string {\n return value\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n}\n\n/** Single-quote a value for the POSIX shell inside the .app stub script. */\nfunction shQuote(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\nfunction macAppPath(name: string): string {\n return join(homedir(), 'Applications', `${name}.app`);\n}\n\nasync function installMac(opts: InstallOptions): Promise<LauncherResult> {\n const warnings: string[] = [];\n const appPath = macAppPath(opts.name);\n const macosDir = join(appPath, 'Contents/MacOS');\n const resourcesDir = join(appPath, 'Contents/Resources');\n const execName = opts.id;\n\n await mkdir(macosDir, { recursive: true });\n await mkdir(resourcesDir, { recursive: true });\n\n // The bundle executable is a shell stub: no compiled code, no signing needed.\n // A locally generated .app carries no quarantine attribute, so Gatekeeper\n // lets it run even unsigned.\n const stub = [\n '#!/bin/sh',\n '# Generated by `runeya install-desktop` — safe to delete.',\n `cd ${shQuote(launcherWorkingDir(opts.workingDir))} || exit 1`,\n `exec ${[opts.nodePath, opts.cliEntry, ...launcherArgs(opts)].map(shQuote).join(' ')} \"$@\"`,\n '',\n ].filter(Boolean).join('\\n');\n await writeFile(join(macosDir, execName), stub, { mode: 0o755 });\n\n // CFBundleIconFile is only emitted when the .icns actually made it into the\n // bundle — a key pointing at a missing file makes Finder fall back silently,\n // which is harder to diagnose than no key at all.\n const sourceIcns = join(opts.distDir, 'assets/icon.icns');\n let iconKey = '';\n if (await exists(sourceIcns)) {\n await copyFile(sourceIcns, join(resourcesDir, `${execName}.icns`));\n iconKey = `\\n <key>CFBundleIconFile</key><string>${plistString(execName)}</string>`;\n } else {\n warnings.push(`Icône introuvable (${sourceIcns}), icône générique utilisée`);\n }\n\n const plist = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>CFBundleName</key><string>${plistString(opts.name)}</string>\n <key>CFBundleDisplayName</key><string>${plistString(opts.name)}</string>\n <key>CFBundleExecutable</key><string>${plistString(execName)}</string>\n <key>CFBundleIdentifier</key><string>dev.runeya.launcher.${plistString(opts.id)}</string>\n <key>CFBundlePackageType</key><string>APPL</string>${iconKey}\n <key>CFBundleInfoDictionaryVersion</key><string>6.0</string>\n <key>CFBundleShortVersionString</key><string>1.0</string>\n <key>NSHighResolutionCapable</key><true/>\n</dict>\n</plist>\n`;\n await writeFile(join(appPath, 'Contents/Info.plist'), plist);\n\n // Ask LaunchServices to notice the new bundle so Spotlight finds it right away.\n await tryExec(\n '/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister',\n ['-f', appPath],\n warnings,\n );\n\n return { paths: [appPath], warnings };\n}\n\nasync function uninstallMac(name: string): Promise<LauncherResult> {\n const appPath = macAppPath(name);\n if (!(await exists(appPath))) return { paths: [], warnings: [] };\n await rm(appPath, { recursive: true, force: true });\n return { paths: [appPath], warnings: [] };\n}\n\n// ─── Windows ─────────────────────────────────────────────────────────────────\n\n/** Single-quote a value for a PowerShell literal string. */\nexport function psQuote(value: string): string {\n return `'${value.replace(/'/g, \"''\")}'`;\n}\n\nfunction windowsLnkPath(name: string): string {\n const appData = process.env['APPDATA'] || join(homedir(), 'AppData/Roaming');\n return join(appData, 'Microsoft/Windows/Start Menu/Programs', `${name}.lnk`);\n}\n\n/**\n * Où vit le script qui lance Runeya sans console.\n *\n * Hors du dossier du menu Démarrer — un `.vbs` posé là apparaîtrait dans la\n * recherche Windows à côté du raccourci — et hors du `dist` du paquet, qu'une\n * réinstallation npm remplace : le script y disparaîtrait sans que rien ne le\n * recrée, faute de postinstall (npm 12 les bloque).\n */\nfunction windowsVbsPath(id: string): string {\n const localAppData = process.env['LOCALAPPDATA'] || join(homedir(), 'AppData/Local');\n return join(localAppData, 'Runeya', `${id}.vbs`);\n}\n\n/** Double-quote a value for a VBScript string literal. */\nexport function vbsQuote(value: string): string {\n return `\"${value.replace(/\"/g, '\"\"')}\"`;\n}\n\n/**\n * Le script qui lance Runeya **sans fenêtre**.\n *\n * `node.exe` est une application console : Windows lui alloue une console, et\n * un raccourci ne sait que la réduire (`WindowStyle = 7`) — d'où une fenêtre de\n * commande dans la barre des tâches pendant tout l'usage de l'application.\n *\n * `wscript.exe`, lui, est une application graphique : il n'ouvre aucune console\n * et lance sa cible en `SW_HIDE` (le `0` de `Run`). La console de Node existe\n * donc toujours — c'est ce qui compte : **elle est seulement cachée, pas\n * absente**, et tout ce que Runeya lance ensuite (l'agent, git, docker, les\n * services) l'hérite sans rien afficher. C'est la même intention que le\n * `windowsHide` des runners, posée une fois pour toute la descendance.\n *\n * Le `False` rend la main immédiatement : `wscript` sort, Runeya reste.\n */\nexport function windowsVbsScript(\n opts: Pick<InstallOptions, 'nodePath' | 'cliEntry' | 'port' | 'agentPort'> & { workingDir: string | null },\n): string {\n const command = [opts.nodePath, opts.cliEntry, ...launcherArgs(opts)]\n .map((part) => `\"${part}\"`)\n .join(' ');\n return [\n // Commentaires en ASCII : wscript lit un .vbs sans BOM comme de l'ANSI, et\n // des accents s'y afficheraient de travers à qui l'ouvre.\n \"' Runeya launcher - created by 'runeya install-desktop', do not edit.\",\n \"' wscript.exe opens no console; the 0 below starts Runeya hidden.\",\n 'Set sh = CreateObject(\"WScript.Shell\")',\n `sh.CurrentDirectory = ${vbsQuote(launcherWorkingDir(opts.workingDir))}`,\n `sh.Run ${vbsQuote(command)}, 0, False`,\n '',\n ].join('\\n');\n}\n\nasync function runPowerShell(script: string, warnings: string[]): Promise<void> {\n // -EncodedCommand avoids every layer of cmd.exe quoting.\n const encoded = Buffer.from(script, 'utf16le').toString('base64');\n try {\n await exec('powershell.exe', ['-NoProfile', '-NonInteractive', '-EncodedCommand', encoded]);\n } catch (err) {\n warnings.push(`PowerShell a échoué : ${(err as Error).message}`);\n throw err;\n }\n}\n\nasync function installWindows(opts: InstallOptions): Promise<LauncherResult> {\n const warnings: string[] = [];\n const lnk = windowsLnkPath(opts.name);\n\n // The .ico is referenced in place inside the installed dist rather than\n // copied: the shortcut already breaks if that dist moves, so a second copy\n // would only add a file to leave behind.\n const icoPath = join(opts.distDir, 'assets/icon.ico');\n const iconPath = (await exists(icoPath)) ? icoPath : null;\n if (!iconPath) warnings.push(`Icône introuvable (${icoPath}), icône de Node utilisée`);\n\n // Le raccourci ne lance pas Node : il lance `wscript.exe`, qui lance Node\n // sans console. Un raccourci pointant sur `node.exe` laissait une fenêtre de\n // commande dans la barre des tâches, `WindowStyle` ne sachant que la réduire.\n const vbs = windowsVbsPath(opts.id);\n await mkdir(dirname(vbs), { recursive: true });\n await writeFile(vbs, windowsVbsScript(opts), 'utf8');\n\n const wscript = join(process.env['SystemRoot'] || 'C:\\\\Windows', 'System32', 'wscript.exe');\n\n const script = [\n `$ws = New-Object -ComObject WScript.Shell`,\n `$sc = $ws.CreateShortcut(${psQuote(lnk)})`,\n `$sc.TargetPath = ${psQuote(wscript)}`,\n `$sc.Arguments = ${psQuote(`\"${vbs}\"`)}`,\n `$sc.WorkingDirectory = ${psQuote(launcherWorkingDir(opts.workingDir))}`,\n `$sc.Description = 'Runeya — process and service manager'`,\n // L'icône reste celle de Runeya : elle est déclarée à part de la cible.\n iconPath ? `$sc.IconLocation = ${psQuote(iconPath)}` : '',\n `$sc.Save()`,\n ].filter(Boolean).join('\\n');\n\n await mkdir(dirname(lnk), { recursive: true });\n await runPowerShell(script, warnings);\n\n return { paths: [lnk, vbs], warnings };\n}\n\nasync function uninstallWindows(name: string, id: string): Promise<LauncherResult> {\n // Les deux fichiers, et chacun pour lui-même : un raccourci posé avant que le\n // lanceur ne passe par `wscript` n'a pas de `.vbs` à côté de lui, et son\n // absence n'est pas une raison de laisser le raccourci en place.\n const removed: string[] = [];\n for (const path of [windowsLnkPath(name), windowsVbsPath(id)]) {\n if (!(await exists(path))) continue;\n await rm(path, { force: true });\n removed.push(path);\n }\n return { paths: removed, warnings: [] };\n}\n\n// ─── Entry points ────────────────────────────────────────────────────────────\n\nexport async function installDesktopLauncher(opts: InstallOptions): Promise<LauncherResult> {\n switch (process.platform) {\n case 'linux':\n case 'freebsd':\n case 'openbsd':\n return installLinux(opts);\n case 'darwin':\n return installMac(opts);\n case 'win32':\n return installWindows(opts);\n default:\n throw new Error(`Plateforme non supportée : ${process.platform}`);\n }\n}\n\nexport async function uninstallDesktopLauncher(name: string, id: string): Promise<LauncherResult> {\n switch (process.platform) {\n case 'linux':\n case 'freebsd':\n case 'openbsd':\n return uninstallLinux(id);\n case 'darwin':\n return uninstallMac(name);\n case 'win32':\n return uninstallWindows(name, id);\n default:\n throw new Error(`Plateforme non supportée : ${process.platform}`);\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,209 +0,0 @@
1
- import {
2
- findFreePortPair,
3
- isPortFree,
4
- parsePort
5
- } from "./chunk-O2KOX4LU.js";
6
-
7
- // src/desktop-wizard.ts
8
- import { createInterface } from "readline/promises";
9
- import { basename } from "path";
10
- var DEFAULT_PORT = 4e3;
11
- var useColor = process.stdout.isTTY && !process.env["NO_COLOR"];
12
- var c = {
13
- bold: (s) => useColor ? `\x1B[1m${s}\x1B[0m` : s,
14
- dim: (s) => useColor ? `\x1B[2m${s}\x1B[0m` : s,
15
- cyan: (s) => useColor ? `\x1B[36m${s}\x1B[0m` : s,
16
- green: (s) => useColor ? `\x1B[32m${s}\x1B[0m` : s,
17
- yellow: (s) => useColor ? `\x1B[33m${s}\x1B[0m` : s
18
- };
19
- function shouldRunWizard(rest, hasPositional) {
20
- if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
21
- if (process.env["CI"]) return false;
22
- if (hasPositional) return false;
23
- return !rest.some((a) => a === "--name" || a === "--no-cwd" || a === "--yes" || a === "-y" || a === "--port" || a === "--agent-port");
24
- }
25
- var WizardAborted = class extends Error {
26
- };
27
- async function askChoice(rl, question, choices) {
28
- console.log(`
29
- ${c.bold(question)}`);
30
- choices.forEach((choice, i) => {
31
- console.log(` ${c.cyan(String(i + 1))}. ${choice.label}`);
32
- console.log(` ${c.dim(choice.hint)}`);
33
- });
34
- for (; ; ) {
35
- let answer;
36
- try {
37
- answer = (await rl.question(`
38
- ${c.dim("Votre choix")} [1-${choices.length}] \u203A `)).trim();
39
- } catch {
40
- throw new WizardAborted();
41
- }
42
- const index = Number(answer) - 1;
43
- if (Number.isInteger(index) && index >= 0 && index < choices.length) return index;
44
- console.log(c.yellow(` R\xE9ponse attendue : un nombre entre 1 et ${choices.length}.`));
45
- }
46
- }
47
- async function askText(rl, question, fallback) {
48
- console.log(`
49
- ${c.bold(question)}`);
50
- console.log(` ${c.dim(`Entr\xE9e pour garder \xAB ${fallback} \xBB`)}`);
51
- try {
52
- const answer = (await rl.question(`
53
- ${c.dim("Nom")} \u203A `)).trim();
54
- return answer || fallback;
55
- } catch {
56
- return fallback;
57
- }
58
- }
59
- async function askPorts(rl) {
60
- const suggestion = await findFreePortPair();
61
- const defaultsFree = await isPortFree(DEFAULT_PORT) && await isPortFree(DEFAULT_PORT + 1);
62
- const choices = [
63
- ...suggestion === null ? [] : [{
64
- label: `Ports d\xE9di\xE9s ${c.dim(`(${suggestion} et ${suggestion + 1})`)}`,
65
- hint: "Tir\xE9s au hasard parmi les ports libres \u2014 recommand\xE9, aucun risque de conflit"
66
- }],
67
- {
68
- label: `Ports par d\xE9faut de Runeya ${c.dim(`(${DEFAULT_PORT} et ${DEFAULT_PORT + 1})`)}`,
69
- hint: defaultsFree ? "Libres actuellement" : `${DEFAULT_PORT} ou ${DEFAULT_PORT + 1} est d\xE9j\xE0 occup\xE9 \u2014 le raccourci \xE9chouera tant que ce sera le cas`
70
- },
71
- { label: "Choisir moi-m\xEAme", hint: "Saisir le port de Runeya, puis celui de l'agent" }
72
- ];
73
- const picked = await askChoice(rl, "Quels ports ?", choices);
74
- const offset = suggestion === null ? 1 : 0;
75
- if (picked + offset === 0) return { port: suggestion, agentPort: suggestion + 1 };
76
- if (picked + offset === 1) return { port: null, agentPort: null };
77
- const port = await askPort(rl, "Port de Runeya ?", suggestion ?? DEFAULT_PORT);
78
- const agentPort = await askPort(rl, "Port de l'agent ?", port + 1);
79
- return { port, agentPort };
80
- }
81
- async function askPort(rl, question, fallback) {
82
- for (; ; ) {
83
- console.log(`
84
- ${c.bold(question)}`);
85
- console.log(` ${c.dim(`Entr\xE9e pour garder ${fallback}`)}`);
86
- let answer;
87
- try {
88
- answer = (await rl.question(`
89
- ${c.dim("Port")} \u203A `)).trim();
90
- } catch {
91
- return fallback;
92
- }
93
- if (answer === "") return fallback;
94
- const port = parsePort(answer);
95
- if (port === null) {
96
- console.log(c.yellow(" R\xE9ponse attendue : un entier entre 1 et 65535."));
97
- continue;
98
- }
99
- if (!await isPortFree(port)) {
100
- console.log(c.yellow(` Attention : le port ${port} est occup\xE9 actuellement.`));
101
- }
102
- return port;
103
- }
104
- }
105
- async function runInstallWizard(cwd) {
106
- const rl = createInterface({ input: process.stdin, output: process.stdout });
107
- let aborted = false;
108
- rl.on("SIGINT", () => {
109
- aborted = true;
110
- rl.close();
111
- });
112
- try {
113
- console.log(`
114
- ${c.bold("Cr\xE9ation d'un raccourci Runeya")}`);
115
- console.log(c.dim("\u2500".repeat(46)));
116
- const scope = await askChoice(rl, "Quel type de raccourci ?", [
117
- {
118
- label: `Ce projet ${c.dim(`(${basename(cwd)})`)}`,
119
- hint: `D\xE9marre Runeya dans ${cwd}`
120
- },
121
- {
122
- label: "Global",
123
- hint: "D\xE9marre Runeya dans votre dossier personnel \u2014 les donn\xE9es iront dans ~/.runeya"
124
- }
125
- ]);
126
- const workingDir = scope === 0 ? cwd : null;
127
- const suggested = workingDir ? `Runeya \u2014 ${basename(workingDir)}` : "Runeya";
128
- const name = await askText(rl, "Nom du raccourci ?", suggested);
129
- const { port, agentPort } = await askPorts(rl);
130
- return { workingDir, name, port, agentPort };
131
- } catch (err) {
132
- if (err instanceof WizardAborted) return null;
133
- throw err;
134
- } finally {
135
- if (aborted) console.log("\nAnnul\xE9.");
136
- rl.close();
137
- }
138
- }
139
- function keyValueBlock(rows) {
140
- const width = Math.max(...rows.map(([k]) => k.length));
141
- return rows.map(([k, v]) => ` ${c.dim(k.padEnd(width))} ${v}`).join("\n");
142
- }
143
- function shellArg(value) {
144
- return /^[\w@%+=:,./-]+$/.test(value) ? value : `'${value.replace(/'/g, `'\\''`)}'`;
145
- }
146
- function printInstallReport(report) {
147
- const { name, workingDir, nodePath, port, agentPort, result } = report;
148
- console.log(`
149
- ${c.green("\u2713")} ${c.bold("Raccourci cr\xE9\xE9")}`);
150
- console.log(c.dim("\u2500".repeat(46)));
151
- const effectivePort = port ?? 4e3;
152
- console.log(keyValueBlock([
153
- ["Nom", name],
154
- ["Port\xE9e", workingDir ? `ce projet \u2014 ${workingDir}` : "global (aucun dossier fix\xE9)"],
155
- ["Adresse", `http://localhost:${effectivePort}`],
156
- ["Ports", `${effectivePort} (Runeya) \xB7 ${agentPort ?? effectivePort + 1} (agent)${port === null ? c.dim(" \u2014 d\xE9fauts") : ""}`],
157
- ["Node", nodePath]
158
- ]));
159
- console.log(`
160
- ${c.bold("Fichiers \xE9crits")}`);
161
- for (const path of result.paths) console.log(` ${path}`);
162
- for (const warning of result.warnings) console.log(`
163
- ${c.yellow("\u26A0")} ${warning}`);
164
- console.log(`
165
- ${c.bold("O\xF9 le trouver")}`);
166
- console.log(` ${c.dim(whereToFind())}`);
167
- console.log(`
168
- ${c.bold("Pour le supprimer")}`);
169
- console.log(` ${c.cyan(`runeya uninstall-desktop --name ${shellArg(name)}`)}`);
170
- console.log(` ${c.dim("Cette commande retire exactement les fichiers list\xE9s ci-dessus.")}`);
171
- console.log(`
172
- ${c.dim("Le raccourci pointe vers le Node ci-dessus. Si vous changez de version")}`);
173
- console.log(`${c.dim("de Node, relancez `runeya install-desktop` pour le repointer.")}
174
- `);
175
- }
176
- function whereToFind() {
177
- switch (process.platform) {
178
- case "darwin":
179
- return "Dans ~/Applications, et via Spotlight (\u2318 + espace).";
180
- case "win32":
181
- return "Dans le menu D\xE9marrer.";
182
- default:
183
- return "Dans le menu des applications de votre bureau. Certains environnements demandent une reconnexion.";
184
- }
185
- }
186
- function printUninstallReport(name, result) {
187
- if (result.paths.length === 0) {
188
- console.log(`
189
- Aucun raccourci \xAB ${name} \xBB trouv\xE9.`);
190
- console.log(`${c.dim("Astuce : pr\xE9cisez le nom exact avec --name, ou le dossier du projet en argument.")}
191
- `);
192
- return;
193
- }
194
- console.log(`
195
- ${c.green("\u2713")} ${c.bold("Raccourci supprim\xE9")} ${c.dim(`\u2014 ${name}`)}`);
196
- console.log(c.dim("\u2500".repeat(46)));
197
- for (const path of result.paths) console.log(` ${path}`);
198
- for (const warning of result.warnings) console.log(`
199
- ${c.yellow("\u26A0")} ${warning}`);
200
- console.log("");
201
- }
202
- export {
203
- printInstallReport,
204
- printUninstallReport,
205
- runInstallWizard,
206
- shellArg,
207
- shouldRunWizard
208
- };
209
- //# sourceMappingURL=desktop-wizard-4CYANX2O.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/desktop-wizard.ts"],"sourcesContent":["/**\n * Interactive front-end for `runeya install-desktop`.\n *\n * Runs only when the sub-command is invoked bare on a TTY. Any flag that\n * already answers a question (--name, --no-cwd, a path, --yes) is taken as\n * explicit intent and skips the wizard entirely, so scripts and CI keep\n * working unattended.\n */\nimport { createInterface } from 'node:readline/promises';\nimport { basename } from 'node:path';\nimport { findFreePortPair, isPortFree, parsePort } from './free-port.js';\nimport type { LauncherResult } from './desktop-launcher.js';\n\n/** Runeya's own defaults, offered as one of the port choices. */\nconst DEFAULT_PORT = 4000;\n\n/** ANSI helpers — disabled when the output is piped or NO_COLOR is set. */\nconst useColor = process.stdout.isTTY && !process.env['NO_COLOR'];\nconst c = {\n bold: (s: string) => (useColor ? `\\x1b[1m${s}\\x1b[0m` : s),\n dim: (s: string) => (useColor ? `\\x1b[2m${s}\\x1b[0m` : s),\n cyan: (s: string) => (useColor ? `\\x1b[36m${s}\\x1b[0m` : s),\n green: (s: string) => (useColor ? `\\x1b[32m${s}\\x1b[0m` : s),\n yellow: (s: string) => (useColor ? `\\x1b[33m${s}\\x1b[0m` : s),\n};\n\nexport type WizardAnswers = {\n workingDir: string | null;\n name: string;\n port: number | null;\n agentPort: number | null;\n};\n\n/** True when we can and should prompt: a real terminal, and nothing pre-answered. */\nexport function shouldRunWizard(rest: string[], hasPositional: boolean): boolean {\n if (!process.stdin.isTTY || !process.stdout.isTTY) return false;\n if (process.env['CI']) return false;\n if (hasPositional) return false;\n return !rest.some((a) =>\n a === '--name' || a === '--no-cwd' || a === '--yes' || a === '-y'\n || a === '--port' || a === '--agent-port');\n}\n\n/** Thrown when stdin ends or the user interrupts on a question with no safe default. */\nclass WizardAborted extends Error {}\n\n/**\n * Ask a single-key numbered question. Returns the chosen index.\n * Anything unrecognised re-asks rather than silently picking the default —\n * this writes files into the user's desktop environment.\n */\nasync function askChoice(\n rl: ReturnType<typeof createInterface>,\n question: string,\n choices: { label: string; hint: string }[],\n): Promise<number> {\n console.log(`\\n${c.bold(question)}`);\n choices.forEach((choice, i) => {\n console.log(` ${c.cyan(String(i + 1))}. ${choice.label}`);\n console.log(` ${c.dim(choice.hint)}`);\n });\n\n for (;;) {\n // A closed stdin rejects the pending question. There is no safe default\n // here — the answer decides where files get written — so abort.\n let answer: string;\n try {\n answer = (await rl.question(`\\n${c.dim('Votre choix')} [1-${choices.length}] › `)).trim();\n } catch {\n throw new WizardAborted();\n }\n const index = Number(answer) - 1;\n if (Number.isInteger(index) && index >= 0 && index < choices.length) return index;\n console.log(c.yellow(` Réponse attendue : un nombre entre 1 et ${choices.length}.`));\n }\n}\n\n/** Ask for free text, falling back to `fallback` when the user just hits Enter. */\nasync function askText(\n rl: ReturnType<typeof createInterface>,\n question: string,\n fallback: string,\n): Promise<string> {\n console.log(`\\n${c.bold(question)}`);\n console.log(` ${c.dim(`Entrée pour garder « ${fallback} »`)}`);\n // Enter and end-of-input both mean \"keep the suggestion\".\n try {\n const answer = (await rl.question(`\\n${c.dim('Nom')} › `)).trim();\n return answer || fallback;\n } catch {\n return fallback;\n }\n}\n\n/**\n * Ask which ports the launcher should use.\n *\n * A dedicated pair is offered first, and is the right answer for most people:\n * the reason to pin a port in a shortcut is so a second Runeya — a dev server,\n * another project's launcher — cannot take it out from under you.\n */\nasync function askPorts(\n rl: ReturnType<typeof createInterface>,\n): Promise<{ port: number | null; agentPort: number | null }> {\n const suggestion = await findFreePortPair();\n const defaultsFree = (await isPortFree(DEFAULT_PORT)) && (await isPortFree(DEFAULT_PORT + 1));\n\n const choices = [\n ...(suggestion === null ? [] : [{\n label: `Ports dédiés ${c.dim(`(${suggestion} et ${suggestion + 1})`)}`,\n hint: 'Tirés au hasard parmi les ports libres — recommandé, aucun risque de conflit',\n }]),\n {\n label: `Ports par défaut de Runeya ${c.dim(`(${DEFAULT_PORT} et ${DEFAULT_PORT + 1})`)}`,\n hint: defaultsFree\n ? 'Libres actuellement'\n : `${DEFAULT_PORT} ou ${DEFAULT_PORT + 1} est déjà occupé — le raccourci échouera tant que ce sera le cas`,\n },\n { label: 'Choisir moi-même', hint: 'Saisir le port de Runeya, puis celui de l\\'agent' },\n ];\n\n const picked = await askChoice(rl, 'Quels ports ?', choices);\n // The suggestion occupies slot 0 only when there is one to offer\n const offset = suggestion === null ? 1 : 0;\n\n if (picked + offset === 0) return { port: suggestion, agentPort: suggestion! + 1 };\n if (picked + offset === 1) return { port: null, agentPort: null };\n\n const port = await askPort(rl, 'Port de Runeya ?', suggestion ?? DEFAULT_PORT);\n const agentPort = await askPort(rl, 'Port de l\\'agent ?', port + 1);\n return { port, agentPort };\n}\n\n/** Ask for a port, re-asking until the answer is a valid one. Warns if taken. */\nasync function askPort(\n rl: ReturnType<typeof createInterface>,\n question: string,\n fallback: number,\n): Promise<number> {\n for (;;) {\n console.log(`\\n${c.bold(question)}`);\n console.log(` ${c.dim(`Entrée pour garder ${fallback}`)}`);\n\n let answer: string;\n try {\n answer = (await rl.question(`\\n${c.dim('Port')} › `)).trim();\n } catch {\n return fallback; // end of input reads as \"keep the suggestion\"\n }\n if (answer === '') return fallback;\n\n const port = parsePort(answer);\n if (port === null) {\n console.log(c.yellow(' Réponse attendue : un entier entre 1 et 65535.'));\n continue;\n }\n // Taken is a warning, not a refusal: the user may be about to free it.\n if (!(await isPortFree(port))) {\n console.log(c.yellow(` Attention : le port ${port} est occupé actuellement.`));\n }\n return port;\n }\n}\n\n/**\n * Walk the user through scope and name.\n * Returns null if they abort (Ctrl+C / Ctrl+D), so the caller can exit quietly.\n */\nexport async function runInstallWizard(cwd: string): Promise<WizardAnswers | null> {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n\n // Ctrl+C during a question closes the interface and rejects the pending\n // promise; treat that as an abort rather than a crash.\n let aborted = false;\n rl.on('SIGINT', () => { aborted = true; rl.close(); });\n\n try {\n console.log(`\\n${c.bold('Création d\\'un raccourci Runeya')}`);\n console.log(c.dim('─'.repeat(46)));\n\n const scope = await askChoice(rl, 'Quel type de raccourci ?', [\n {\n label: `Ce projet ${c.dim(`(${basename(cwd)})`)}`,\n hint: `Démarre Runeya dans ${cwd}`,\n },\n {\n label: 'Global',\n hint: 'Démarre Runeya dans votre dossier personnel — les données iront dans ~/.runeya',\n },\n ]);\n\n const workingDir = scope === 0 ? cwd : null;\n const suggested = workingDir ? `Runeya — ${basename(workingDir)}` : 'Runeya';\n const name = await askText(rl, 'Nom du raccourci ?', suggested);\n const { port, agentPort } = await askPorts(rl);\n\n return { workingDir, name, port, agentPort };\n } catch (err) {\n if (err instanceof WizardAborted) return null;\n throw err;\n } finally {\n if (aborted) console.log('\\nAnnulé.');\n rl.close();\n }\n}\n\n// ─── Result step ─────────────────────────────────────────────────────────────\n\n/** Right-pad the keys of a two-column block so the values line up. */\nfunction keyValueBlock(rows: [string, string][]): string {\n const width = Math.max(...rows.map(([k]) => k.length));\n return rows.map(([k, v]) => ` ${c.dim(k.padEnd(width))} ${v}`).join('\\n');\n}\n\n/**\n * Quote a value for the shell only when it needs it, so the printed uninstall\n * command stays copy-pasteable in both cases.\n */\nexport function shellArg(value: string): string {\n return /^[\\w@%+=:,./-]+$/.test(value) ? value : `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\nexport type InstallReport = {\n name: string;\n workingDir: string | null;\n nodePath: string;\n port: number | null;\n agentPort: number | null;\n result: LauncherResult;\n};\n\nexport function printInstallReport(report: InstallReport): void {\n const { name, workingDir, nodePath, port, agentPort, result } = report;\n\n console.log(`\\n${c.green('✓')} ${c.bold('Raccourci créé')}`);\n console.log(c.dim('─'.repeat(46)));\n const effectivePort = port ?? 4000;\n console.log(keyValueBlock([\n ['Nom', name],\n ['Portée', workingDir ? `ce projet — ${workingDir}` : 'global (aucun dossier fixé)'],\n ['Adresse', `http://localhost:${effectivePort}`],\n ['Ports', `${effectivePort} (Runeya) · ${agentPort ?? effectivePort + 1} (agent)${port === null ? c.dim(' — défauts') : ''}`],\n ['Node', nodePath],\n ]));\n\n console.log(`\\n${c.bold('Fichiers écrits')}`);\n for (const path of result.paths) console.log(` ${path}`);\n\n for (const warning of result.warnings) console.log(`\\n${c.yellow('⚠')} ${warning}`);\n\n console.log(`\\n${c.bold('Où le trouver')}`);\n console.log(` ${c.dim(whereToFind())}`);\n\n console.log(`\\n${c.bold('Pour le supprimer')}`);\n console.log(` ${c.cyan(`runeya uninstall-desktop --name ${shellArg(name)}`)}`);\n console.log(` ${c.dim('Cette commande retire exactement les fichiers listés ci-dessus.')}`);\n\n console.log(`\\n${c.dim('Le raccourci pointe vers le Node ci-dessus. Si vous changez de version')}`);\n console.log(`${c.dim('de Node, relancez `runeya install-desktop` pour le repointer.')}\\n`);\n}\n\n/** Per-platform hint about where the entry shows up. */\nfunction whereToFind(): string {\n switch (process.platform) {\n case 'darwin':\n return 'Dans ~/Applications, et via Spotlight (⌘ + espace).';\n case 'win32':\n return 'Dans le menu Démarrer.';\n default:\n return 'Dans le menu des applications de votre bureau. Certains environnements demandent une reconnexion.';\n }\n}\n\nexport function printUninstallReport(name: string, result: LauncherResult): void {\n if (result.paths.length === 0) {\n console.log(`\\nAucun raccourci « ${name} » trouvé.`);\n console.log(`${c.dim('Astuce : précisez le nom exact avec --name, ou le dossier du projet en argument.')}\\n`);\n return;\n }\n\n console.log(`\\n${c.green('✓')} ${c.bold('Raccourci supprimé')} ${c.dim(`— ${name}`)}`);\n console.log(c.dim('─'.repeat(46)));\n for (const path of result.paths) console.log(` ${path}`);\n for (const warning of result.warnings) console.log(`\\n${c.yellow('⚠')} ${warning}`);\n console.log('');\n}\n"],"mappings":"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","names":[]}
@@ -1,10 +0,0 @@
1
- import {
2
- settingsManager
3
- } from "./chunk-I7JHF5FE.js";
4
- import "./chunk-BDQOBEZ3.js";
5
- import "./chunk-5EMEJNVU.js";
6
- import "./chunk-ZFELQG4B.js";
7
- export {
8
- settingsManager
9
- };
10
- //# sourceMappingURL=settings-manager-J4QBIU3T.js.map