@runeya/runeya 2.0.132 → 2.0.133

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 (235) hide show
  1. package/agent/index.js +1 -1
  2. package/agent/index.js.map +1 -1
  3. package/{agent-manager-J75NZ6MN.js → agent-manager-TUFAFC6U.js} +3 -3
  4. package/{chat-ICUWJZEX.js → chat-37VHPDPJ.js} +6 -6
  5. package/{chunk-WN36W5OW.js → chunk-5EMEJNVU.js} +2 -2
  6. package/chunk-5EMEJNVU.js.map +1 -0
  7. package/{chunk-3HGTIUGB.js → chunk-7JAJSV4L.js} +2 -2
  8. package/{chunk-24UJRQRM.js → chunk-I7JHF5FE.js} +2 -2
  9. package/{chunk-RLLUJCPQ.js → chunk-JHJHU6UX.js} +14 -11
  10. package/chunk-JHJHU6UX.js.map +1 -0
  11. package/{chunk-PVLDFBL6.js → chunk-TG44C7QT.js} +6 -6
  12. package/{companion-IYK2652T.js → companion-27RCQRZV.js} +4 -4
  13. package/{desktop-launcher-GHCALSOS.js → desktop-launcher-3COY6F6H.js} +2 -2
  14. package/index.js +13 -5
  15. package/index.js.map +1 -1
  16. package/log-file-XAEHICMH.js +123 -0
  17. package/log-file-XAEHICMH.js.map +1 -0
  18. package/mcp-server/index.js +6 -4
  19. package/mcp-server/index.js.map +1 -1
  20. package/package.json +1 -1
  21. package/{settings-manager-3G5RHW3X.js → settings-manager-J4QBIU3T.js} +3 -3
  22. package/{src-FS7Y4DA7.js → src-PSJSIJN6.js} +10 -9
  23. package/src-PSJSIJN6.js.map +1 -0
  24. package/web/assets/{AgentScalarChatInterface.vue-CImJBBKk.js → AgentScalarChatInterface.vue-BMJAUTbn.js} +1 -1
  25. package/web/assets/{AgentTerminalPage-iRrYZG3N.js → AgentTerminalPage-DJny5leF.js} +1 -1
  26. package/web/assets/AiChatPage-Co5YwUra.js +1 -0
  27. package/web/assets/{AppLayout-CkZbU0SI.js → AppLayout-DhRnQ7sB.js} +1 -1
  28. package/web/assets/{AuditPage-C-yVNrOi.js → AuditPage-B87IuU2E.js} +1 -1
  29. package/web/assets/{CloudAccountPage-7XqPLVAS.js → CloudAccountPage-B9zHVg91.js} +1 -1
  30. package/web/assets/CloudAccountPage-ClRW-luH.js +1 -0
  31. package/web/assets/{CloudMessagingPage-CZBpneaV.js → CloudMessagingPage-Cil491lq.js} +1 -1
  32. package/web/assets/{DashboardPage-CBZZyVwY.js → DashboardPage-vQ69rIA_.js} +1 -1
  33. package/web/assets/{DirectoryPickerDialog-1MThX25G.js → DirectoryPickerDialog-BZG4wryg.js} +1 -1
  34. package/web/assets/{EditorIcon-BVisg2uv.js → EditorIcon-V_Fqyf2s.js} +1 -1
  35. package/web/assets/{EnvironmentForm-C82fYWhW.js → EnvironmentForm-qlF1EeZ2.js} +1 -1
  36. package/web/assets/{EnvironmentFormPage-BVOpMMJ7.js → EnvironmentFormPage-BrW-34oI.js} +1 -1
  37. package/web/assets/{EnvironmentListPage-CPRmFtVH.js → EnvironmentListPage-BdEPphrn.js} +1 -1
  38. package/web/assets/{KanbanBoardPage-pzBPUjj2.js → KanbanBoardPage-DQKqtxxI.js} +3 -3
  39. package/web/assets/KanbanBoardPage-cXyI-2uZ.css +1 -0
  40. package/web/assets/{KanbanListPage-Cy0eP5v1.js → KanbanListPage-5-yh2hO3.js} +1 -1
  41. package/web/assets/{LaunchProjectPage-Bn_wU_QT.js → LaunchProjectPage-g_5Wme1T.js} +1 -1
  42. package/web/assets/{LaunchServicesPage-BuxokNH7.js → LaunchServicesPage-BxUrOZ44.js} +1 -1
  43. package/web/assets/{LogViewer-DFPxgP8T.js → LogViewer-DhTTUJLn.js} +1 -1
  44. package/web/assets/{OrgKeyPrompt-B8qmru6I.js → OrgKeyPrompt-Bs08QGKq.js} +1 -1
  45. package/web/assets/{OrgLogo-9eOcBM3O.js → OrgLogo-CWXqzPiS.js} +1 -1
  46. package/web/assets/{ProcessControls-BA9IDUMF.js → ProcessControls-DIN7XQOl.js} +1 -1
  47. package/web/assets/{ProcessDetailPage-CnOdgJXS.js → ProcessDetailPage-DMFYdJO6.js} +1 -1
  48. package/web/assets/{ProcessMetrics-fFZhpyqE.js → ProcessMetrics-DED63acT.js} +1 -1
  49. package/web/assets/{RandomJobTestPage-Cw5KA5rW.js → RandomJobTestPage-CqOMbdjK.js} +1 -1
  50. package/web/assets/{ScenarioEditorPage-DY9Sfei7.js → ScenarioEditorPage-DPuYttHT.js} +1 -1
  51. package/web/assets/{SendToChatDialog-DLR7jXBG.js → SendToChatDialog-qbllbAWj.js} +1 -1
  52. package/web/assets/{ServiceControlsBar-szGNMHjF.js → ServiceControlsBar-DxPLkFTF.js} +1 -1
  53. package/web/assets/{ServiceDetailPage-BXZ2tvHn.js → ServiceDetailPage-Cp0zW4vF.js} +1 -1
  54. package/web/assets/{ServiceFormPage-B6oUWP9J.js → ServiceFormPage-COy2T7gp.js} +1 -1
  55. package/web/assets/{SettingsPage-95JC2bIP.js → SettingsPage-DsLaZJWX.js} +4 -4
  56. package/web/assets/{UnlockPage-P4gYB5LT.js → UnlockPage-shod0TOQ.js} +1 -1
  57. package/web/assets/{VaultMigrationPage-CQH54K0y.js → VaultMigrationPage-BDJIDUa6.js} +1 -1
  58. package/web/assets/{VersionBadge-D-Zv0XzJ.js → VersionBadge-V6I68xY-.js} +1 -1
  59. package/web/assets/WikiPage-CRPtaZ4n.js +1 -0
  60. package/web/assets/{WikiView-BLoRr_y4.js → WikiView-trPq-25v.js} +1 -1
  61. package/web/assets/{add-scalar-classes-Bpf67R_k.js → add-scalar-classes-CSUXL3L0.js} +3 -3
  62. package/web/assets/{autocomplete-B4ASWozR.js → autocomplete-DKHFlhhO.js} +1 -1
  63. package/web/assets/{basic-shape-diamond.svg-D96ayS7-.js → basic-shape-diamond.svg-DCxdtThm.js} +1 -1
  64. package/web/assets/{basic-shape-hexagon.svg-lBCgoQIf.js → basic-shape-hexagon.svg-BllqL52E.js} +1 -1
  65. package/web/assets/{basic-shape-primary-circle-ellipse-round.svg-BEzXT_e-.js → basic-shape-primary-circle-ellipse-round.svg-qsZEp39q.js} +1 -1
  66. package/web/assets/{basic-shape-primary-square-rectangle.svg-Bkzr23_8.js → basic-shape-primary-square-rectangle.svg-DrsT6mAT.js} +1 -1
  67. package/web/assets/{basic-shape-shield.svg-C3H6eT_i.js → basic-shape-shield.svg-Cbxs8_Nf.js} +1 -1
  68. package/web/assets/{browser-JZPiFr6p.js → browser-3Xde4kSz.js} +1 -1
  69. package/web/assets/{browser-C1dU95Eq.js → browser-pqiHj2Ya.js} +1 -1
  70. package/web/assets/{card-Carw-Smf.js → card-wrii-nrq.js} +1 -1
  71. package/web/assets/{checkbox-SY6iZYJT.js → checkbox-BcVCOcOx.js} +1 -1
  72. package/web/assets/{chip-jKPsBaDG.js → chip-DCUZHTdu.js} +1 -1
  73. package/web/assets/{client-CrX3je4X.js → client-B9hsmT1s.js} +1 -1
  74. package/web/assets/{cloud-chat.store-Cv-pkXPK.js → cloud-chat.store-o00oRsgO.js} +1 -1
  75. package/web/assets/cloud-client-TKLL1zwR.js +1 -0
  76. package/web/assets/{cloud-session-CY8qNDWs.js → cloud-session-B9wU6_5G.js} +2 -2
  77. package/web/assets/cloud-session-DloNvu91.js +1 -0
  78. package/web/assets/{column-Du74odg_.js → column-DA7ijaud.js} +1 -1
  79. package/web/assets/{composables-CAPumxhl.js → composables-DgWeyWnW.js} +1 -1
  80. package/web/assets/{computer-device-desktop-monitor.svg-CKfHZCAn.js → computer-device-desktop-monitor.svg-2AkCd4Vg.js} +1 -1
  81. package/web/assets/{computer-device-desktop.svg-FokfiMmI.js → computer-device-desktop.svg-BX6dDfTh.js} +1 -1
  82. package/web/assets/{computer-device-laptop.svg-u5TTufiX.js → computer-device-laptop.svg-DQot5tMG.js} +1 -1
  83. package/web/assets/{computer-device-mobile-phone-android-samsung-back.svg-D-4JYDXb.js → computer-device-mobile-phone-android-samsung-back.svg-BqQpExMo.js} +1 -1
  84. package/web/assets/{computer-device-mobile-phone-android-samsung.svg-CZGGF9sY.js → computer-device-mobile-phone-android-samsung.svg-uWqzS9ou.js} +1 -1
  85. package/web/assets/{computer-device-mobile-phone-iphone-x-back.svg-DA78gxI_.js → computer-device-mobile-phone-iphone-x-back.svg-lGlmpWrH.js} +1 -1
  86. package/web/assets/{computer-device-mobile-phone-iphone-x.svg-B4MANHvY.js → computer-device-mobile-phone-iphone-x.svg-BZkIeiFY.js} +1 -1
  87. package/web/assets/{computer-device-mobile-tablet-touch.svg-C8TQMpJm.js → computer-device-mobile-tablet-touch.svg-BIY2ojxF.js} +1 -1
  88. package/web/assets/{computer-device-mobile-tablet.svg-BwWJUi6h.js → computer-device-mobile-tablet.svg-EsUtZRCO.js} +1 -1
  89. package/web/assets/{computer-device-network-ethernet-cat6.svg-BbuOLgRf.js → computer-device-network-ethernet-cat6.svg-CFYKvBLS.js} +1 -1
  90. package/web/assets/{computer-device-network-lan-www.svg-Bus_xZ3r.js → computer-device-network-lan-www.svg-DD140-i0.js} +1 -1
  91. package/web/assets/{computer-device-network-wifi-connection.svg-D93e73Wq.js → computer-device-network-wifi-connection.svg-B6xlwqRF.js} +1 -1
  92. package/web/assets/{computer-device-network-wifi-router.svg-6qPxKjkZ.js → computer-device-network-wifi-router.svg-D2oEGuXL.js} +1 -1
  93. package/web/assets/{cssMode-BA6ryPYU.js → cssMode-CyhbxQFj.js} +1 -1
  94. package/web/assets/{divider-Nf1cI936.js → divider-bEPGnPmT.js} +1 -1
  95. package/web/assets/{docx-preview-Beq_uoGc.js → docx-preview-CPCu7gIi.js} +1 -1
  96. package/web/assets/{ecology-science-erlenmeyer-flask.svg-D60hNAZ7.js → ecology-science-erlenmeyer-flask.svg-C3Zo72lq.js} +1 -1
  97. package/web/assets/{fieldset-BO8ymcQg.js → fieldset-BSON_QE9.js} +1 -1
  98. package/web/assets/{freemarker2-u4uWoBOZ.js → freemarker2-764Mz1z9.js} +1 -1
  99. package/web/assets/{handlebars-Crco_whq.js → handlebars-BcplsCVf.js} +1 -1
  100. package/web/assets/{html-krzCI2Gx.js → html-Ab2Gwigb.js} +1 -1
  101. package/web/assets/{htmlMode-C9vDwT8E.js → htmlMode-D8yRZKkz.js} +1 -1
  102. package/web/assets/{image-flash-lightning.svg-B4xlEwgS.js → image-flash-lightning.svg-D-jM06gw.js} +1 -1
  103. package/web/assets/{image-picture-flower.svg-DXs_C4Eb.js → image-picture-flower.svg-X2opjZMU.js} +1 -1
  104. package/web/assets/{index-0Vd4ITAj.js → index-CI76mltd.js} +6 -6
  105. package/web/assets/{interface-alert-exclamation-diamond.svg-CQmiBFHu.js → interface-alert-exclamation-diamond.svg-B3xHmrw0.js} +1 -1
  106. package/web/assets/{interface-alert-exclamation-triangle-warning.svg-Ddp3S5kR.js → interface-alert-exclamation-triangle-warning.svg-BYsDqmTI.js} +1 -1
  107. package/web/assets/{interface-alert-information-circle.svg-CXZRx_eH.js → interface-alert-information-circle.svg-CC4CgbBo.js} +1 -1
  108. package/web/assets/{interface-award-crown.svg-BLjchqiv.js → interface-award-crown.svg-B08Pbh8m.js} +1 -1
  109. package/web/assets/{interface-bookmark.svg-BZXXPgVb.js → interface-bookmark-tag.svg-BcxMXdHY.js} +1 -1
  110. package/web/assets/{interface-bookmark-tag.svg-DykA4zk6.js → interface-bookmark.svg-CS29ZpkA.js} +1 -1
  111. package/web/assets/{interface-calendar-date-one.svg-DY5zquNe.js → interface-calendar-date-one.svg-QnK7dekM.js} +1 -1
  112. package/web/assets/{interface-content-book-open-pages.svg-BkhdueSK.js → interface-content-book-open-pages.svg-C4tNKeZR.js} +1 -1
  113. package/web/assets/{interface-content-book-page.svg-Do2xq5cr.js → interface-content-book-page.svg-6Rp1a1dk.js} +1 -1
  114. package/web/assets/{interface-content-file.svg-D-T9Y5v-.js → interface-content-file.svg-llFUOjLX.js} +1 -1
  115. package/web/assets/interface-content-folder.svg-D9afgGr0.js +1 -0
  116. package/web/assets/{interface-content-folder.svg-C7Xt4Hhi.js → interface-content-folder.svg-OI_omwbE.js} +1 -1
  117. package/web/assets/{interface-copy-clipboard.svg-CNChmFeI.js → interface-copy-clipboard.svg-Cz3_mRtM.js} +1 -1
  118. package/web/assets/{interface-edit-attachment.svg-BPFnKeJn.js → interface-edit-attachment.svg-DXOfVMyI.js} +1 -1
  119. package/web/assets/{interface-edit-binocular.svg-B15WWlwm.js → interface-edit-binocular.svg-Bx3DHzuZ.js} +1 -1
  120. package/web/assets/{interface-edit-magic-wand.svg-BOlpxpIl.js → interface-edit-magic-wand.svg-CAfIYJHR.js} +1 -1
  121. package/web/assets/{interface-edit-tool-paint-roller.svg-BAYfPrFg.js → interface-edit-tool-paint-roller.svg-FMiiT6dK.js} +1 -1
  122. package/web/assets/{interface-edit-tool-pencil.svg-BM5bmeTs.js → interface-edit-tool-pencil.svg-DbkLSbF0.js} +1 -1
  123. package/web/assets/{interface-favorite-award.svg-C2y2AP20.js → interface-favorite-award.svg-hIvxW1cg.js} +1 -1
  124. package/web/assets/{interface-favorite-flag.svg-XykDhXhn.js → interface-favorite-flag.svg-CXlWtfuy.js} +1 -1
  125. package/web/assets/{interface-favorite-heart.svg-CZPb5io9.js → interface-favorite-heart.svg-BzYW_bf1.js} +1 -1
  126. package/web/assets/{interface-favorite-star.svg-DpNTOpjf.js → interface-favorite-star.svg-C-Um6PkR.js} +1 -1
  127. package/web/assets/{interface-favorite-stars-sparkles.svg-7cCHSGs4.js → interface-favorite-stars-sparkles.svg-DO6EAdIZ.js} +1 -1
  128. package/web/assets/{interface-hierarchy-flowchart.svg-BjDJwof2.js → interface-hierarchy-flowchart.svg-CT5ujWQr.js} +1 -1
  129. package/web/assets/{interface-home-house.svg-PIM3QWnr.js → interface-home-house.svg-Inv2Er4f.js} +1 -1
  130. package/web/assets/{interface-hyperlink.svg-DGiT9LRd.js → interface-hyperlink.svg-6GygCg4m.js} +1 -1
  131. package/web/assets/{interface-lighting-brightness.svg-MFs_QAAQ.js → interface-lighting-brightness.svg-DWnle7Gq.js} +1 -1
  132. package/web/assets/{interface-lock-closed.svg-CjFqOV9n.js → interface-lock-closed.svg-D-wTtQo2.js} +1 -1
  133. package/web/assets/{interface-lock-open-unlock.svg-DTgPXrba.js → interface-lock-open-unlock.svg-B_c9nJ0x.js} +1 -1
  134. package/web/assets/{interface-login-key.svg-8cDLtR8c.js → interface-login-key.svg-UCNam9v0.js} +1 -1
  135. package/web/assets/{interface-search.svg-SJaqfmP-.js → interface-search.svg-BCkx6NFS.js} +1 -1
  136. package/web/assets/{interface-setting-cog.svg-CYAoV6-k.js → interface-setting-cog.svg-B72XaLKk.js} +1 -1
  137. package/web/assets/{interface-share-megaphone-bullhorn.svg-C6C8KuHc.js → interface-share-megaphone-bullhorn.svg-M_vr4ET6.js} +1 -1
  138. package/web/assets/{interface-share-rocket.svg-BgqOKppb.js → interface-share-rocket.svg-c3ZAv4Fq.js} +1 -1
  139. package/web/assets/{interface-share-satellite.svg-BhfjDwyA.js → interface-share-satellite.svg-C-cwO4ZJ.js} +1 -1
  140. package/web/assets/{interface-share-space-ship.svg-BUapB87z.js → interface-share-space-ship.svg-7YTjWYKO.js} +1 -1
  141. package/web/assets/{interface-share.svg-CwPC5e-3.js → interface-share.svg-DJwukuDM.js} +1 -1
  142. package/web/assets/{interface-signal-square.svg-BvC7799s.js → interface-signal-square.svg-BpoFub4k.js} +1 -1
  143. package/web/assets/{interface-time-clock-circle.svg-DYKRANoG.js → interface-time-clock-circle.svg-xsV2D_qB.js} +1 -1
  144. package/web/assets/{interface-time-hour-glass.svg-AYkRiFe-.js → interface-time-hour-glass.svg-4ENYolRr.js} +1 -1
  145. package/web/assets/{interface-users-multiple.svg-BXFBhgsj.js → interface-users-multiple.svg-eev_D0ig.js} +1 -1
  146. package/web/assets/{interface-weather-moon.svg-ZozvgB_v.js → interface-weather-moon.svg-CrLYHTyu.js} +1 -1
  147. package/web/assets/{javascript-CTdiuLav.js → javascript-DU1DQexv.js} +1 -1
  148. package/web/assets/{jsonMode-CLF3YN6s.js → jsonMode-CB8B-oHc.js} +1 -1
  149. package/web/assets/{liquid-CUugxlF_.js → liquid-Dumxg7oa.js} +1 -1
  150. package/web/assets/{lspLanguageFeatures-yWNYHr_2.js → lspLanguageFeatures-DQTWe8ey.js} +1 -1
  151. package/web/assets/{mail-chat-bubble-square.svg-BG2z_u4M.js → mail-chat-bubble-square.svg-DMcOjB2m.js} +1 -1
  152. package/web/assets/{mail-send-email-paper-airplane.svg-CUQDu7ep.js → mail-send-email-paper-airplane.svg-CKpmx979.js} +1 -1
  153. package/web/assets/{mail-send-envelope.svg-pk8Xd68w.js → mail-send-envelope.svg-C-WAmEPg.js} +1 -1
  154. package/web/assets/{mdx-BE-R90za.js → mdx-DNzXmMw3.js} +1 -1
  155. package/web/assets/{minus-DXcyjEvM.js → minus-CmvRtEQe.js} +1 -1
  156. package/web/assets/{modal-DEXm8R-m.js → modal-C0O2XBPJ.js} +1 -1
  157. package/web/assets/modal-DRUfpIPe.js +1 -0
  158. package/web/assets/{money-cashier-receipt.svg-CN9CzrqX.js → money-cashier-receipt.svg-DeL4SF6F.js} +1 -1
  159. package/web/assets/{money-currency-dollar-pay.svg-BUjSCFrb.js → money-currency-dollar-pay.svg-DCIbDsIr.js} +1 -1
  160. package/web/assets/{money-graph-arrow-increase.svg-B_90Bmbk.js → money-graph-arrow-increase.svg-NDD5MY4C.js} +1 -1
  161. package/web/assets/{money-graph-bar-chart-increase.svg-DEHprvsR.js → money-graph-bar-chart-increase.svg-CqFZrAkq.js} +1 -1
  162. package/web/assets/{multiselect-DHN-4dF5.js → multiselect-C3dGhKnP.js} +1 -1
  163. package/web/assets/{nature-ecology-leaf.svg-VzV83bka.js → nature-ecology-leaf.svg-C74TcBty.js} +1 -1
  164. package/web/assets/{password-Cn-GHrdR.js → password-Cf8j-GkJ.js} +1 -1
  165. package/web/assets/{phone-telephone.svg-B7K0iTF5.js → phone-telephone.svg-BeNULj1e.js} +1 -1
  166. package/web/assets/{plus-BavJPboa.js → plus-hUxz8lH_.js} +1 -1
  167. package/web/assets/process.store-TQsoI7AA.js +1 -0
  168. package/web/assets/{programming-bug.svg-BQArvDEk.js → programming-bug.svg-DSydJcD0.js} +1 -1
  169. package/web/assets/{programming-cloud.svg-Diup3d6q.js → programming-cloud.svg-2xUngU0S.js} +1 -1
  170. package/web/assets/{programming-computer-database-server.svg-Cry9WzIl.js → programming-computer-database-server.svg-TAX5z1tR.js} +1 -1
  171. package/web/assets/{programming-computer-database.svg-B2DIP4pU.js → programming-computer-database.svg-mO5bElVh.js} +1 -1
  172. package/web/assets/{programming-module-four-layout.svg-BGnmF15h.js → programming-module-four-layout.svg-Dr767G1Z.js} +1 -1
  173. package/web/assets/{programming-module-three.svg-Dlx8NKbv.js → programming-module-three.svg-D4oVsZl_.js} +1 -1
  174. package/web/assets/{programming-module.svg-1TSwsWTr.js → programming-module.svg-wdwopIvm.js} +1 -1
  175. package/web/assets/{programming-script-code.svg-DpNHCOrR.js → programming-script-code.svg-DBPWoki2.js} +1 -1
  176. package/web/assets/project-launch.store-CZsTY83m.js +1 -0
  177. package/web/assets/project.store-eIP8RM3Q.js +1 -0
  178. package/web/assets/{python-BfgnQ0Q-.js → python-BE5DaTS2.js} +1 -1
  179. package/web/assets/{radiobutton-1vkC7CQy.js → radiobutton-CImlBTBP.js} +1 -1
  180. package/web/assets/{razor-a5t1Ro53.js → razor-Cmx-7XPV.js} +1 -1
  181. package/web/assets/router-CVSY8aIb.js +1 -0
  182. package/web/assets/{selectbutton-DSr_ExzW.js → selectbutton-BhpYZyFl.js} +1 -1
  183. package/web/assets/settings-scope-CxYQcvAR.js +1 -0
  184. package/web/assets/{settings.store-BBQfvtZb.js → settings.store-DridR-ck.js} +1 -1
  185. package/web/assets/{shopping-cart.svg-16zfxHII.js → shopping-cart.svg-C3En9-vl.js} +1 -1
  186. package/web/assets/{shopping-gift-present.svg-DEDgwlxd.js → shopping-gift-present.svg-7p-hRdPX.js} +1 -1
  187. package/web/assets/{shopping-shipping-box-parcel-package.svg-CBOsBi-s.js → shopping-shipping-box-parcel-package.svg-BWbZhI8w.js} +1 -1
  188. package/web/assets/src-BM_sDDlr.css +1 -0
  189. package/web/assets/{src-wb0MqCTT.js → src-DTiDFW3B.js} +32 -32
  190. package/web/assets/{src-B_TK9M1Z.js → src-isLSni-N.js} +1 -1
  191. package/web/assets/{tabpanel-CqAq0gJE.js → tabpanel-Bfol4XTd.js} +1 -1
  192. package/web/assets/{tag-new-circle.svg-DN5XPkdR.js → tag-new-circle.svg-Spe566L2.js} +1 -1
  193. package/web/assets/theme-4th617B_.js +1 -0
  194. package/web/assets/{toggleswitch-Cr9zROI7.js → toggleswitch-CZCAv-jp.js} +1 -1
  195. package/web/assets/{travel-map-earth-globe.svg-CN8908SS.js → travel-map-earth-globe.svg-DKz5j-UT.js} +1 -1
  196. package/web/assets/trpc-CBXwYAMy.js +1 -0
  197. package/web/assets/{tsMode-D8tqTb6Z.js → tsMode-AQ4klRHU.js} +1 -1
  198. package/web/assets/{typescript-C2tUdKLU.js → typescript-yluvE--_.js} +1 -1
  199. package/web/assets/useAiChatDrawer-D_AzdjrA.js +1 -0
  200. package/web/assets/{useCloudOrg-C1-UCQOV.js → useCloudOrg-b-QnhnSc.js} +1 -1
  201. package/web/assets/{useEnvVarAutocomplete-5sTKensF.js → useEnvVarAutocomplete-Bj9GeijO.js} +1 -1
  202. package/web/assets/{useProjectCatalog-Dj4rYNAZ.js → useProjectCatalog-BGdTjXzH.js} +1 -1
  203. package/web/assets/{useProjectCloudOrg-B1KHG4Co.js → useProjectCloudOrg-DQJMaDXR.js} +1 -1
  204. package/web/assets/{useServiceUrlHost-CDiftJ5-.js → useServiceUrlHost-BezQuX2r.js} +1 -1
  205. package/web/assets/{xml-09bhQ5hy.js → xml-BEYNsHpr.js} +1 -1
  206. package/web/assets/{yaml-DE2l2UeT.js → yaml-CdJTW_Jy.js} +1 -1
  207. package/web/index.html +1 -1
  208. package/chunk-RLLUJCPQ.js.map +0 -1
  209. package/chunk-WN36W5OW.js.map +0 -1
  210. package/src-FS7Y4DA7.js.map +0 -1
  211. package/web/assets/AiChatPage-DWAuKlmg.js +0 -1
  212. package/web/assets/CloudAccountPage-Cxo7nX-K.js +0 -1
  213. package/web/assets/KanbanBoardPage-BmJwTFE8.css +0 -1
  214. package/web/assets/WikiPage-DzFvtMxw.js +0 -1
  215. package/web/assets/cloud-client-D01e8Pib.js +0 -1
  216. package/web/assets/cloud-session-DHJ2Dn0_.js +0 -1
  217. package/web/assets/interface-content-folder.svg-D8Pl9Ud7.js +0 -1
  218. package/web/assets/modal-DDtmE9ls.js +0 -1
  219. package/web/assets/process.store-BHtXNXJN.js +0 -1
  220. package/web/assets/project-launch.store-MjBfxlB3.js +0 -1
  221. package/web/assets/project.store-4LkhN_Kf.js +0 -1
  222. package/web/assets/router-D2CFZuT6.js +0 -1
  223. package/web/assets/settings-scope-Bfve93ym.js +0 -1
  224. package/web/assets/src-DXLPQX5t.css +0 -1
  225. package/web/assets/theme-BRinmkRN.js +0 -1
  226. package/web/assets/trpc-CGXr2as5.js +0 -1
  227. package/web/assets/useAiChatDrawer-1cmqYfrd.js +0 -1
  228. /package/{settings-manager-3G5RHW3X.js.map → agent-manager-TUFAFC6U.js.map} +0 -0
  229. /package/{companion-IYK2652T.js.map → chat-37VHPDPJ.js.map} +0 -0
  230. /package/{chunk-3HGTIUGB.js.map → chunk-7JAJSV4L.js.map} +0 -0
  231. /package/{chunk-24UJRQRM.js.map → chunk-I7JHF5FE.js.map} +0 -0
  232. /package/{chunk-PVLDFBL6.js.map → chunk-TG44C7QT.js.map} +0 -0
  233. /package/{chat-ICUWJZEX.js.map → companion-27RCQRZV.js.map} +0 -0
  234. /package/{desktop-launcher-GHCALSOS.js.map → desktop-launcher-3COY6F6H.js.map} +0 -0
  235. /package/{agent-manager-J75NZ6MN.js.map → settings-manager-J4QBIU3T.js.map} +0 -0
@@ -23,7 +23,7 @@ import {
23
23
  serviceStore,
24
24
  setProjectServices,
25
25
  setProjectVault
26
- } from "./chunk-3HGTIUGB.js";
26
+ } from "./chunk-7JAJSV4L.js";
27
27
  import {
28
28
  atomicWriteSecure,
29
29
  fingerprintFiles,
@@ -36,7 +36,7 @@ import {
36
36
  COMPANION_RELAY_OPEN,
37
37
  ProjectSchema,
38
38
  extractCompanionRelay
39
- } from "./chunk-WN36W5OW.js";
39
+ } from "./chunk-5EMEJNVU.js";
40
40
  import {
41
41
  allVaultRoots,
42
42
  ensureLocalVault,
@@ -2037,7 +2037,7 @@ async function runCompanionForTurn(conversationId) {
2037
2037
  if (!hasNew) {
2038
2038
  return skip(conversationId, "nothingNew", `rien de neuf \xE0 relire (${messageCount} messages)`);
2039
2039
  }
2040
- const { startCliSession } = await import("./chat-ICUWJZEX.js");
2040
+ const { startCliSession } = await import("./chat-37VHPDPJ.js");
2041
2041
  const companionConv = await ensureCompanionConversation(conv);
2042
2042
  const isFirstTurn = (companionConv.messages?.length ?? 0) === 0;
2043
2043
  const exchange = formatExchange(conv.messages, from);
@@ -2152,7 +2152,7 @@ async function deliverToMainConversation(conv, message) {
2152
2152
  async function attemptDelivery(conv, message) {
2153
2153
  if (await writeToLivePty(conv.id, message)) return "pty";
2154
2154
  try {
2155
- const { startCliSession } = await import("./chat-ICUWJZEX.js");
2155
+ const { startCliSession } = await import("./chat-37VHPDPJ.js");
2156
2156
  await startCliSession(conv.runner, conv.id, message, { jwt: await signJwt() });
2157
2157
  return "headless";
2158
2158
  } catch (err) {
@@ -2175,7 +2175,7 @@ async function writeToLivePty(conversationId, message) {
2175
2175
  }
2176
2176
  async function companionSettings() {
2177
2177
  try {
2178
- const { settingsManager } = await import("./settings-manager-3G5RHW3X.js");
2178
+ const { settingsManager } = await import("./settings-manager-J4QBIU3T.js");
2179
2179
  const settings = await settingsManager.getSettings();
2180
2180
  return settings.companion ?? { enabledByDefault: false };
2181
2181
  } catch {
@@ -2317,4 +2317,4 @@ export {
2317
2317
  runCompanionNow,
2318
2318
  initCompanion
2319
2319
  };
2320
- //# sourceMappingURL=chunk-PVLDFBL6.js.map
2320
+ //# sourceMappingURL=chunk-TG44C7QT.js.map
@@ -27,11 +27,11 @@ import {
27
27
  reviewWindow,
28
28
  runCompanionNow,
29
29
  takeRelaunchSlot
30
- } from "./chunk-PVLDFBL6.js";
30
+ } from "./chunk-TG44C7QT.js";
31
31
  import "./chunk-MD3VW4HQ.js";
32
- import "./chunk-3HGTIUGB.js";
32
+ import "./chunk-7JAJSV4L.js";
33
33
  import "./chunk-BDQOBEZ3.js";
34
- import "./chunk-WN36W5OW.js";
34
+ import "./chunk-5EMEJNVU.js";
35
35
  import "./chunk-ZFELQG4B.js";
36
36
  import "./chunk-4RMM2OUU.js";
37
37
  export {
@@ -64,4 +64,4 @@ export {
64
64
  runCompanionNow,
65
65
  takeRelaunchSlot
66
66
  };
67
- //# sourceMappingURL=companion-IYK2652T.js.map
67
+ //# sourceMappingURL=companion-27RCQRZV.js.map
@@ -2,7 +2,7 @@ import {
2
2
  deriveLauncherIdentity,
3
3
  launcherIdFromName,
4
4
  slugifyLauncherName
5
- } from "./chunk-WN36W5OW.js";
5
+ } from "./chunk-5EMEJNVU.js";
6
6
 
7
7
  // src/desktop-launcher.ts
8
8
  import { mkdir, writeFile, rm, copyFile, access } from "fs/promises";
@@ -278,4 +278,4 @@ export {
278
278
  vbsQuote,
279
279
  windowsVbsScript
280
280
  };
281
- //# sourceMappingURL=desktop-launcher-GHCALSOS.js.map
281
+ //# sourceMappingURL=desktop-launcher-3COY6F6H.js.map
package/index.js CHANGED
@@ -84,7 +84,7 @@ for (const { flag, env: key } of ENV_FLAGS) {
84
84
  if (args.includes("--debug")) process.env["RUNEYA_DEBUG"] = "1";
85
85
  var subCommand = args[0];
86
86
  if (subCommand === "install-desktop" || subCommand === "uninstall-desktop") {
87
- const { installDesktopLauncher, uninstallDesktopLauncher, deriveIdentity } = await import("./desktop-launcher-GHCALSOS.js");
87
+ const { installDesktopLauncher, uninstallDesktopLauncher, deriveIdentity } = await import("./desktop-launcher-3COY6F6H.js");
88
88
  const { shouldRunWizard, runInstallWizard, printInstallReport, printUninstallReport } = await import("./desktop-wizard-4CYANX2O.js");
89
89
  const { parsePort } = await import("./free-port-565NMFIZ.js");
90
90
  const rest = args.slice(1);
@@ -135,7 +135,7 @@ if (subCommand === "install-desktop" || subCommand === "uninstall-desktop") {
135
135
  }
136
136
  }
137
137
  if (subCommand === "instances") {
138
- const { listInstances, killInstance, restartInstance } = await import("./src-FS7Y4DA7.js");
138
+ const { listInstances, killInstance, restartInstance } = await import("./src-PSJSIJN6.js");
139
139
  const { runInstancesCommand } = await import("./instances-command-KZ5UGXOR.js");
140
140
  process.exit(await runInstancesCommand(args.slice(1), {
141
141
  listInstances,
@@ -298,8 +298,16 @@ async function main() {
298
298
  const { ensureNodeBinOnPath, ensureUserBinsOnPath, stampConsole } = await import("./node-JU7A5NDT.js");
299
299
  ensureNodeBinOnPath();
300
300
  await ensureUserBinsOnPath();
301
- if (!isPullEnv) stampConsole();
302
- const { createLocalServer, pullEnv, PullEnvError, registerInstance, registerCliLocation } = await import("./src-FS7Y4DA7.js");
301
+ if (!isPullEnv) {
302
+ stampConsole();
303
+ try {
304
+ const { installLogFile } = await import("./log-file-XAEHICMH.js");
305
+ console.log(`[cli] Journal : ${installLogFile().logPath}`);
306
+ } catch (err) {
307
+ console.warn(`[cli] Journal sur disque indisponible : ${err.message}`);
308
+ }
309
+ }
310
+ const { createLocalServer, pullEnv, PullEnvError, registerInstance, registerCliLocation } = await import("./src-PSJSIJN6.js");
303
311
  registerCliLocation({ execPath: process.execPath, cliEntry: fileURLToPath(import.meta.url) });
304
312
  if (isPullEnv) {
305
313
  if (!serviceArg) {
@@ -408,7 +416,7 @@ async function main() {
408
416
  networkInfo,
409
417
  setLanMode,
410
418
  resolveTrayIcon
411
- } = await import("./src-FS7Y4DA7.js");
419
+ } = await import("./src-PSJSIJN6.js");
412
420
  tray = await startInstanceTray({
413
421
  info: { cwd: process.cwd(), port, version, url: appUrl },
414
422
  assetsDir: join(__dirname, "assets"),
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/port-resolution.ts"],"sourcesContent":["#!/usr/bin/env node\nimport type { Server } from 'node:http';\nimport type { WebSocketServer } from 'ws';\nimport type { Request, Response } from 'express';\nimport { fileURLToPath, URL as NodeURL } from 'node:url';\nimport { dirname, join, resolve } from 'node:path';\nimport { readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport express from 'express';\nimport dotenv from 'dotenv'\nimport open from 'open';\nimport { resolvePort } from './port-resolution.js';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nconst { version } = JSON.parse(\n readFileSync(new NodeURL('./package.json', import.meta.url), 'utf8'),\n) as { version: string };\n\nfunction printStartupTable(port: number, appUrl: string): void {\n const rows: [string, string][] = [\n ['Version', version],\n ['Port', String(port)],\n ['Url', appUrl],\n ];\n\n const col0 = Math.max(...rows.map(([k]) => k.length));\n const col1 = Math.max(...rows.map(([, v]) => v.length));\n\n const pad = (s: string, n: number) => s.padEnd(n);\n const hr = (l: string, m: string, r: string, f: string) =>\n l + f.repeat(col0 + 2) + m + f.repeat(col1 + 2) + r;\n\n console.log('');\n console.log(hr('┌', '┬', '┐', '─'));\n for (const [key, value] of rows) {\n console.log(`│ ${pad(key, col0)} │ ${pad(value, col1)} │`);\n }\n console.log(hr('└', '┴', '┘', '─'));\n console.log('');\n}\n\n// Parse CLI flags\nconst args = process.argv.slice(2);\n\n/**\n * Set by the desktop launcher. It means nobody is watching a terminal, so a\n * startup failure has to be reported through a window of its own.\n */\nconst isFromDesktop = args.includes('--from-desktop');\n\n// Capture must start before anything logs, hence this early import.\nconst startupFailure = isFromDesktop ? await import('./startup-failure.js') : null;\nstartupFailure?.captureOutput();\n\nfunction getFlagValue(flags: string[]): string | undefined {\n for (const flag of flags) {\n const idx = args.indexOf(flag);\n if (idx !== -1 && idx + 1 < args.length) return args[idx + 1];\n }\n return undefined;\n}\n\n/**\n * Flags that mirror a RUNEYA_* environment variable. The flag always wins over\n * the variable, and both are equivalent otherwise.\n *\n * Secrets (RUNEYA_ENCRYPTION_KEY, RUNEYA_MASTER_PASSWORD) deliberately have no\n * flag: process arguments are world-readable through `ps` on most systems.\n */\nconst ENV_FLAGS: { flag: string; env: string }[] = [\n { flag: '--host', env: 'RUNEYA_HOST' },\n { flag: '--agent-port', env: 'RUNEYA_AGENT_PORT' },\n { flag: '--agent-host', env: 'RUNEYA_AGENT_HOST' },\n { flag: '--agent-binary-path', env: 'RUNEYA_AGENT_BINARY_PATH' },\n { flag: '--data-dir', env: 'RUNEYA_DATA_DIR' },\n { flag: '--mode', env: 'RUNEYA_MODE' },\n { flag: '--cloud-url', env: 'RUNEYA_CLOUD_URL' },\n { flag: '--cloud-app-url', env: 'RUNEYA_CLOUD_APP_URL' },\n { flag: '--cors-origin', env: 'RUNEYA_CORS_ORIGIN' },\n { flag: '--claude-pty', env: 'RUNEYA_CLAUDE_PTY' },\n];\n\n// Flags taking a value — needed so their value is not mistaken for the target directory\nconst flagsWithValues = new Set([\n '--port',\n '--name',\n '-e', '--environment',\n '-s', '--service',\n ...ENV_FLAGS.map((f) => f.flag),\n]);\n\n// Apply value flags to their env var (flag wins over an already-set variable).\n// Done before dotenv so a .env file can never override an explicit flag.\nfor (const { flag, env: key } of ENV_FLAGS) {\n const value = getFlagValue([flag]);\n if (value !== undefined) process.env[key] = value;\n}\n// --debug is a boolean shortcut for RUNEYA_DEBUG=1\nif (args.includes('--debug')) process.env['RUNEYA_DEBUG'] = '1';\n\n/**\n * `install-desktop` / `uninstall-desktop` — handled before anything else so the\n * sub-command name is never mistaken for a target directory, and so the current\n * working directory is still the user's when we capture it.\n *\n * Bare on a TTY it opens a wizard; any flag that pre-answers a question skips\n * straight to the action so scripts stay unattended.\n */\nconst subCommand = args[0];\nif (subCommand === 'install-desktop' || subCommand === 'uninstall-desktop') {\n const { installDesktopLauncher, uninstallDesktopLauncher, deriveIdentity } =\n await import('./desktop-launcher.js');\n const { shouldRunWizard, runInstallWizard, printInstallReport, printUninstallReport } =\n await import('./desktop-wizard.js');\n\n const { parsePort } = await import('./free-port.js');\n\n const rest = args.slice(1);\n // Every flag of this sub-command that takes a value: without this, the value\n // itself (a port number, a name) is mistaken for the target directory.\n const subFlagsWithValues = new Set(['--name', '--port', '--agent-port']);\n const positional = rest.find((a, i) => !a.startsWith('-') && !subFlagsWithValues.has(rest[i - 1] ?? ''));\n const nameFlag = getFlagValue(['--name']);\n\n // Ports baked into the shortcut. Null means \"follow Runeya's default\", so a\n // launcher created without them keeps tracking the default if it changes.\n const portFlagRaw = getFlagValue(['--port']);\n const agentPortFlagRaw = getFlagValue(['--agent-port']);\n for (const [flag, raw] of [['--port', portFlagRaw], ['--agent-port', agentPortFlagRaw]] as const) {\n if (raw !== undefined && parsePort(raw) === null) {\n console.error(`Erreur : ${flag} attend un entier entre 1 et 65535 (reçu ${JSON.stringify(raw)}).`);\n process.exit(1);\n }\n }\n let port = parsePort(portFlagRaw);\n let agentPort = parsePort(agentPortFlagRaw);\n\n // The data directory is resolved from the working directory, so a launcher\n // that does not pin one would start Runeya in the desktop's cwd (usually the\n // home directory) and create a stray .runeya there. Pin the cwd by default.\n let workingDir = rest.includes('--no-cwd') ? null : resolve(positional ?? process.cwd());\n let displayName = nameFlag;\n\n if (subCommand === 'install-desktop' && shouldRunWizard(rest, positional !== undefined)) {\n const answers = await runInstallWizard(process.cwd());\n if (!answers) process.exit(130); // aborted with Ctrl+C\n workingDir = answers.workingDir;\n displayName = answers.name;\n port = answers.port;\n agentPort = answers.agentPort;\n }\n\n const { name, id } = deriveIdentity(displayName, workingDir);\n\n try {\n if (subCommand === 'install-desktop') {\n const result = await installDesktopLauncher({\n nodePath: process.execPath,\n cliEntry: fileURLToPath(import.meta.url),\n distDir: __dirname,\n workingDir,\n name,\n id,\n port,\n agentPort,\n });\n printInstallReport({ name, workingDir, nodePath: process.execPath, port, agentPort, result });\n } else {\n printUninstallReport(name, await uninstallDesktopLauncher(name, id));\n }\n process.exit(0);\n } catch (err) {\n console.error(`Erreur : ${(err as Error).message}`);\n process.exit(1);\n }\n}\n\n/**\n * `runeya instances` — voir et piloter les Runeya de cette machine depuis un\n * terminal. Traité ici, avec les autres sous-commandes, pour que le mot\n * « instances » ne soit jamais pris pour un répertoire cible.\n *\n * Le pendant de l'icône de barre système, qui ne montre qu'une instance — la\n * sienne — et n'existe pas partout. Celle-ci les montre toutes, partout.\n *\n * Aucun serveur n'est démarré : le registre machine est un dossier de fichiers,\n * et le lire ne demande rien d'autre que de le lire.\n */\nif (subCommand === 'instances') {\n // Importé ici et pas en tête de fichier : charger `@runeya/apps-server` a un\n // coût, et un `runeya` ordinaire n'a pas à le payer pour une sous-commande\n // qu'il n'utilise pas.\n const { listInstances, killInstance, restartInstance } = await import('@runeya/apps-server');\n const { runInstancesCommand } = await import('./instances-command.js');\n\n process.exit(await runInstancesCommand(args.slice(1), {\n listInstances,\n stopInstance: killInstance,\n restartInstance: async (pid: number) => {\n const { pid: newPid, portReleased } = await restartInstance(pid);\n return { pid: newPid, portReleased };\n },\n openUrl: (url: string) => open(url),\n log: (message: string) => console.log(message),\n warn: (message: string) => console.error(message),\n }));\n}\n\n// Resolve target directory (first positional arg, skipping flag values)\nconst targetDir = args.find((a, i) => !a.startsWith('-') && !flagsWithValues.has(args[i - 1] ?? ''));\nif (targetDir) {\n const resolved = resolve(targetDir);\n process.chdir(resolved);\n console.log(`[cli] Working directory: ${resolved}`);\n} else if (process.env['RUNEYA_DATA_DIR']) {\n const resolved = resolve(process.env['RUNEYA_DATA_DIR'], '..');\n process.chdir(resolved);\n console.log(`[cli] Working directory: ${resolved} (from RUNEYA_DATA_DIR)`);\n} else if (process.cwd() === '/') {\n /**\n * On n'écrit jamais à la racine.\n *\n * Un lanceur global — installé sans dossier épinglé — démarre avec le cwd que\n * lui donne le système, et le Finder comme les services systemd donnent `/`.\n * `DATA_DIR` y vaudrait `/.runeya` : sous macOS la racine est le volume\n * système signé, monté en lecture seule, et la première écriture locale\n * échouerait en EROFS — que même root ne peut pas lever sans\n * `/etc/synthetic.conf` et un redémarrage. Sous Linux elle demanderait les\n * droits du superutilisateur pour un dossier qui n'a rien à faire là.\n *\n * Le repli vaut aussi pour les lanceurs DÉJÀ installés, que corriger le stub\n * ne rattraperait pas.\n */\n const home = homedir();\n process.chdir(home);\n console.log(`[cli] Working directory: ${home} (lanceur sans dossier épinglé)`);\n}\n\ndotenv.config({ quiet: true });\n\nif (args.includes('--help') || args.includes('-h')) {\n console.log(`Usage: runeya [path-to-your-stack] [options]\n\nCommands:\n install-desktop [path] Create a desktop/menu launcher for this machine\n Bare on a terminal, this opens a short wizard.\n uninstall-desktop Remove a launcher created by install-desktop\n --name <label> Launcher name (default: \"Runeya — <folder>\")\n --no-cwd Global launcher — do not pin a working directory\n --port <n> Port baked into the launcher (default: Runeya's own)\n --agent-port <n> Agent port baked in (default: launcher port + 1)\n -y, --yes Skip the wizard and take the defaults\n instances [open|stop|restart <pid>]\n List the Runeya running on this machine, and act on\n one. --json for the raw records.\n --from-desktop Set by desktop launchers: report startup failures\n in a browser window instead of a silent exit\n\nOptions:\n --version Show version number\n --pe, --pull-env Print env vars for a service to stdout (requires -e and -s)\n -e, --environment <n> Environment name or id\n -s, --service <name> Service name or id\n --lan Expose server on the local network (shortcut for --host 0.0.0.0)\n --no-open Do not open browser on startup\n --no-tray Do not put this instance in the system tray\n --agent Run as agent only (no server, no UI) — for remote machines\n -h, --help Show this help message\n\nConfiguration:\n Each setting has a flag and an equivalent RUNEYA_ environment variable; the\n flag wins. Variables are prefixed so they cannot collide with those of the\n services you manage. A .env file in the working directory is loaded\n automatically, but never overrides a flag.\n\n Flag Environment variable Default\n --port <n> RUNEYA_HTTP_PORT 4000\n (binds the agent instead when --agent is used)\n --host <address> RUNEYA_HOST 127.0.0.1\n --agent-port <n> RUNEYA_AGENT_PORT server port + 1\n --agent-host <address> RUNEYA_AGENT_HOST 127.0.0.1\n --agent-binary-path <path> RUNEYA_AGENT_BINARY_PATH bundled with the CLI\n --data-dir <path> RUNEYA_DATA_DIR <cwd>/.runeya\n --mode <mode> RUNEYA_MODE local-simple\n 'local-simple' | 'cloud'\n --cloud-url <url> RUNEYA_CLOUD_URL —\n --cloud-app-url <url> RUNEYA_CLOUD_APP_URL —\n --cors-origin <origin> RUNEYA_CORS_ORIGIN —\n --lan RUNEYA_LAN_PROXY false\n --debug RUNEYA_DEBUG false\n --claude-pty <0|1> RUNEYA_CLAUDE_PTY 1\n PTY mode for the Claude Code runner\n\n Secrets have no flag — process arguments are readable by other users via 'ps':\n RUNEYA_ENCRYPTION_KEY 64-char hex key for CI/CD — unlocks secrets without a\n master password AND disables tRPC authentication.\n Never set this on a machine reachable by others.\n RUNEYA_MASTER_PASSWORD Master password used by --pull-env instead of prompting\n\n Standard variables Runeya also honours: NODE_ENV, CI (skips opening the browser).\n`);\n process.exit(0);\n}\n\nif (args.includes('--version')) {\n console.log(version);\n process.exit(0);\n}\n\n/**\n * L'icône de barre système, sauf `--no-tray`.\n *\n * Chaque Runeya pose la sienne au démarrage et la retire en s'arrêtant : une\n * icône par instance en cours. Là où la barre système n'existe pas (serveur\n * sans bureau, arm64, paquet optionnel absent), il n'y a rien à désactiver —\n * l'icône ne se pose pas, et Runeya démarre pareil.\n */\nconst noTray = args.includes('--no-tray');\n\nconst noOpen =\n args.includes('--no-open') ||\n !!process.env['VITEST'] ||\n !!process.env['CI'] ||\n process.env['NODE_ENV'] === 'test';\n\n// --pull-env flag — detect early so we can silence stdout before any log\nconst isPullEnv = args.includes('--pull-env') || args.includes('--pe');\n\n// In pull-env mode, redirect console.log/info to stderr so only KEY=VALUE goes to stdout\nif (isPullEnv) {\n const toStderr = (...a: unknown[]) => process.stderr.write(a.join(' ') + '\\n');\n console.log = toStderr;\n console.info = toStderr;\n}\n\nconst serviceArg = getFlagValue(['-s', '--service']);\nconst environmentArg = getFlagValue(['-e', '--environment']);\n\n// Configure environment BEFORE importing server (env is parsed at module load)\n// --agent mode: run as standalone agent only (no server, no UI)\nconst isAgentOnly = args.includes('--agent');\n\n// --port targets the server, except in agent mode where it binds the agent\nconst portFlag = getFlagValue(['--port']);\nif (portFlag) {\n process.env[isAgentOnly ? 'RUNEYA_AGENT_PORT' : 'RUNEYA_HTTP_PORT'] = portFlag;\n}\n\n// --lan binds to 0.0.0.0. As an explicit flag it outranks RUNEYA_HOST; coming\n// from RUNEYA_LAN_PROXY it only fills in a host nobody else set.\nconst hostFlag = getFlagValue(['--host']);\nconst isLan = args.includes('--lan');\nconst isLanProxy = isLan || process.env.RUNEYA_LAN_PROXY === 'true' || process.env.RUNEYA_LAN_PROXY === '1';\nif (isLanProxy) {\n process.env.RUNEYA_LAN_PROXY = 'true';\n if (!hostFlag && isLan) process.env.RUNEYA_HOST = '0.0.0.0';\n else process.env.RUNEYA_HOST ??= '0.0.0.0';\n}\n\n// In agent mode --host binds the agent rather than the server\nif (isAgentOnly) {\n if (hostFlag) {\n process.env.RUNEYA_AGENT_HOST = hostFlag;\n } else if (isLan) {\n process.env.RUNEYA_AGENT_HOST = '0.0.0.0';\n } else if (isLanProxy) {\n process.env.RUNEYA_AGENT_HOST ??= '0.0.0.0';\n }\n}\n\n// Agent binary shipped inside the CLI dist — overridable via --agent-binary-path\nprocess.env.RUNEYA_AGENT_BINARY_PATH ??= join(__dirname, 'agent/index.js');\n// Expose CLI version to server\nprocess.env.RUNEYA_VERSION = version;\n// Tell the server it was launched from a shortcut, so the UI can say so\nif (isFromDesktop) process.env.RUNEYA_FROM_DESKTOP = '1';\n// Data directory defaults to CWD/.runeya (server env.ts default)\n// so Runeya data lives alongside the target project.\n\n/**\n * Listen with retry for EADDRINUSE — handles the race condition when the CLI\n * restarts the server before the old process has fully released the port.\n *\n * The `wss` parameter is needed because the `ws` library re-emits HTTP server\n * errors on the WebSocketServer — without a handler the error becomes unhandled.\n */\nfunction listenWithRetry(\n server: Server,\n port: number,\n host: string,\n wss?: WebSocketServer,\n maxRetries = 20,\n delay = 500,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n let attempts = 0;\n\n // Absorb EADDRINUSE errors re-emitted by the ws library on the WSS\n // during the retry window. Without this, Node.js crashes on unhandled error.\n const wssErrorHandler = () => { /* absorbed — handled via server 'error' */ };\n wss?.on('error', wssErrorHandler);\n\n const tryListen = () => {\n const onError = (err: NodeJS.ErrnoException) => {\n // Clean up the 'listening' callback that server.listen() registered\n server.removeAllListeners('listening');\n\n if (err.code === 'EADDRINUSE' && attempts < maxRetries) {\n attempts++;\n console.log(`[cli] Port ${port} in use, retrying in ${delay}ms (${attempts}/${maxRetries})...`);\n setTimeout(tryListen, delay);\n } else {\n wss?.removeListener('error', wssErrorHandler);\n reject(err);\n }\n };\n\n server.once('error', onError);\n server.listen(port, host, () => {\n server.removeListener('error', onError);\n wss?.removeListener('error', wssErrorHandler);\n resolve();\n });\n };\n\n tryListen();\n });\n}\n\nasync function main() {\n // Avant tout : ce que ce process hérite ici, le serveur, l'agent local et\n // chaque service lancé ensuite en héritent à leur tour. Un raccourci de bureau\n // reçoit le PATH de la session graphique, où ni les gestionnaires de version\n // ni les binaires installés par l'utilisateur (claude, codex) ne figurent.\n const { ensureNodeBinOnPath, ensureUserBinsOnPath, stampConsole } = await import('@runeya/packages-shared/node');\n ensureNodeBinOnPath();\n await ensureUserBinsOnPath();\n\n // Journaux datés du temps écoulé depuis le démarrage. Jamais en --pull-env :\n // sa sortie est lue par un script, pas par un humain.\n if (!isPullEnv) stampConsole();\n\n // Dynamic import ensures env is parsed AFTER we configure it\n const { createLocalServer, pullEnv, PullEnvError, registerInstance, registerCliLocation } = await import('@runeya/apps-server');\n\n // D'où ce CLI a été lancé, pour que l'interface puisse proposer `install-desktop`\n // sans que le serveur ait à deviner un exécutable.\n registerCliLocation({ execPath: process.execPath, cliEntry: fileURLToPath(import.meta.url) });\n\n // Handle --pull-env mode: resolve env vars and print, then exit\n if (isPullEnv) {\n if (!serviceArg) {\n console.error('Error: --service (-s) is required with --pull-env');\n process.exit(1);\n }\n if (!environmentArg) {\n console.error('Error: --environment (-e) is required with --pull-env');\n process.exit(1);\n }\n try {\n const output = await pullEnv({ service: serviceArg, environment: environmentArg });\n if (output) process.stdout.write(output + '\\n');\n process.exit(0);\n } catch (err: unknown) {\n if (err instanceof PullEnvError) {\n console.error(`Error: ${err.message}`);\n process.exit(err.exitCode);\n }\n throw err;\n }\n }\n\n // --agent mode: standalone agent, no server, no UI\n if (isAgentOnly) {\n const { spawn } = await import('node:child_process');\n const agentBin = join(__dirname, 'agent/index.js');\n const child = spawn(process.execPath, [agentBin], { stdio: 'inherit', windowsHide: true });\n child.on('exit', (code) => process.exit(code ?? 0));\n // SIGINT is already delivered to the child by the terminal (same process group).\n // Intercept it here only to suppress Node's default exit so we stay alive\n // until the child finishes its graceful shutdown.\n process.on('SIGINT', () => { /* wait for child to exit */ });\n process.on('SIGTERM', () => child.kill('SIGTERM'));\n return;\n }\n\n /**\n * Un relais de redémarrage (`appUpdate.restart`) est l'exception au garde-fou\n * ci-dessous : l'instance qui répond encore sur le port est précisément celle\n * qu'on remplace. On la laisse s'éteindre, `listenWithRetry` absorbe\n * l'EADDRINUSE du chevauchement. La marque est consommée ici pour ne pas se\n * propager aux services lancés ensuite, qui héritent de cet environnement.\n */\n const isRestartHandoff = process.env.RUNEYA_RESTART_HANDOFF === '1';\n delete process.env.RUNEYA_RESTART_HANDOFF;\n\n /**\n * A shortcut clicked twice must not fail.\n *\n * Starting a second instance on a port a Runeya already holds ends in\n * EADDRINUSE after ten seconds of retries — and from a launcher there is no\n * terminal to read that in. So the port is asked first: if Runeya answers,\n * the right move is to bring up the window that already exists.\n *\n * Only for launcher starts. From a terminal, `runeya` twice on one port is a\n * mistake worth reporting, not one worth papering over.\n */\n if (isFromDesktop && !isRestartHandoff) {\n const port = resolvePort();\n const { probeRuneya } = await import('./free-port.js');\n const existing = await probeRuneya(port);\n if (existing) {\n const url = `http://localhost:${port}`;\n console.log(`[cli] Runeya v${existing.version} déjà en cours sur le port ${port} — ouverture de ${url}`);\n if (!noOpen) await open(url);\n return;\n }\n }\n\n console.log('[cli] Starting Runeya...');\n\n // Create server (automatically spawns local agent)\n const { app, server, wss, shutdown } = await createLocalServer();\n\n // Serve static files from web frontend (embedded in CLI dist during build)\n const webDistPath = join(__dirname, 'web');\n\n /**\n * Les fichiers d'`assets/` portent un hash de leur contenu dans leur nom : une\n * mise à jour produit un NOUVEAU nom, jamais un contenu différent sous le même\n * nom. Ils peuvent donc être gardés indéfiniment, et `immutable` dit au\n * navigateur de ne même pas revalider.\n *\n * Sans cela, `express.static` répond `max-age=0` : chaque rechargement\n * redemande les 295 fichiers pour s'entendre répondre 304. Ce sont des\n * requêtes vides, mais elles occupent les six connexions qu'un navigateur\n * accorde par hôte — pour tous ses onglets à la fois. Avec plusieurs onglets\n * rechargés ensemble, l'ouverture du WebSocket attendait derrière cette file.\n */\n app.use('/assets', express.static(join(webDistPath, 'assets'), {\n immutable: true,\n maxAge: '1y',\n fallthrough: false,\n }));\n\n // Tout le reste (favicon…) : revalidation à chaque fois, ces noms ne changent\n // pas d'une version à l'autre.\n app.use(express.static(webDistPath, {\n index: false,\n setHeaders: (res) => res.setHeader('Cache-Control', 'no-cache'),\n }));\n\n // Fallback to index.html for client-side routing (Vue Router)\n // Express 5 requires explicit path patterns (not '*')\n //\n // JAMAIS mis en cache : c'est lui qui nomme les assets de la version courante.\n // Un index.html périmé rappellerait les fichiers de l'ancienne version — qui,\n // eux, ne sont plus là.\n //\n // `root` + nom relatif, jamais un chemin absolu : `sendFile` refuse tout\n // segment commençant par un point (`dotfiles: 'ignore'` par défaut) et\n // répond 404. Or l'installation la plus courante — `npx @runeya/runeya` —\n // vit sous `~/.npm/_npx/…`. Avec un chemin absolu, la page d'accueil était\n // donc introuvable sur toute machine lancée par npx (ou depuis `~/.nvm`),\n // alors que `/index.html` répondait : `express.static` ne teste, lui, que la\n // partie relative à sa racine.\n app.use((_req: Request, res: Response) => {\n res.setHeader('Cache-Control', 'no-cache');\n res.sendFile('index.html', { root: webDistPath });\n });\n\n const port = resolvePort();\n const host = process.env.RUNEYA_HOST ?? '127.0.0.1';\n\n await listenWithRetry(server, port, host, wss);\n\n // Announce this instance now that the port is really ours, so the settings\n // panel of any Runeya on this machine can list it.\n await registerInstance();\n\n /**\n * L'adresse d'écoute n'est pas une adresse de visite.\n *\n * `0.0.0.0` (et son équivalent IPv6 `::`) dit « toutes les interfaces » à\n * bind ; ce n'est pas une destination. Sous Linux une connexion vers elle\n * retombe sur la boucle locale, ce qui a longtemps masqué le problème — sous\n * Windows elle n'est pas routable du tout, et les navigateurs la bloquent\n * désormais ailleurs aussi. On écoute donc partout, mais on ouvre localhost.\n */\n const browseHost = host === '0.0.0.0' || host === '::' ? 'localhost' : host;\n const appUrl = `http://${browseHost}:${port}`;\n\n if (!noOpen) {\n await open(appUrl);\n }\n\n console.log('\\n🚀 Runeya is running!');\n if (isLanProxy) {\n console.log('🌐 LAN mode: server and service ports exposed on local network');\n }\n printStartupTable(port, appUrl);\n console.log('[cli] Press Ctrl+C to stop');\n\n // Assignée plus bas : l'arrêt doit pouvoir la retirer, et la poser demande\n // de savoir arrêter — les deux se référencent.\n let tray: { stop: () => Promise<void> } | null = null;\n\n let shuttingDown = false;\n const gracefulShutdown = async (signal: string) => {\n if (shuttingDown) {\n console.log(`[cli] Forced exit (second ${signal})`);\n process.exit(1);\n }\n shuttingDown = true;\n console.log(`\\n[cli] Received ${signal}, shutting down gracefully...`);\n\n // L'icône part en premier : elle annonce une instance vivante, et la\n // laisser pendant l'extinction inviterait à cliquer dans le vide.\n await tray?.stop();\n\n // In dev, exit immediately — ports are freed on process death,\n // and the 'exit' handler in agent-spawner SIGKILLs the agent.\n if (process.env.NODE_ENV === 'development') {\n process.exit(0);\n }\n\n await shutdown();\n console.log('[cli] Shutdown complete');\n process.exit(0);\n };\n\n process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));\n process.on('SIGINT', () => gracefulShutdown('SIGINT'));\n\n if (!noTray) {\n const { startInstanceTray } = await import('./tray.js');\n const {\n scheduleSelfRestart,\n listTrayServices,\n onTrayServicesChanged,\n startProcess,\n stopProcess,\n restartProcess,\n networkInfo,\n setLanMode,\n resolveTrayIcon,\n } = await import('@runeya/apps-server');\n\n tray = await startInstanceTray({\n info: { cwd: process.cwd(), port, version, url: appUrl },\n assetsDir: join(__dirname, 'assets'),\n openUrl: (target) => open(target),\n restart: () => scheduleSelfRestart(),\n stop: () => void gracefulShutdown('tray'),\n\n listServices: listTrayServices,\n startService: (id) => startProcess(id),\n // L'arrêt exige l'agent qui le fait tourner : il est dans la vue, et\n // seul un service en cours propose ce geste.\n stopService: async (id) => {\n const service = (await listTrayServices()).find((s) => s.id === id);\n if (!service?.agentId) throw new Error(`Aucun agent pour ${id}`);\n return stopProcess(id, service.agentId);\n },\n restartService: (id) => restartProcess(id),\n onServicesChanged: onTrayServicesChanged,\n // Le logo de l'organisation du projet ouvert, quand il y en a un : c'est ce\n // qui distingue deux Runeya dans la barre système.\n projectIcon: () => resolveTrayIcon(),\n\n lan: {\n read: () => {\n const info = networkInfo();\n // `lanUrls` est déjà ce qu'on voudrait lire au survol : des adresses\n // joignables, pas des IP brutes. Vide hors mode réseau local.\n return { enabled: info.lanEnabled, addresses: info.lanUrls };\n },\n toggle: (enabled) => setLanMode(enabled),\n },\n\n warn: (message) => console.log(message),\n });\n }\n}\n\nmain().catch(async (err) => {\n console.error('[cli] Fatal error:', err);\n\n // With a terminal, the message above is the report. Without one, it goes\n // nowhere: serve it as a page and open it in the browser instead.\n if (startupFailure) {\n try {\n const { diagnose, renderFailurePage, capturedLines, showStartupFailure } = startupFailure;\n const html = renderFailurePage(\n diagnose(err, resolvePort()),\n capturedLines(),\n {\n 'Version': version,\n 'Dossier de travail': process.cwd(),\n 'Node': process.execPath,\n 'Runeya': fileURLToPath(import.meta.url),\n },\n );\n await showStartupFailure(html);\n } catch (reportErr) {\n console.error('[cli] Impossible d\\'afficher le rapport d\\'erreur:', reportErr);\n }\n }\n\n process.exit(1);\n});\n","/**\n * Resolve the HTTP port Runeya should listen on.\n *\n * Only RUNEYA_HTTP_PORT is read (default 4000) — the generic PORT variable is\n * intentionally ignored so it can stay reserved for the user's own services.\n *\n * Throws if the resolved value is not an integer in [1, 65535].\n */\nexport function resolvePort(): number {\n const raw = process.env.RUNEYA_HTTP_PORT;\n if (raw === undefined) return 4000;\n\n const port = Number(raw);\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new Error(\n `Invalid port: ${JSON.stringify(raw)}. Must be an integer between 1 and 65535.`,\n );\n }\n return port;\n}\n"],"mappings":"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","names":["resolve","port"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/port-resolution.ts"],"sourcesContent":["#!/usr/bin/env node\nimport type { Server } from 'node:http';\nimport type { WebSocketServer } from 'ws';\nimport type { Request, Response } from 'express';\nimport { fileURLToPath, URL as NodeURL } from 'node:url';\nimport { dirname, join, resolve } from 'node:path';\nimport { readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport express from 'express';\nimport dotenv from 'dotenv'\nimport open from 'open';\nimport { resolvePort } from './port-resolution.js';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nconst { version } = JSON.parse(\n readFileSync(new NodeURL('./package.json', import.meta.url), 'utf8'),\n) as { version: string };\n\nfunction printStartupTable(port: number, appUrl: string): void {\n const rows: [string, string][] = [\n ['Version', version],\n ['Port', String(port)],\n ['Url', appUrl],\n ];\n\n const col0 = Math.max(...rows.map(([k]) => k.length));\n const col1 = Math.max(...rows.map(([, v]) => v.length));\n\n const pad = (s: string, n: number) => s.padEnd(n);\n const hr = (l: string, m: string, r: string, f: string) =>\n l + f.repeat(col0 + 2) + m + f.repeat(col1 + 2) + r;\n\n console.log('');\n console.log(hr('┌', '┬', '┐', '─'));\n for (const [key, value] of rows) {\n console.log(`│ ${pad(key, col0)} │ ${pad(value, col1)} │`);\n }\n console.log(hr('└', '┴', '┘', '─'));\n console.log('');\n}\n\n// Parse CLI flags\nconst args = process.argv.slice(2);\n\n/**\n * Set by the desktop launcher. It means nobody is watching a terminal, so a\n * startup failure has to be reported through a window of its own.\n */\nconst isFromDesktop = args.includes('--from-desktop');\n\n// Capture must start before anything logs, hence this early import.\nconst startupFailure = isFromDesktop ? await import('./startup-failure.js') : null;\nstartupFailure?.captureOutput();\n\nfunction getFlagValue(flags: string[]): string | undefined {\n for (const flag of flags) {\n const idx = args.indexOf(flag);\n if (idx !== -1 && idx + 1 < args.length) return args[idx + 1];\n }\n return undefined;\n}\n\n/**\n * Flags that mirror a RUNEYA_* environment variable. The flag always wins over\n * the variable, and both are equivalent otherwise.\n *\n * Secrets (RUNEYA_ENCRYPTION_KEY, RUNEYA_MASTER_PASSWORD) deliberately have no\n * flag: process arguments are world-readable through `ps` on most systems.\n */\nconst ENV_FLAGS: { flag: string; env: string }[] = [\n { flag: '--host', env: 'RUNEYA_HOST' },\n { flag: '--agent-port', env: 'RUNEYA_AGENT_PORT' },\n { flag: '--agent-host', env: 'RUNEYA_AGENT_HOST' },\n { flag: '--agent-binary-path', env: 'RUNEYA_AGENT_BINARY_PATH' },\n { flag: '--data-dir', env: 'RUNEYA_DATA_DIR' },\n { flag: '--mode', env: 'RUNEYA_MODE' },\n { flag: '--cloud-url', env: 'RUNEYA_CLOUD_URL' },\n { flag: '--cloud-app-url', env: 'RUNEYA_CLOUD_APP_URL' },\n { flag: '--cors-origin', env: 'RUNEYA_CORS_ORIGIN' },\n { flag: '--claude-pty', env: 'RUNEYA_CLAUDE_PTY' },\n];\n\n// Flags taking a value — needed so their value is not mistaken for the target directory\nconst flagsWithValues = new Set([\n '--port',\n '--name',\n '-e', '--environment',\n '-s', '--service',\n ...ENV_FLAGS.map((f) => f.flag),\n]);\n\n// Apply value flags to their env var (flag wins over an already-set variable).\n// Done before dotenv so a .env file can never override an explicit flag.\nfor (const { flag, env: key } of ENV_FLAGS) {\n const value = getFlagValue([flag]);\n if (value !== undefined) process.env[key] = value;\n}\n// --debug is a boolean shortcut for RUNEYA_DEBUG=1\nif (args.includes('--debug')) process.env['RUNEYA_DEBUG'] = '1';\n\n/**\n * `install-desktop` / `uninstall-desktop` — handled before anything else so the\n * sub-command name is never mistaken for a target directory, and so the current\n * working directory is still the user's when we capture it.\n *\n * Bare on a TTY it opens a wizard; any flag that pre-answers a question skips\n * straight to the action so scripts stay unattended.\n */\nconst subCommand = args[0];\nif (subCommand === 'install-desktop' || subCommand === 'uninstall-desktop') {\n const { installDesktopLauncher, uninstallDesktopLauncher, deriveIdentity } =\n await import('./desktop-launcher.js');\n const { shouldRunWizard, runInstallWizard, printInstallReport, printUninstallReport } =\n await import('./desktop-wizard.js');\n\n const { parsePort } = await import('./free-port.js');\n\n const rest = args.slice(1);\n // Every flag of this sub-command that takes a value: without this, the value\n // itself (a port number, a name) is mistaken for the target directory.\n const subFlagsWithValues = new Set(['--name', '--port', '--agent-port']);\n const positional = rest.find((a, i) => !a.startsWith('-') && !subFlagsWithValues.has(rest[i - 1] ?? ''));\n const nameFlag = getFlagValue(['--name']);\n\n // Ports baked into the shortcut. Null means \"follow Runeya's default\", so a\n // launcher created without them keeps tracking the default if it changes.\n const portFlagRaw = getFlagValue(['--port']);\n const agentPortFlagRaw = getFlagValue(['--agent-port']);\n for (const [flag, raw] of [['--port', portFlagRaw], ['--agent-port', agentPortFlagRaw]] as const) {\n if (raw !== undefined && parsePort(raw) === null) {\n console.error(`Erreur : ${flag} attend un entier entre 1 et 65535 (reçu ${JSON.stringify(raw)}).`);\n process.exit(1);\n }\n }\n let port = parsePort(portFlagRaw);\n let agentPort = parsePort(agentPortFlagRaw);\n\n // The data directory is resolved from the working directory, so a launcher\n // that does not pin one would start Runeya in the desktop's cwd (usually the\n // home directory) and create a stray .runeya there. Pin the cwd by default.\n let workingDir = rest.includes('--no-cwd') ? null : resolve(positional ?? process.cwd());\n let displayName = nameFlag;\n\n if (subCommand === 'install-desktop' && shouldRunWizard(rest, positional !== undefined)) {\n const answers = await runInstallWizard(process.cwd());\n if (!answers) process.exit(130); // aborted with Ctrl+C\n workingDir = answers.workingDir;\n displayName = answers.name;\n port = answers.port;\n agentPort = answers.agentPort;\n }\n\n const { name, id } = deriveIdentity(displayName, workingDir);\n\n try {\n if (subCommand === 'install-desktop') {\n const result = await installDesktopLauncher({\n nodePath: process.execPath,\n cliEntry: fileURLToPath(import.meta.url),\n distDir: __dirname,\n workingDir,\n name,\n id,\n port,\n agentPort,\n });\n printInstallReport({ name, workingDir, nodePath: process.execPath, port, agentPort, result });\n } else {\n printUninstallReport(name, await uninstallDesktopLauncher(name, id));\n }\n process.exit(0);\n } catch (err) {\n console.error(`Erreur : ${(err as Error).message}`);\n process.exit(1);\n }\n}\n\n/**\n * `runeya instances` — voir et piloter les Runeya de cette machine depuis un\n * terminal. Traité ici, avec les autres sous-commandes, pour que le mot\n * « instances » ne soit jamais pris pour un répertoire cible.\n *\n * Le pendant de l'icône de barre système, qui ne montre qu'une instance — la\n * sienne — et n'existe pas partout. Celle-ci les montre toutes, partout.\n *\n * Aucun serveur n'est démarré : le registre machine est un dossier de fichiers,\n * et le lire ne demande rien d'autre que de le lire.\n */\nif (subCommand === 'instances') {\n // Importé ici et pas en tête de fichier : charger `@runeya/apps-server` a un\n // coût, et un `runeya` ordinaire n'a pas à le payer pour une sous-commande\n // qu'il n'utilise pas.\n const { listInstances, killInstance, restartInstance } = await import('@runeya/apps-server');\n const { runInstancesCommand } = await import('./instances-command.js');\n\n process.exit(await runInstancesCommand(args.slice(1), {\n listInstances,\n stopInstance: killInstance,\n restartInstance: async (pid: number) => {\n const { pid: newPid, portReleased } = await restartInstance(pid);\n return { pid: newPid, portReleased };\n },\n openUrl: (url: string) => open(url),\n log: (message: string) => console.log(message),\n warn: (message: string) => console.error(message),\n }));\n}\n\n// Resolve target directory (first positional arg, skipping flag values)\nconst targetDir = args.find((a, i) => !a.startsWith('-') && !flagsWithValues.has(args[i - 1] ?? ''));\nif (targetDir) {\n const resolved = resolve(targetDir);\n process.chdir(resolved);\n console.log(`[cli] Working directory: ${resolved}`);\n} else if (process.env['RUNEYA_DATA_DIR']) {\n const resolved = resolve(process.env['RUNEYA_DATA_DIR'], '..');\n process.chdir(resolved);\n console.log(`[cli] Working directory: ${resolved} (from RUNEYA_DATA_DIR)`);\n} else if (process.cwd() === '/') {\n /**\n * On n'écrit jamais à la racine.\n *\n * Un lanceur global — installé sans dossier épinglé — démarre avec le cwd que\n * lui donne le système, et le Finder comme les services systemd donnent `/`.\n * `DATA_DIR` y vaudrait `/.runeya` : sous macOS la racine est le volume\n * système signé, monté en lecture seule, et la première écriture locale\n * échouerait en EROFS — que même root ne peut pas lever sans\n * `/etc/synthetic.conf` et un redémarrage. Sous Linux elle demanderait les\n * droits du superutilisateur pour un dossier qui n'a rien à faire là.\n *\n * Le repli vaut aussi pour les lanceurs DÉJÀ installés, que corriger le stub\n * ne rattraperait pas.\n */\n const home = homedir();\n process.chdir(home);\n console.log(`[cli] Working directory: ${home} (lanceur sans dossier épinglé)`);\n}\n\ndotenv.config({ quiet: true });\n\nif (args.includes('--help') || args.includes('-h')) {\n console.log(`Usage: runeya [path-to-your-stack] [options]\n\nCommands:\n install-desktop [path] Create a desktop/menu launcher for this machine\n Bare on a terminal, this opens a short wizard.\n uninstall-desktop Remove a launcher created by install-desktop\n --name <label> Launcher name (default: \"Runeya — <folder>\")\n --no-cwd Global launcher — do not pin a working directory\n --port <n> Port baked into the launcher (default: Runeya's own)\n --agent-port <n> Agent port baked in (default: launcher port + 1)\n -y, --yes Skip the wizard and take the defaults\n instances [open|stop|restart <pid>]\n List the Runeya running on this machine, and act on\n one. --json for the raw records.\n --from-desktop Set by desktop launchers: report startup failures\n in a browser window instead of a silent exit\n\nOptions:\n --version Show version number\n --pe, --pull-env Print env vars for a service to stdout (requires -e and -s)\n -e, --environment <n> Environment name or id\n -s, --service <name> Service name or id\n --lan Expose server on the local network (shortcut for --host 0.0.0.0)\n --no-open Do not open browser on startup\n --no-tray Do not put this instance in the system tray\n --agent Run as agent only (no server, no UI) — for remote machines\n -h, --help Show this help message\n\nConfiguration:\n Each setting has a flag and an equivalent RUNEYA_ environment variable; the\n flag wins. Variables are prefixed so they cannot collide with those of the\n services you manage. A .env file in the working directory is loaded\n automatically, but never overrides a flag.\n\n Flag Environment variable Default\n --port <n> RUNEYA_HTTP_PORT 4000\n (binds the agent instead when --agent is used)\n --host <address> RUNEYA_HOST 127.0.0.1\n --agent-port <n> RUNEYA_AGENT_PORT server port + 1\n --agent-host <address> RUNEYA_AGENT_HOST 127.0.0.1\n --agent-binary-path <path> RUNEYA_AGENT_BINARY_PATH bundled with the CLI\n --data-dir <path> RUNEYA_DATA_DIR <cwd>/.runeya\n --mode <mode> RUNEYA_MODE local-simple\n 'local-simple' | 'cloud'\n --cloud-url <url> RUNEYA_CLOUD_URL —\n --cloud-app-url <url> RUNEYA_CLOUD_APP_URL —\n --cors-origin <origin> RUNEYA_CORS_ORIGIN —\n --lan RUNEYA_LAN_PROXY false\n --debug RUNEYA_DEBUG false\n --claude-pty <0|1> RUNEYA_CLAUDE_PTY 1\n PTY mode for the Claude Code runner\n\n Secrets have no flag — process arguments are readable by other users via 'ps':\n RUNEYA_ENCRYPTION_KEY 64-char hex key for CI/CD — unlocks secrets without a\n master password AND disables tRPC authentication.\n Never set this on a machine reachable by others.\n RUNEYA_MASTER_PASSWORD Master password used by --pull-env instead of prompting\n\n Standard variables Runeya also honours: NODE_ENV, CI (skips opening the browser).\n`);\n process.exit(0);\n}\n\nif (args.includes('--version')) {\n console.log(version);\n process.exit(0);\n}\n\n/**\n * L'icône de barre système, sauf `--no-tray`.\n *\n * Chaque Runeya pose la sienne au démarrage et la retire en s'arrêtant : une\n * icône par instance en cours. Là où la barre système n'existe pas (serveur\n * sans bureau, arm64, paquet optionnel absent), il n'y a rien à désactiver —\n * l'icône ne se pose pas, et Runeya démarre pareil.\n */\nconst noTray = args.includes('--no-tray');\n\nconst noOpen =\n args.includes('--no-open') ||\n !!process.env['VITEST'] ||\n !!process.env['CI'] ||\n process.env['NODE_ENV'] === 'test';\n\n// --pull-env flag — detect early so we can silence stdout before any log\nconst isPullEnv = args.includes('--pull-env') || args.includes('--pe');\n\n// In pull-env mode, redirect console.log/info to stderr so only KEY=VALUE goes to stdout\nif (isPullEnv) {\n const toStderr = (...a: unknown[]) => process.stderr.write(a.join(' ') + '\\n');\n console.log = toStderr;\n console.info = toStderr;\n}\n\nconst serviceArg = getFlagValue(['-s', '--service']);\nconst environmentArg = getFlagValue(['-e', '--environment']);\n\n// Configure environment BEFORE importing server (env is parsed at module load)\n// --agent mode: run as standalone agent only (no server, no UI)\nconst isAgentOnly = args.includes('--agent');\n\n// --port targets the server, except in agent mode where it binds the agent\nconst portFlag = getFlagValue(['--port']);\nif (portFlag) {\n process.env[isAgentOnly ? 'RUNEYA_AGENT_PORT' : 'RUNEYA_HTTP_PORT'] = portFlag;\n}\n\n// --lan binds to 0.0.0.0. As an explicit flag it outranks RUNEYA_HOST; coming\n// from RUNEYA_LAN_PROXY it only fills in a host nobody else set.\nconst hostFlag = getFlagValue(['--host']);\nconst isLan = args.includes('--lan');\nconst isLanProxy = isLan || process.env.RUNEYA_LAN_PROXY === 'true' || process.env.RUNEYA_LAN_PROXY === '1';\nif (isLanProxy) {\n process.env.RUNEYA_LAN_PROXY = 'true';\n if (!hostFlag && isLan) process.env.RUNEYA_HOST = '0.0.0.0';\n else process.env.RUNEYA_HOST ??= '0.0.0.0';\n}\n\n// In agent mode --host binds the agent rather than the server\nif (isAgentOnly) {\n if (hostFlag) {\n process.env.RUNEYA_AGENT_HOST = hostFlag;\n } else if (isLan) {\n process.env.RUNEYA_AGENT_HOST = '0.0.0.0';\n } else if (isLanProxy) {\n process.env.RUNEYA_AGENT_HOST ??= '0.0.0.0';\n }\n}\n\n// Agent binary shipped inside the CLI dist — overridable via --agent-binary-path\nprocess.env.RUNEYA_AGENT_BINARY_PATH ??= join(__dirname, 'agent/index.js');\n// Expose CLI version to server\nprocess.env.RUNEYA_VERSION = version;\n// Tell the server it was launched from a shortcut, so the UI can say so\nif (isFromDesktop) process.env.RUNEYA_FROM_DESKTOP = '1';\n// Data directory defaults to CWD/.runeya (server env.ts default)\n// so Runeya data lives alongside the target project.\n\n/**\n * Listen with retry for EADDRINUSE — handles the race condition when the CLI\n * restarts the server before the old process has fully released the port.\n *\n * The `wss` parameter is needed because the `ws` library re-emits HTTP server\n * errors on the WebSocketServer — without a handler the error becomes unhandled.\n */\nfunction listenWithRetry(\n server: Server,\n port: number,\n host: string,\n wss?: WebSocketServer,\n maxRetries = 20,\n delay = 500,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n let attempts = 0;\n\n // Absorb EADDRINUSE errors re-emitted by the ws library on the WSS\n // during the retry window. Without this, Node.js crashes on unhandled error.\n const wssErrorHandler = () => { /* absorbed — handled via server 'error' */ };\n wss?.on('error', wssErrorHandler);\n\n const tryListen = () => {\n const onError = (err: NodeJS.ErrnoException) => {\n // Clean up the 'listening' callback that server.listen() registered\n server.removeAllListeners('listening');\n\n if (err.code === 'EADDRINUSE' && attempts < maxRetries) {\n attempts++;\n console.log(`[cli] Port ${port} in use, retrying in ${delay}ms (${attempts}/${maxRetries})...`);\n setTimeout(tryListen, delay);\n } else {\n wss?.removeListener('error', wssErrorHandler);\n reject(err);\n }\n };\n\n server.once('error', onError);\n server.listen(port, host, () => {\n server.removeListener('error', onError);\n wss?.removeListener('error', wssErrorHandler);\n resolve();\n });\n };\n\n tryListen();\n });\n}\n\nasync function main() {\n // Avant tout : ce que ce process hérite ici, le serveur, l'agent local et\n // chaque service lancé ensuite en héritent à leur tour. Un raccourci de bureau\n // reçoit le PATH de la session graphique, où ni les gestionnaires de version\n // ni les binaires installés par l'utilisateur (claude, codex) ne figurent.\n const { ensureNodeBinOnPath, ensureUserBinsOnPath, stampConsole } = await import('@runeya/packages-shared/node');\n ensureNodeBinOnPath();\n await ensureUserBinsOnPath();\n\n // Journaux datés du temps écoulé depuis le démarrage. Jamais en --pull-env :\n // sa sortie est lue par un script, pas par un humain.\n if (!isPullEnv) {\n stampConsole();\n // Sortie et crash recopiés sur disque : une instance relancée en\n // `stdio: 'ignore'` (bureau, mise à jour) n'a sinon aucune trace.\n try {\n const { installLogFile } = await import('./log-file.js');\n console.log(`[cli] Journal : ${installLogFile().logPath}`);\n } catch (err) {\n console.warn(`[cli] Journal sur disque indisponible : ${(err as Error).message}`);\n }\n }\n\n // Dynamic import ensures env is parsed AFTER we configure it\n const { createLocalServer, pullEnv, PullEnvError, registerInstance, registerCliLocation } = await import('@runeya/apps-server');\n\n // D'où ce CLI a été lancé, pour que l'interface puisse proposer `install-desktop`\n // sans que le serveur ait à deviner un exécutable.\n registerCliLocation({ execPath: process.execPath, cliEntry: fileURLToPath(import.meta.url) });\n\n // Handle --pull-env mode: resolve env vars and print, then exit\n if (isPullEnv) {\n if (!serviceArg) {\n console.error('Error: --service (-s) is required with --pull-env');\n process.exit(1);\n }\n if (!environmentArg) {\n console.error('Error: --environment (-e) is required with --pull-env');\n process.exit(1);\n }\n try {\n const output = await pullEnv({ service: serviceArg, environment: environmentArg });\n if (output) process.stdout.write(output + '\\n');\n process.exit(0);\n } catch (err: unknown) {\n if (err instanceof PullEnvError) {\n console.error(`Error: ${err.message}`);\n process.exit(err.exitCode);\n }\n throw err;\n }\n }\n\n // --agent mode: standalone agent, no server, no UI\n if (isAgentOnly) {\n const { spawn } = await import('node:child_process');\n const agentBin = join(__dirname, 'agent/index.js');\n const child = spawn(process.execPath, [agentBin], { stdio: 'inherit', windowsHide: true });\n child.on('exit', (code) => process.exit(code ?? 0));\n // SIGINT is already delivered to the child by the terminal (same process group).\n // Intercept it here only to suppress Node's default exit so we stay alive\n // until the child finishes its graceful shutdown.\n process.on('SIGINT', () => { /* wait for child to exit */ });\n process.on('SIGTERM', () => child.kill('SIGTERM'));\n return;\n }\n\n /**\n * Un relais de redémarrage (`appUpdate.restart`) est l'exception au garde-fou\n * ci-dessous : l'instance qui répond encore sur le port est précisément celle\n * qu'on remplace. On la laisse s'éteindre, `listenWithRetry` absorbe\n * l'EADDRINUSE du chevauchement. La marque est consommée ici pour ne pas se\n * propager aux services lancés ensuite, qui héritent de cet environnement.\n */\n const isRestartHandoff = process.env.RUNEYA_RESTART_HANDOFF === '1';\n delete process.env.RUNEYA_RESTART_HANDOFF;\n\n /**\n * A shortcut clicked twice must not fail.\n *\n * Starting a second instance on a port a Runeya already holds ends in\n * EADDRINUSE after ten seconds of retries — and from a launcher there is no\n * terminal to read that in. So the port is asked first: if Runeya answers,\n * the right move is to bring up the window that already exists.\n *\n * Only for launcher starts. From a terminal, `runeya` twice on one port is a\n * mistake worth reporting, not one worth papering over.\n */\n if (isFromDesktop && !isRestartHandoff) {\n const port = resolvePort();\n const { probeRuneya } = await import('./free-port.js');\n const existing = await probeRuneya(port);\n if (existing) {\n const url = `http://localhost:${port}`;\n console.log(`[cli] Runeya v${existing.version} déjà en cours sur le port ${port} — ouverture de ${url}`);\n if (!noOpen) await open(url);\n return;\n }\n }\n\n console.log('[cli] Starting Runeya...');\n\n // Create server (automatically spawns local agent)\n const { app, server, wss, shutdown } = await createLocalServer();\n\n // Serve static files from web frontend (embedded in CLI dist during build)\n const webDistPath = join(__dirname, 'web');\n\n /**\n * Les fichiers d'`assets/` portent un hash de leur contenu dans leur nom : une\n * mise à jour produit un NOUVEAU nom, jamais un contenu différent sous le même\n * nom. Ils peuvent donc être gardés indéfiniment, et `immutable` dit au\n * navigateur de ne même pas revalider.\n *\n * Sans cela, `express.static` répond `max-age=0` : chaque rechargement\n * redemande les 295 fichiers pour s'entendre répondre 304. Ce sont des\n * requêtes vides, mais elles occupent les six connexions qu'un navigateur\n * accorde par hôte — pour tous ses onglets à la fois. Avec plusieurs onglets\n * rechargés ensemble, l'ouverture du WebSocket attendait derrière cette file.\n */\n app.use('/assets', express.static(join(webDistPath, 'assets'), {\n immutable: true,\n maxAge: '1y',\n fallthrough: false,\n }));\n\n // Tout le reste (favicon…) : revalidation à chaque fois, ces noms ne changent\n // pas d'une version à l'autre.\n app.use(express.static(webDistPath, {\n index: false,\n setHeaders: (res) => res.setHeader('Cache-Control', 'no-cache'),\n }));\n\n // Fallback to index.html for client-side routing (Vue Router)\n // Express 5 requires explicit path patterns (not '*')\n //\n // JAMAIS mis en cache : c'est lui qui nomme les assets de la version courante.\n // Un index.html périmé rappellerait les fichiers de l'ancienne version — qui,\n // eux, ne sont plus là.\n //\n // `root` + nom relatif, jamais un chemin absolu : `sendFile` refuse tout\n // segment commençant par un point (`dotfiles: 'ignore'` par défaut) et\n // répond 404. Or l'installation la plus courante — `npx @runeya/runeya` —\n // vit sous `~/.npm/_npx/…`. Avec un chemin absolu, la page d'accueil était\n // donc introuvable sur toute machine lancée par npx (ou depuis `~/.nvm`),\n // alors que `/index.html` répondait : `express.static` ne teste, lui, que la\n // partie relative à sa racine.\n app.use((_req: Request, res: Response) => {\n res.setHeader('Cache-Control', 'no-cache');\n res.sendFile('index.html', { root: webDistPath });\n });\n\n const port = resolvePort();\n const host = process.env.RUNEYA_HOST ?? '127.0.0.1';\n\n await listenWithRetry(server, port, host, wss);\n\n // Announce this instance now that the port is really ours, so the settings\n // panel of any Runeya on this machine can list it.\n await registerInstance();\n\n /**\n * L'adresse d'écoute n'est pas une adresse de visite.\n *\n * `0.0.0.0` (et son équivalent IPv6 `::`) dit « toutes les interfaces » à\n * bind ; ce n'est pas une destination. Sous Linux une connexion vers elle\n * retombe sur la boucle locale, ce qui a longtemps masqué le problème — sous\n * Windows elle n'est pas routable du tout, et les navigateurs la bloquent\n * désormais ailleurs aussi. On écoute donc partout, mais on ouvre localhost.\n */\n const browseHost = host === '0.0.0.0' || host === '::' ? 'localhost' : host;\n const appUrl = `http://${browseHost}:${port}`;\n\n if (!noOpen) {\n await open(appUrl);\n }\n\n console.log('\\n🚀 Runeya is running!');\n if (isLanProxy) {\n console.log('🌐 LAN mode: server and service ports exposed on local network');\n }\n printStartupTable(port, appUrl);\n console.log('[cli] Press Ctrl+C to stop');\n\n // Assignée plus bas : l'arrêt doit pouvoir la retirer, et la poser demande\n // de savoir arrêter — les deux se référencent.\n let tray: { stop: () => Promise<void> } | null = null;\n\n let shuttingDown = false;\n const gracefulShutdown = async (signal: string) => {\n if (shuttingDown) {\n console.log(`[cli] Forced exit (second ${signal})`);\n process.exit(1);\n }\n shuttingDown = true;\n console.log(`\\n[cli] Received ${signal}, shutting down gracefully...`);\n\n // L'icône part en premier : elle annonce une instance vivante, et la\n // laisser pendant l'extinction inviterait à cliquer dans le vide.\n await tray?.stop();\n\n // In dev, exit immediately — ports are freed on process death,\n // and the 'exit' handler in agent-spawner SIGKILLs the agent.\n if (process.env.NODE_ENV === 'development') {\n process.exit(0);\n }\n\n await shutdown();\n console.log('[cli] Shutdown complete');\n process.exit(0);\n };\n\n process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));\n process.on('SIGINT', () => gracefulShutdown('SIGINT'));\n\n if (!noTray) {\n const { startInstanceTray } = await import('./tray.js');\n const {\n scheduleSelfRestart,\n listTrayServices,\n onTrayServicesChanged,\n startProcess,\n stopProcess,\n restartProcess,\n networkInfo,\n setLanMode,\n resolveTrayIcon,\n } = await import('@runeya/apps-server');\n\n tray = await startInstanceTray({\n info: { cwd: process.cwd(), port, version, url: appUrl },\n assetsDir: join(__dirname, 'assets'),\n openUrl: (target) => open(target),\n restart: () => scheduleSelfRestart(),\n stop: () => void gracefulShutdown('tray'),\n\n listServices: listTrayServices,\n startService: (id) => startProcess(id),\n // L'arrêt exige l'agent qui le fait tourner : il est dans la vue, et\n // seul un service en cours propose ce geste.\n stopService: async (id) => {\n const service = (await listTrayServices()).find((s) => s.id === id);\n if (!service?.agentId) throw new Error(`Aucun agent pour ${id}`);\n return stopProcess(id, service.agentId);\n },\n restartService: (id) => restartProcess(id),\n onServicesChanged: onTrayServicesChanged,\n // Le logo de l'organisation du projet ouvert, quand il y en a un : c'est ce\n // qui distingue deux Runeya dans la barre système.\n projectIcon: () => resolveTrayIcon(),\n\n lan: {\n read: () => {\n const info = networkInfo();\n // `lanUrls` est déjà ce qu'on voudrait lire au survol : des adresses\n // joignables, pas des IP brutes. Vide hors mode réseau local.\n return { enabled: info.lanEnabled, addresses: info.lanUrls };\n },\n toggle: (enabled) => setLanMode(enabled),\n },\n\n warn: (message) => console.log(message),\n });\n }\n}\n\nmain().catch(async (err) => {\n console.error('[cli] Fatal error:', err);\n\n // With a terminal, the message above is the report. Without one, it goes\n // nowhere: serve it as a page and open it in the browser instead.\n if (startupFailure) {\n try {\n const { diagnose, renderFailurePage, capturedLines, showStartupFailure } = startupFailure;\n const html = renderFailurePage(\n diagnose(err, resolvePort()),\n capturedLines(),\n {\n 'Version': version,\n 'Dossier de travail': process.cwd(),\n 'Node': process.execPath,\n 'Runeya': fileURLToPath(import.meta.url),\n },\n );\n await showStartupFailure(html);\n } catch (reportErr) {\n console.error('[cli] Impossible d\\'afficher le rapport d\\'erreur:', reportErr);\n }\n }\n\n process.exit(1);\n});\n","/**\n * Resolve the HTTP port Runeya should listen on.\n *\n * Only RUNEYA_HTTP_PORT is read (default 4000) — the generic PORT variable is\n * intentionally ignored so it can stay reserved for the user's own services.\n *\n * Throws if the resolved value is not an integer in [1, 65535].\n */\nexport function resolvePort(): number {\n const raw = process.env.RUNEYA_HTTP_PORT;\n if (raw === undefined) return 4000;\n\n const port = Number(raw);\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new Error(\n `Invalid port: ${JSON.stringify(raw)}. Must be an integer between 1 and 65535.`,\n );\n }\n return port;\n}\n"],"mappings":";;;AAIA,SAAS,eAAe,OAAO,eAAe;AAC9C,SAAS,SAAS,MAAM,eAAe;AACvC,SAAS,oBAAoB;AAC7B,SAAS,eAAe;AACxB,OAAO,aAAa;AACpB,OAAO,YAAY;AACnB,OAAO,UAAU;;;ACFV,SAAS,cAAsB;AACpC,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,QAAQ,OAAW,QAAO;AAE9B,QAAM,OAAO,OAAO,GAAG;AACvB,MAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,OAAO,OAAO;AACvD,UAAM,IAAI;AAAA,MACR,iBAAiB,KAAK,UAAU,GAAG,CAAC;AAAA,IACtC;AAAA,EACF;AACA,SAAO;AACT;;;ADNA,IAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AAExD,IAAM,EAAE,QAAQ,IAAI,KAAK;AAAA,EACvB,aAAa,IAAI,QAAQ,kBAAkB,YAAY,GAAG,GAAG,MAAM;AACrE;AAEA,SAAS,kBAAkB,MAAc,QAAsB;AAC7D,QAAM,OAA2B;AAAA,IAC/B,CAAC,WAAW,OAAO;AAAA,IACnB,CAAC,QAAQ,OAAO,IAAI,CAAC;AAAA,IACrB,CAAC,OAAO,MAAM;AAAA,EAChB;AAEA,QAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC;AACpD,QAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;AAEtD,QAAM,MAAM,CAAC,GAAW,MAAc,EAAE,OAAO,CAAC;AAChD,QAAM,KAAK,CAAC,GAAW,GAAW,GAAW,MAC3C,IAAI,EAAE,OAAO,OAAO,CAAC,IAAI,IAAI,EAAE,OAAO,OAAO,CAAC,IAAI;AAEpD,UAAQ,IAAI,EAAE;AACd,UAAQ,IAAI,GAAG,UAAK,UAAK,UAAK,QAAG,CAAC;AAClC,aAAW,CAAC,KAAK,KAAK,KAAK,MAAM;AAC/B,YAAQ,IAAI,UAAK,IAAI,KAAK,IAAI,CAAC,WAAM,IAAI,OAAO,IAAI,CAAC,SAAI;AAAA,EAC3D;AACA,UAAQ,IAAI,GAAG,UAAK,UAAK,UAAK,QAAG,CAAC;AAClC,UAAQ,IAAI,EAAE;AAChB;AAGA,IAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AAMjC,IAAM,gBAAgB,KAAK,SAAS,gBAAgB;AAGpD,IAAM,iBAAiB,gBAAgB,MAAM,OAAO,+BAAsB,IAAI;AAC9E,gBAAgB,cAAc;AAE9B,SAAS,aAAa,OAAqC;AACzD,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,KAAK,QAAQ,IAAI;AAC7B,QAAI,QAAQ,MAAM,MAAM,IAAI,KAAK,OAAQ,QAAO,KAAK,MAAM,CAAC;AAAA,EAC9D;AACA,SAAO;AACT;AASA,IAAM,YAA6C;AAAA,EACjD,EAAE,MAAM,UAAU,KAAK,cAAc;AAAA,EACrC,EAAE,MAAM,gBAAgB,KAAK,oBAAoB;AAAA,EACjD,EAAE,MAAM,gBAAgB,KAAK,oBAAoB;AAAA,EACjD,EAAE,MAAM,uBAAuB,KAAK,2BAA2B;AAAA,EAC/D,EAAE,MAAM,cAAc,KAAK,kBAAkB;AAAA,EAC7C,EAAE,MAAM,UAAU,KAAK,cAAc;AAAA,EACrC,EAAE,MAAM,eAAe,KAAK,mBAAmB;AAAA,EAC/C,EAAE,MAAM,mBAAmB,KAAK,uBAAuB;AAAA,EACvD,EAAE,MAAM,iBAAiB,KAAK,qBAAqB;AAAA,EACnD,EAAE,MAAM,gBAAgB,KAAK,oBAAoB;AACnD;AAGA,IAAM,kBAAkB,oBAAI,IAAI;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EAAM;AAAA,EACN;AAAA,EAAM;AAAA,EACN,GAAG,UAAU,IAAI,CAAC,MAAM,EAAE,IAAI;AAChC,CAAC;AAID,WAAW,EAAE,MAAM,KAAK,IAAI,KAAK,WAAW;AAC1C,QAAM,QAAQ,aAAa,CAAC,IAAI,CAAC;AACjC,MAAI,UAAU,OAAW,SAAQ,IAAI,GAAG,IAAI;AAC9C;AAEA,IAAI,KAAK,SAAS,SAAS,EAAG,SAAQ,IAAI,cAAc,IAAI;AAU5D,IAAM,aAAa,KAAK,CAAC;AACzB,IAAI,eAAe,qBAAqB,eAAe,qBAAqB;AAC1E,QAAM,EAAE,wBAAwB,0BAA0B,eAAe,IACvE,MAAM,OAAO,gCAAuB;AACtC,QAAM,EAAE,iBAAiB,kBAAkB,oBAAoB,qBAAqB,IAClF,MAAM,OAAO,8BAAqB;AAEpC,QAAM,EAAE,UAAU,IAAI,MAAM,OAAO,yBAAgB;AAEnD,QAAM,OAAO,KAAK,MAAM,CAAC;AAGzB,QAAM,qBAAqB,oBAAI,IAAI,CAAC,UAAU,UAAU,cAAc,CAAC;AACvE,QAAM,aAAa,KAAK,KAAK,CAAC,GAAG,MAAM,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC,mBAAmB,IAAI,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;AACvG,QAAM,WAAW,aAAa,CAAC,QAAQ,CAAC;AAIxC,QAAM,cAAc,aAAa,CAAC,QAAQ,CAAC;AAC3C,QAAM,mBAAmB,aAAa,CAAC,cAAc,CAAC;AACtD,aAAW,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,UAAU,WAAW,GAAG,CAAC,gBAAgB,gBAAgB,CAAC,GAAY;AAChG,QAAI,QAAQ,UAAa,UAAU,GAAG,MAAM,MAAM;AAChD,cAAQ,MAAM,YAAY,IAAI,+CAA4C,KAAK,UAAU,GAAG,CAAC,IAAI;AACjG,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AACA,MAAI,OAAO,UAAU,WAAW;AAChC,MAAI,YAAY,UAAU,gBAAgB;AAK1C,MAAI,aAAa,KAAK,SAAS,UAAU,IAAI,OAAO,QAAQ,cAAc,QAAQ,IAAI,CAAC;AACvF,MAAI,cAAc;AAElB,MAAI,eAAe,qBAAqB,gBAAgB,MAAM,eAAe,MAAS,GAAG;AACvF,UAAM,UAAU,MAAM,iBAAiB,QAAQ,IAAI,CAAC;AACpD,QAAI,CAAC,QAAS,SAAQ,KAAK,GAAG;AAC9B,iBAAa,QAAQ;AACrB,kBAAc,QAAQ;AACtB,WAAO,QAAQ;AACf,gBAAY,QAAQ;AAAA,EACtB;AAEA,QAAM,EAAE,MAAM,GAAG,IAAI,eAAe,aAAa,UAAU;AAE3D,MAAI;AACF,QAAI,eAAe,mBAAmB;AACpC,YAAM,SAAS,MAAM,uBAAuB;AAAA,QAC1C,UAAU,QAAQ;AAAA,QAClB,UAAU,cAAc,YAAY,GAAG;AAAA,QACvC,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AACD,yBAAmB,EAAE,MAAM,YAAY,UAAU,QAAQ,UAAU,MAAM,WAAW,OAAO,CAAC;AAAA,IAC9F,OAAO;AACL,2BAAqB,MAAM,MAAM,yBAAyB,MAAM,EAAE,CAAC;AAAA,IACrE;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB,SAAS,KAAK;AACZ,YAAQ,MAAM,YAAa,IAAc,OAAO,EAAE;AAClD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAaA,IAAI,eAAe,aAAa;AAI9B,QAAM,EAAE,eAAe,cAAc,gBAAgB,IAAI,MAAM,OAAO,mBAAqB;AAC3F,QAAM,EAAE,oBAAoB,IAAI,MAAM,OAAO,iCAAwB;AAErE,UAAQ,KAAK,MAAM,oBAAoB,KAAK,MAAM,CAAC,GAAG;AAAA,IACpD;AAAA,IACA,cAAc;AAAA,IACd,iBAAiB,OAAO,QAAgB;AACtC,YAAM,EAAE,KAAK,QAAQ,aAAa,IAAI,MAAM,gBAAgB,GAAG;AAC/D,aAAO,EAAE,KAAK,QAAQ,aAAa;AAAA,IACrC;AAAA,IACA,SAAS,CAAC,QAAgB,KAAK,GAAG;AAAA,IAClC,KAAK,CAAC,YAAoB,QAAQ,IAAI,OAAO;AAAA,IAC7C,MAAM,CAAC,YAAoB,QAAQ,MAAM,OAAO;AAAA,EAClD,CAAC,CAAC;AACJ;AAGA,IAAM,YAAY,KAAK,KAAK,CAAC,GAAG,MAAM,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC,gBAAgB,IAAI,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;AACnG,IAAI,WAAW;AACb,QAAM,WAAW,QAAQ,SAAS;AAClC,UAAQ,MAAM,QAAQ;AACtB,UAAQ,IAAI,4BAA4B,QAAQ,EAAE;AACpD,WAAW,QAAQ,IAAI,iBAAiB,GAAG;AACzC,QAAM,WAAW,QAAQ,QAAQ,IAAI,iBAAiB,GAAG,IAAI;AAC7D,UAAQ,MAAM,QAAQ;AACtB,UAAQ,IAAI,4BAA4B,QAAQ,yBAAyB;AAC3E,WAAW,QAAQ,IAAI,MAAM,KAAK;AAehC,QAAM,OAAO,QAAQ;AACrB,UAAQ,MAAM,IAAI;AAClB,UAAQ,IAAI,4BAA4B,IAAI,uCAAiC;AAC/E;AAEA,OAAO,OAAO,EAAE,OAAO,KAAK,CAAC;AAE7B,IAAI,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,IAAI,GAAG;AAClD,UAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CA2Db;AACC,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAI,KAAK,SAAS,WAAW,GAAG;AAC9B,UAAQ,IAAI,OAAO;AACnB,UAAQ,KAAK,CAAC;AAChB;AAUA,IAAM,SAAS,KAAK,SAAS,WAAW;AAExC,IAAM,SACJ,KAAK,SAAS,WAAW,KACzB,CAAC,CAAC,QAAQ,IAAI,QAAQ,KACtB,CAAC,CAAC,QAAQ,IAAI,IAAI,KAClB,QAAQ,IAAI,UAAU,MAAM;AAG9B,IAAM,YAAY,KAAK,SAAS,YAAY,KAAK,KAAK,SAAS,MAAM;AAGrE,IAAI,WAAW;AACb,QAAM,WAAW,IAAI,MAAiB,QAAQ,OAAO,MAAM,EAAE,KAAK,GAAG,IAAI,IAAI;AAC7E,UAAQ,MAAM;AACd,UAAQ,OAAO;AACjB;AAEA,IAAM,aAAa,aAAa,CAAC,MAAM,WAAW,CAAC;AACnD,IAAM,iBAAiB,aAAa,CAAC,MAAM,eAAe,CAAC;AAI3D,IAAM,cAAc,KAAK,SAAS,SAAS;AAG3C,IAAM,WAAW,aAAa,CAAC,QAAQ,CAAC;AACxC,IAAI,UAAU;AACZ,UAAQ,IAAI,cAAc,sBAAsB,kBAAkB,IAAI;AACxE;AAIA,IAAM,WAAW,aAAa,CAAC,QAAQ,CAAC;AACxC,IAAM,QAAQ,KAAK,SAAS,OAAO;AACnC,IAAM,aAAa,SAAS,QAAQ,IAAI,qBAAqB,UAAU,QAAQ,IAAI,qBAAqB;AACxG,IAAI,YAAY;AACd,UAAQ,IAAI,mBAAmB;AAC/B,MAAI,CAAC,YAAY,MAAO,SAAQ,IAAI,cAAc;AAAA,MAC7C,SAAQ,IAAI,gBAAgB;AACnC;AAGA,IAAI,aAAa;AACf,MAAI,UAAU;AACZ,YAAQ,IAAI,oBAAoB;AAAA,EAClC,WAAW,OAAO;AAChB,YAAQ,IAAI,oBAAoB;AAAA,EAClC,WAAW,YAAY;AACrB,YAAQ,IAAI,sBAAsB;AAAA,EACpC;AACF;AAGA,QAAQ,IAAI,6BAA6B,KAAK,WAAW,gBAAgB;AAEzE,QAAQ,IAAI,iBAAiB;AAE7B,IAAI,cAAe,SAAQ,IAAI,sBAAsB;AAWrD,SAAS,gBACP,QACA,MACA,MACA,KACA,aAAa,IACb,QAAQ,KACO;AACf,SAAO,IAAI,QAAQ,CAACA,UAAS,WAAW;AACtC,QAAI,WAAW;AAIf,UAAM,kBAAkB,MAAM;AAAA,IAA8C;AAC5E,SAAK,GAAG,SAAS,eAAe;AAEhC,UAAM,YAAY,MAAM;AACtB,YAAM,UAAU,CAAC,QAA+B;AAE9C,eAAO,mBAAmB,WAAW;AAErC,YAAI,IAAI,SAAS,gBAAgB,WAAW,YAAY;AACtD;AACA,kBAAQ,IAAI,cAAc,IAAI,wBAAwB,KAAK,OAAO,QAAQ,IAAI,UAAU,MAAM;AAC9F,qBAAW,WAAW,KAAK;AAAA,QAC7B,OAAO;AACL,eAAK,eAAe,SAAS,eAAe;AAC5C,iBAAO,GAAG;AAAA,QACZ;AAAA,MACF;AAEA,aAAO,KAAK,SAAS,OAAO;AAC5B,aAAO,OAAO,MAAM,MAAM,MAAM;AAC9B,eAAO,eAAe,SAAS,OAAO;AACtC,aAAK,eAAe,SAAS,eAAe;AAC5C,QAAAA,SAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAEA,cAAU;AAAA,EACZ,CAAC;AACH;AAEA,eAAe,OAAO;AAKpB,QAAM,EAAE,qBAAqB,sBAAsB,aAAa,IAAI,MAAM,OAAO,oBAA8B;AAC/G,sBAAoB;AACpB,QAAM,qBAAqB;AAI3B,MAAI,CAAC,WAAW;AACd,iBAAa;AAGb,QAAI;AACF,YAAM,EAAE,eAAe,IAAI,MAAM,OAAO,wBAAe;AACvD,cAAQ,IAAI,mBAAmB,eAAe,EAAE,OAAO,EAAE;AAAA,IAC3D,SAAS,KAAK;AACZ,cAAQ,KAAK,2CAA4C,IAAc,OAAO,EAAE;AAAA,IAClF;AAAA,EACF;AAGA,QAAM,EAAE,mBAAmB,SAAS,cAAc,kBAAkB,oBAAoB,IAAI,MAAM,OAAO,mBAAqB;AAI9H,sBAAoB,EAAE,UAAU,QAAQ,UAAU,UAAU,cAAc,YAAY,GAAG,EAAE,CAAC;AAG5F,MAAI,WAAW;AACb,QAAI,CAAC,YAAY;AACf,cAAQ,MAAM,mDAAmD;AACjE,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,QAAI,CAAC,gBAAgB;AACnB,cAAQ,MAAM,uDAAuD;AACrE,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,QAAI;AACF,YAAM,SAAS,MAAM,QAAQ,EAAE,SAAS,YAAY,aAAa,eAAe,CAAC;AACjF,UAAI,OAAQ,SAAQ,OAAO,MAAM,SAAS,IAAI;AAC9C,cAAQ,KAAK,CAAC;AAAA,IAChB,SAAS,KAAc;AACrB,UAAI,eAAe,cAAc;AAC/B,gBAAQ,MAAM,UAAU,IAAI,OAAO,EAAE;AACrC,gBAAQ,KAAK,IAAI,QAAQ;AAAA,MAC3B;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAGA,MAAI,aAAa;AACf,UAAM,EAAE,MAAM,IAAI,MAAM,OAAO,eAAoB;AACnD,UAAM,WAAW,KAAK,WAAW,gBAAgB;AACjD,UAAM,QAAQ,MAAM,QAAQ,UAAU,CAAC,QAAQ,GAAG,EAAE,OAAO,WAAW,aAAa,KAAK,CAAC;AACzF,UAAM,GAAG,QAAQ,CAAC,SAAS,QAAQ,KAAK,QAAQ,CAAC,CAAC;AAIlD,YAAQ,GAAG,UAAU,MAAM;AAAA,IAA+B,CAAC;AAC3D,YAAQ,GAAG,WAAW,MAAM,MAAM,KAAK,SAAS,CAAC;AACjD;AAAA,EACF;AASA,QAAM,mBAAmB,QAAQ,IAAI,2BAA2B;AAChE,SAAO,QAAQ,IAAI;AAanB,MAAI,iBAAiB,CAAC,kBAAkB;AACtC,UAAMC,QAAO,YAAY;AACzB,UAAM,EAAE,YAAY,IAAI,MAAM,OAAO,yBAAgB;AACrD,UAAM,WAAW,MAAM,YAAYA,KAAI;AACvC,QAAI,UAAU;AACZ,YAAM,MAAM,oBAAoBA,KAAI;AACpC,cAAQ,IAAI,iBAAiB,SAAS,OAAO,oCAA8BA,KAAI,wBAAmB,GAAG,EAAE;AACvG,UAAI,CAAC,OAAQ,OAAM,KAAK,GAAG;AAC3B;AAAA,IACF;AAAA,EACF;AAEA,UAAQ,IAAI,0BAA0B;AAGtC,QAAM,EAAE,KAAK,QAAQ,KAAK,SAAS,IAAI,MAAM,kBAAkB;AAG/D,QAAM,cAAc,KAAK,WAAW,KAAK;AAczC,MAAI,IAAI,WAAW,QAAQ,OAAO,KAAK,aAAa,QAAQ,GAAG;AAAA,IAC7D,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,aAAa;AAAA,EACf,CAAC,CAAC;AAIF,MAAI,IAAI,QAAQ,OAAO,aAAa;AAAA,IAClC,OAAO;AAAA,IACP,YAAY,CAAC,QAAQ,IAAI,UAAU,iBAAiB,UAAU;AAAA,EAChE,CAAC,CAAC;AAgBF,MAAI,IAAI,CAAC,MAAe,QAAkB;AACxC,QAAI,UAAU,iBAAiB,UAAU;AACzC,QAAI,SAAS,cAAc,EAAE,MAAM,YAAY,CAAC;AAAA,EAClD,CAAC;AAED,QAAM,OAAO,YAAY;AACzB,QAAM,OAAO,QAAQ,IAAI,eAAe;AAExC,QAAM,gBAAgB,QAAQ,MAAM,MAAM,GAAG;AAI7C,QAAM,iBAAiB;AAWvB,QAAM,aAAa,SAAS,aAAa,SAAS,OAAO,cAAc;AACvE,QAAM,SAAS,UAAU,UAAU,IAAI,IAAI;AAE3C,MAAI,CAAC,QAAQ;AACX,UAAM,KAAK,MAAM;AAAA,EACnB;AAEA,UAAQ,IAAI,iCAA0B;AACtC,MAAI,YAAY;AACd,YAAQ,IAAI,wEAAiE;AAAA,EAC/E;AACA,oBAAkB,MAAM,MAAM;AAC9B,UAAQ,IAAI,4BAA4B;AAIxC,MAAI,OAA6C;AAEjD,MAAI,eAAe;AACnB,QAAM,mBAAmB,OAAO,WAAmB;AACjD,QAAI,cAAc;AAChB,cAAQ,IAAI,6BAA6B,MAAM,GAAG;AAClD,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,mBAAe;AACf,YAAQ,IAAI;AAAA,iBAAoB,MAAM,+BAA+B;AAIrE,UAAM,MAAM,KAAK;AAIjB,QAAI,QAAQ,IAAI,aAAa,eAAe;AAC1C,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,SAAS;AACf,YAAQ,IAAI,yBAAyB;AACrC,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,GAAG,WAAW,MAAM,iBAAiB,SAAS,CAAC;AACvD,UAAQ,GAAG,UAAU,MAAM,iBAAiB,QAAQ,CAAC;AAErD,MAAI,CAAC,QAAQ;AACX,UAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,oBAAW;AACtD,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,MAAM,OAAO,mBAAqB;AAEtC,WAAO,MAAM,kBAAkB;AAAA,MAC7B,MAAM,EAAE,KAAK,QAAQ,IAAI,GAAG,MAAM,SAAS,KAAK,OAAO;AAAA,MACvD,WAAW,KAAK,WAAW,QAAQ;AAAA,MACnC,SAAS,CAAC,WAAW,KAAK,MAAM;AAAA,MAChC,SAAS,MAAM,oBAAoB;AAAA,MACnC,MAAM,MAAM,KAAK,iBAAiB,MAAM;AAAA,MAExC,cAAc;AAAA,MACd,cAAc,CAAC,OAAO,aAAa,EAAE;AAAA;AAAA;AAAA,MAGrC,aAAa,OAAO,OAAO;AACzB,cAAM,WAAW,MAAM,iBAAiB,GAAG,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAClE,YAAI,CAAC,SAAS,QAAS,OAAM,IAAI,MAAM,oBAAoB,EAAE,EAAE;AAC/D,eAAO,YAAY,IAAI,QAAQ,OAAO;AAAA,MACxC;AAAA,MACA,gBAAgB,CAAC,OAAO,eAAe,EAAE;AAAA,MACzC,mBAAmB;AAAA;AAAA;AAAA,MAGnB,aAAa,MAAM,gBAAgB;AAAA,MAEnC,KAAK;AAAA,QACH,MAAM,MAAM;AACV,gBAAM,OAAO,YAAY;AAGzB,iBAAO,EAAE,SAAS,KAAK,YAAY,WAAW,KAAK,QAAQ;AAAA,QAC7D;AAAA,QACA,QAAQ,CAAC,YAAY,WAAW,OAAO;AAAA,MACzC;AAAA,MAEA,MAAM,CAAC,YAAY,QAAQ,IAAI,OAAO;AAAA,IACxC,CAAC;AAAA,EACH;AACF;AAEA,KAAK,EAAE,MAAM,OAAO,QAAQ;AAC1B,UAAQ,MAAM,sBAAsB,GAAG;AAIvC,MAAI,gBAAgB;AAClB,QAAI;AACF,YAAM,EAAE,UAAU,mBAAmB,eAAe,mBAAmB,IAAI;AAC3E,YAAM,OAAO;AAAA,QACX,SAAS,KAAK,YAAY,CAAC;AAAA,QAC3B,cAAc;AAAA,QACd;AAAA,UACE,WAAW;AAAA,UACX,sBAAsB,QAAQ,IAAI;AAAA,UAClC,QAAQ,QAAQ;AAAA,UAChB,UAAU,cAAc,YAAY,GAAG;AAAA,QACzC;AAAA,MACF;AACA,YAAM,mBAAmB,IAAI;AAAA,IAC/B,SAAS,WAAW;AAClB,cAAQ,MAAM,oDAAsD,SAAS;AAAA,IAC/E;AAAA,EACF;AAEA,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["resolve","port"]}
@@ -0,0 +1,123 @@
1
+ // src/log-file.ts
2
+ import { chmodSync, closeSync, fstatSync, lstatSync, mkdirSync, openSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync, writeSync } from "fs";
3
+ import { join } from "path";
4
+ import { tmpdir } from "os";
5
+ var DEFAULT_MAX_BYTES = 10 * 1024 * 1024;
6
+ var DEFAULT_RETENTION_MS = 7 * 24 * 36e5;
7
+ function defaultLogDir() {
8
+ return join(tmpdir(), "runeya-logs");
9
+ }
10
+ function installLogFile(opts = {}) {
11
+ const dir = opts.dir ?? defaultLogDir();
12
+ const pid = opts.pid ?? process.pid;
13
+ const maxBytes = opts.maxBytes ?? DEFAULT_MAX_BYTES;
14
+ const logPath = join(dir, `runeya-${pid}.log`);
15
+ ensurePrivateDir(dir);
16
+ pruneOldFiles(dir, opts.retentionMs ?? DEFAULT_RETENTION_MS);
17
+ let fd = openSync(logPath, "a", 384);
18
+ let size = 0;
19
+ try {
20
+ size = fstatSync(fd).size;
21
+ } catch (err) {
22
+ closeSync(fd);
23
+ throw err;
24
+ }
25
+ const closeLog = () => {
26
+ if (fd === null) return;
27
+ const current = fd;
28
+ fd = null;
29
+ try {
30
+ closeSync(current);
31
+ } catch {
32
+ }
33
+ };
34
+ const append = (chunk) => {
35
+ if (fd === null) return;
36
+ try {
37
+ const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
38
+ const bytes = Buffer.byteLength(text);
39
+ if (size > 0 && size + bytes > maxBytes) {
40
+ closeLog();
41
+ try {
42
+ renameSync(logPath, `${logPath}.1`);
43
+ } catch {
44
+ }
45
+ fd = openSync(logPath, "a", 384);
46
+ size = 0;
47
+ }
48
+ writeSync(fd, text);
49
+ size += bytes;
50
+ } catch {
51
+ closeLog();
52
+ }
53
+ };
54
+ const originals = [process.stdout, process.stderr].map((stream) => {
55
+ const original = stream.write.bind(stream);
56
+ stream.write = ((chunk, ...rest) => {
57
+ append(chunk);
58
+ return original(chunk, ...rest);
59
+ });
60
+ return { stream, original };
61
+ });
62
+ const reportCrash = (err, origin) => {
63
+ try {
64
+ let detail;
65
+ try {
66
+ detail = err instanceof Error ? err.stack ?? err.message : String(err);
67
+ } catch {
68
+ detail = "(erreur illisible : sa pile ou son message l\xE8ve \xE0 la lecture)";
69
+ }
70
+ const report = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${origin} \u2014 pid ${pid}
71
+ ${detail}
72
+ `;
73
+ append(`
74
+ ${report}`);
75
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
76
+ writeFileSync(join(dir, `crash-${pid}-${stamp}.log`), `${report}
77
+ Journal complet : ${logPath}
78
+ `, { mode: 384 });
79
+ } catch {
80
+ }
81
+ };
82
+ const monitor = (err, origin) => reportCrash(err, origin);
83
+ process.on("uncaughtExceptionMonitor", monitor);
84
+ return {
85
+ logPath,
86
+ reportCrash,
87
+ uninstall: () => {
88
+ for (const { stream, original } of originals) stream.write = original;
89
+ process.off("uncaughtExceptionMonitor", monitor);
90
+ closeLog();
91
+ }
92
+ };
93
+ }
94
+ function ensurePrivateDir(dir) {
95
+ mkdirSync(dir, { recursive: true, mode: 448 });
96
+ if (typeof process.getuid !== "function") return;
97
+ const st = lstatSync(dir);
98
+ if (!st.isDirectory() || st.uid !== process.getuid()) {
99
+ throw new Error(`${dir} n'est pas un dossier appartenant \xE0 l'utilisateur courant`);
100
+ }
101
+ if ((st.mode & 63) !== 0) chmodSync(dir, 448);
102
+ }
103
+ function pruneOldFiles(dir, retentionMs) {
104
+ const limit = Date.now() - retentionMs;
105
+ let names;
106
+ try {
107
+ names = readdirSync(dir);
108
+ } catch {
109
+ return;
110
+ }
111
+ for (const name of names) {
112
+ if (!/^(runeya|crash)-.*\.log(\.1)?$/.test(name)) continue;
113
+ const path = join(dir, name);
114
+ try {
115
+ if (statSync(path).mtimeMs < limit) unlinkSync(path);
116
+ } catch {
117
+ }
118
+ }
119
+ }
120
+ export {
121
+ installLogFile
122
+ };
123
+ //# sourceMappingURL=log-file-XAEHICMH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/log-file.ts"],"sourcesContent":["/**\n * Journal sur disque de chaque instance, et rapport de crash.\n *\n * Une instance lancée par le bureau, ou relancée par une mise à jour\n * (`appUpdate.restart`, `instance-registry`), démarre en `stdio: 'ignore'` :\n * sa sortie, y compris la pile de l'erreur qui l'a tuée, part dans le vide.\n * Plutôt que de corriger chaque lanceur, le process recopie lui-même sa sortie\n * dans `<tmpdir>/runeya-logs/runeya-<pid>.log` — ce qui couvre toute façon de\n * le démarrer.\n *\n * Écritures synchrones à dessein : un journal qui perd ses dernières lignes au\n * moment du crash manque précisément celles qu'on vient y chercher.\n */\nimport { chmodSync, closeSync, fstatSync, lstatSync, mkdirSync, openSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync, writeSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { tmpdir } from 'node:os';\n\nconst DEFAULT_MAX_BYTES = 10 * 1024 * 1024;\nconst DEFAULT_RETENTION_MS = 7 * 24 * 3600_000;\n\nfunction defaultLogDir(): string {\n return join(tmpdir(), 'runeya-logs');\n}\n\nexport type LogFileHandle = {\n logPath: string;\n reportCrash: (err: unknown, origin: string) => void;\n uninstall: () => void;\n};\n\nexport function installLogFile(opts: {\n dir?: string;\n pid?: number;\n maxBytes?: number;\n retentionMs?: number;\n} = {}): LogFileHandle {\n const dir = opts.dir ?? defaultLogDir();\n const pid = opts.pid ?? process.pid;\n const maxBytes = opts.maxBytes ?? DEFAULT_MAX_BYTES;\n const logPath = join(dir, `runeya-${pid}.log`);\n\n ensurePrivateDir(dir);\n pruneOldFiles(dir, opts.retentionMs ?? DEFAULT_RETENTION_MS);\n\n // Descripteur gardé ouvert : un journal bavard ne rouvre pas le fichier à chaque ligne.\n // `null` une fois le journal abandonné — jamais un numéro déjà fermé : le\n // système le redonne au prochain fichier ouvert, et on écrirait dedans.\n let fd: number | null = openSync(logPath, 'a', 0o600);\n let size = 0;\n try {\n size = fstatSync(fd).size;\n } catch (err) {\n closeSync(fd);\n throw err;\n }\n\n const closeLog = () => {\n if (fd === null) return;\n const current = fd;\n fd = null;\n try { closeSync(current); } catch { /* déjà inutilisable */ }\n };\n\n const append = (chunk: unknown) => {\n if (fd === null) return;\n try {\n const text = typeof chunk === 'string' ? chunk : Buffer.from(chunk as Uint8Array).toString('utf8');\n const bytes = Buffer.byteLength(text);\n if (size > 0 && size + bytes > maxBytes) {\n closeLog();\n // Rotation refusée : on continue dans le même fichier, et on ne réessaie\n // qu'après `maxBytes` de plus plutôt qu'à chaque ligne — d'où `size = 0`\n // dans les deux cas.\n try { renameSync(logPath, `${logPath}.1`); } catch { /* voir ci-dessus */ }\n fd = openSync(logPath, 'a', 0o600);\n size = 0;\n }\n writeSync(fd, text);\n size += bytes;\n } catch {\n // Le journal ne doit jamais être la raison pour laquelle une écriture échoue.\n // Réouverture impossible, disque plein… : on abandonne le journal, pas le process.\n closeLog();\n }\n };\n\n const originals = [process.stdout, process.stderr].map((stream) => {\n const original = stream.write.bind(stream);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n stream.write = ((chunk: any, ...rest: any[]) => {\n append(chunk);\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n return original(chunk, ...rest);\n }) as typeof stream.write;\n return { stream, original };\n });\n\n const reportCrash = (err: unknown, origin: string) => {\n // Appelé pendant que le process meurt : lever ici remplacerait l'erreur\n // d'origine par la nôtre dans ce que Node affiche.\n try {\n let detail: string;\n try {\n detail = err instanceof Error ? (err.stack ?? err.message) : String(err);\n } catch {\n detail = '(erreur illisible : sa pile ou son message lève à la lecture)';\n }\n const report = `[${new Date().toISOString()}] ${origin} — pid ${pid}\\n${detail}\\n`;\n append(`\\n${report}`);\n const stamp = new Date().toISOString().replace(/[:.]/g, '-');\n writeFileSync(join(dir, `crash-${pid}-${stamp}.log`), `${report}\\nJournal complet : ${logPath}\\n`, { mode: 0o600 });\n } catch { /* rien de plus à tenter en train de mourir */ }\n };\n\n // `uncaughtExceptionMonitor` observe sans rattraper : Node garde son\n // comportement (message, code de sortie 1). Il reçoit aussi les promesses\n // rejetées sans gestionnaire, qui tuent le process par défaut.\n const monitor = (err: Error, origin: string) => reportCrash(err, origin);\n process.on('uncaughtExceptionMonitor', monitor);\n\n return {\n logPath,\n reportCrash,\n uninstall: () => {\n for (const { stream, original } of originals) stream.write = original;\n process.off('uncaughtExceptionMonitor', monitor);\n closeLog();\n },\n };\n}\n\n/**\n * Le dossier temporaire est partagé entre utilisateurs sous Unix, et le journal\n * porte la sortie des services — donc potentiellement des secrets. Dossier en\n * 700, et refus d'un dossier créé d'avance par quelqu'un d'autre (qui pourrait\n * y lire, ou y poser un lien vers un fichier à écraser).\n */\nfunction ensurePrivateDir(dir: string): void {\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n if (typeof process.getuid !== 'function') return; // Windows : tmpdir déjà propre à l'utilisateur\n const st = lstatSync(dir);\n if (!st.isDirectory() || st.uid !== process.getuid()) {\n throw new Error(`${dir} n'est pas un dossier appartenant à l'utilisateur courant`);\n }\n if ((st.mode & 0o077) !== 0) chmodSync(dir, 0o700);\n}\n\nfunction pruneOldFiles(dir: string, retentionMs: number): void {\n const limit = Date.now() - retentionMs;\n let names: string[];\n try { names = readdirSync(dir); } catch { return; }\n for (const name of names) {\n if (!/^(runeya|crash)-.*\\.log(\\.1)?$/.test(name)) continue;\n const path = join(dir, name);\n try {\n if (statSync(path).mtimeMs < limit) unlinkSync(path);\n } catch { /* supprimé entre-temps par une autre instance */ }\n }\n}\n"],"mappings":"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","names":[]}
@@ -1147,7 +1147,7 @@ var UpdateCloudApiKeyInput = z20.object({
1147
1147
  scopes: z20.array(CloudApiScopeSchema).min(1).max(10).optional(),
1148
1148
  boards: z20.array(z20.string().max(64)).max(200).nullable().optional()
1149
1149
  });
1150
- var IntegrationProviderSchema = z21.enum(["intercom"]);
1150
+ var IntegrationProviderSchema = z21.enum(["intercom", "hubspot"]);
1151
1151
  var IntegrationConnectionSchema = z21.object({
1152
1152
  id: z21.string().max(128),
1153
1153
  organizationId: z21.string().max(128),
@@ -1545,17 +1545,19 @@ var RUNEYA_CAPABILITIES = [
1545
1545
  },
1546
1546
  {
1547
1547
  name: "kanban_search_cards",
1548
- description: "Search kanban cards by free text, matched against their title, body and comments (accent- and case-insensitive). Archived cards are included. Searches every board of the organization unless boardId narrows it down.",
1548
+ description: 'Search kanban cards by free text, matched against their title, body, comments and the support conversations they follow (title, messages, internal notes, and the names of message authors) \u2014 accent- and case-insensitive. Archived cards are included. Searches every board of the organization unless boardId narrows it down. createdBy narrows to the cards someone created ("les cartes cr\xE9\xE9es par Isabelle"), alone or with a query.',
1549
1549
  route: "kanban.searchCards",
1550
1550
  method: "GET",
1551
1551
  params: [
1552
- { name: "query", description: "Text to look for in card titles, bodies and comments", required: true },
1552
+ { name: "query", description: "Text to look for in card titles, bodies, comments and followed conversations. Optional when createdBy is given.", required: false },
1553
+ { name: "createdBy", description: "Only cards created by this author: a user id, or a name (accent- and case-insensitive, partial match).", required: false },
1553
1554
  { name: "boardId", description: "Restrict the search to this board. Omit to search all boards.", required: false },
1554
1555
  { name: "limit", description: "Maximum number of cards to return (1-100). Default: 25.", required: false },
1555
1556
  { name: "organizationId", description: "Which organization to search. Optional: needed only when the account belongs to several and the error message asks for it.", required: false }
1556
1557
  ],
1557
1558
  buildInput: (p) => ({
1558
- query: p.query,
1559
+ ...p.query ? { query: p.query } : {},
1560
+ ...p.createdBy ? { createdBy: p.createdBy } : {},
1559
1561
  ...p.boardId ? { boardId: p.boardId } : {},
1560
1562
  ...p.limit ? { limit: Number(p.limit) } : {},
1561
1563
  ...p.organizationId ? { organizationId: p.organizationId } : {}