@runeya/runeya 2.0.27 → 2.0.29

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 (204) hide show
  1. package/agent/index.js +23 -1
  2. package/agent/index.js.map +1 -1
  3. package/agent-manager-KGITN4AE.js +7 -0
  4. package/{chunk-Y2R42AXQ.js → chunk-PZHVJHTC.js} +24 -2
  5. package/chunk-PZHVJHTC.js.map +1 -0
  6. package/index.js +1 -1
  7. package/mcp-server/index.js +11 -1
  8. package/mcp-server/index.js.map +1 -1
  9. package/package.json +1 -1
  10. package/{src-RMLLDYCE.js → src-W64XJTN5.js} +345 -208
  11. package/src-W64XJTN5.js.map +1 -0
  12. package/web/assets/{AgentScalarChatInterface.vue-DSPI6Iw-.js → AgentScalarChatInterface.vue-Tid9c7AI.js} +1 -1
  13. package/web/assets/{AgentTerminalPage-COqIEzlq.js → AgentTerminalPage-Bfmc2lJ5.js} +1 -1
  14. package/web/assets/AiChatPage-LbXbHkW7.js +1 -0
  15. package/web/assets/{AppLayout-CduB5PAm.js → AppLayout-Cq3bBVsr.js} +1 -1
  16. package/web/assets/{AuditPage-BKRt4q5p.js → AuditPage-BTk2MLfW.js} +1 -1
  17. package/web/assets/CloudAccountPage--sgdl0BR.js +1 -0
  18. package/web/assets/{CloudAccountPage-BdtMRHqA.js → CloudAccountPage-sObD2Djw.js} +1 -1
  19. package/web/assets/{CloudMessagingPage-CKRgPVNR.js → CloudMessagingPage-DbkITdyZ.js} +1 -1
  20. package/web/assets/{DashboardPage-COXIB50G.js → DashboardPage-CW5p34P0.js} +1 -1
  21. package/web/assets/{EditorIcon-DIdkqlIr.js → EditorIcon-D1wp4885.js} +1 -1
  22. package/web/assets/{EnvironmentForm-94JbjgMc.js → EnvironmentForm-BA-0wfqa.js} +1 -1
  23. package/web/assets/{EnvironmentFormPage-BPFoGLYG.js → EnvironmentFormPage-ePoUSDaO.js} +1 -1
  24. package/web/assets/{EnvironmentListPage-DoWsGpIn.js → EnvironmentListPage-Cgn6NwWL.js} +1 -1
  25. package/web/assets/{EnvironmentSelector-D7xKYoZZ.js → EnvironmentSelector-C8aULVdj.js} +1 -1
  26. package/web/assets/KanbanBoardPage-0TVI8ncW.js +4 -0
  27. package/web/assets/KanbanBoardPage-kpZiPs_o.css +1 -0
  28. package/web/assets/{KanbanListPage-Cgw2ik7W.js → KanbanListPage-B6QRYUG8.js} +1 -1
  29. package/web/assets/{LaunchProjectPage-447Nb6i3.js → LaunchProjectPage-jx4qoZlc.js} +1 -1
  30. package/web/assets/{LaunchServicesPage-CFU9SkfH.js → LaunchServicesPage-C2hQ8iiO.js} +1 -1
  31. package/web/assets/{LogViewer-DlDsNuvU.js → LogViewer-DPQTUsar.js} +1 -1
  32. package/web/assets/{ProcessControls-BvaAllZ_.js → ProcessControls-n_p4xwJz.js} +1 -1
  33. package/web/assets/{ProcessDetailPage-pS2cLCxq.js → ProcessDetailPage-Cm2iN-19.js} +1 -1
  34. package/web/assets/{ProcessMetrics-BLvaSlXi.js → ProcessMetrics-DRxTLIIf.js} +1 -1
  35. package/web/assets/{ProjectDetailPage-Dg74KYBj.js → ProjectDetailPage-DO7pKGee.js} +1 -1
  36. package/web/assets/{ProjectListPage-CIhtK--_.js → ProjectListPage-CljuUt8K.js} +1 -1
  37. package/web/assets/{RandomJobTestPage-34yoDjxB.js → RandomJobTestPage-DqbzEMbv.js} +1 -1
  38. package/web/assets/{ScenarioEditorPage-C0qdLDFR.js → ScenarioEditorPage-DRUK4ep3.js} +1 -1
  39. package/web/assets/{SendToChatDialog-COS28j81.js → SendToChatDialog-C6d_cEQ4.js} +1 -1
  40. package/web/assets/{ServiceControlsBar-BDtQvmNc.js → ServiceControlsBar-BcCBOny2.js} +1 -1
  41. package/web/assets/{ServiceDetailPage-C_drtJlU.js → ServiceDetailPage-B5Z2oyG1.js} +1 -1
  42. package/web/assets/{ServiceFormPage-mD2msQ6o.js → ServiceFormPage-BkRlzAMF.js} +1 -1
  43. package/web/assets/{SettingsPage-C8BPcYEM.js → SettingsPage-CkAaTz8q.js} +4 -4
  44. package/web/assets/{SetupPage-DK2db8Hp.js → SetupPage-DRRqBmwE.js} +1 -1
  45. package/web/assets/{UnlockPage-WopGWLhW.js → UnlockPage-DFHKtpGb.js} +1 -1
  46. package/web/assets/{VariablesTable-D65CafB_.js → VariablesTable-Csi8gzLH.js} +1 -1
  47. package/web/assets/{VersionBadge-CE0ovTHa.js → VersionBadge-C1-aqmd0.js} +1 -1
  48. package/web/assets/WikiPage-amGnOY35.js +1 -0
  49. package/web/assets/{WikiView-CF6FvyCm.js → WikiView-BSFsn874.js} +1 -1
  50. package/web/assets/{add-scalar-classes-CaO2Xice.js → add-scalar-classes-BrZlN4Hz.js} +3 -3
  51. package/web/assets/auth-errors-VpVD7Ji8.js +1 -0
  52. package/web/assets/{autocomplete-CnW5yK7q.js → autocomplete-CqNBR7AV.js} +1 -1
  53. package/web/assets/{basic-shape-diamond.svg-Bkv9ZjHf.js → basic-shape-diamond.svg-pmR0NFra.js} +1 -1
  54. package/web/assets/{basic-shape-hexagon.svg-D20uJxmK.js → basic-shape-hexagon.svg-DoFRZCyQ.js} +1 -1
  55. package/web/assets/{basic-shape-primary-circle-ellipse-round.svg-B5XhKGTG.js → basic-shape-primary-circle-ellipse-round.svg-CPjLQmZx.js} +1 -1
  56. package/web/assets/{basic-shape-primary-square-rectangle.svg-BWQZbeJS.js → basic-shape-primary-square-rectangle.svg-DcMAxrju.js} +1 -1
  57. package/web/assets/{basic-shape-shield.svg-Cas8taBL.js → basic-shape-shield.svg-Dmg9h6Ld.js} +1 -1
  58. package/web/assets/{browser-CKAGCYBM.js → browser-C6RUDE7s.js} +1 -1
  59. package/web/assets/{browser-ZjFgFnVC.js → browser-DfiNANMf.js} +1 -1
  60. package/web/assets/{card-C20l4eFB.js → card-BtNd-O08.js} +1 -1
  61. package/web/assets/{checkbox-DfnQXBty.js → checkbox-CCOdP3PH.js} +1 -1
  62. package/web/assets/{chip-BJLSl2tN.js → chip-CKD4ZA_K.js} +1 -1
  63. package/web/assets/{client-CiZKwix4.js → client-DUaS1tvD.js} +1 -1
  64. package/web/assets/{cloud-chat.store-D-s33s91.js → cloud-chat.store-Do2pLXa6.js} +1 -1
  65. package/web/assets/cloud-client-DkNqusEt.js +1 -0
  66. package/web/assets/{column-Ce2OMgI5.js → column-EYuEVcRt.js} +1 -1
  67. package/web/assets/{computer-device-desktop-monitor.svg-C1wBG8Sy.js → computer-device-desktop-monitor.svg-C8qLTM16.js} +1 -1
  68. package/web/assets/{computer-device-desktop.svg-CyY6f6_9.js → computer-device-desktop.svg-BwIQxUgG.js} +1 -1
  69. package/web/assets/{computer-device-laptop.svg-BPNvNYfT.js → computer-device-laptop.svg-je8g4h4s.js} +1 -1
  70. package/web/assets/{computer-device-mobile-phone-android-samsung-back.svg-DbltFZte.js → computer-device-mobile-phone-android-samsung-back.svg-DXuOmvmg.js} +1 -1
  71. package/web/assets/{computer-device-mobile-phone-android-samsung.svg-CrLSCe_x.js → computer-device-mobile-phone-android-samsung.svg-Dvck__2L.js} +1 -1
  72. package/web/assets/{computer-device-mobile-phone-iphone-x-back.svg-BY19Nult.js → computer-device-mobile-phone-iphone-x-back.svg-BRzKNDWY.js} +1 -1
  73. package/web/assets/{computer-device-mobile-phone-iphone-x.svg-H7FI65UW.js → computer-device-mobile-phone-iphone-x.svg-DwKt9Eia.js} +1 -1
  74. package/web/assets/{computer-device-mobile-tablet-touch.svg-Cmx8jUA5.js → computer-device-mobile-tablet-touch.svg-B65iLEZR.js} +1 -1
  75. package/web/assets/{computer-device-mobile-tablet.svg-C-ij0kaB.js → computer-device-mobile-tablet.svg-BbUYpqRa.js} +1 -1
  76. package/web/assets/{computer-device-network-ethernet-cat6.svg-BxWINH6l.js → computer-device-network-ethernet-cat6.svg-TVQFk_lM.js} +1 -1
  77. package/web/assets/{computer-device-network-lan-www.svg-BSgN4bQe.js → computer-device-network-lan-www.svg-D9wNL1d9.js} +1 -1
  78. package/web/assets/{computer-device-network-wifi-connection.svg-9-Af1cyW.js → computer-device-network-wifi-connection.svg-B3l3vDCq.js} +1 -1
  79. package/web/assets/{computer-device-network-wifi-router.svg-PGbsNleo.js → computer-device-network-wifi-router.svg-CfJjWVyH.js} +1 -1
  80. package/web/assets/{cssMode-BXCNwJJl.js → cssMode-CT0VgZiM.js} +1 -1
  81. package/web/assets/{divider-D15eSJOf.js → divider-BAtaraJT.js} +1 -1
  82. package/web/assets/{ecology-science-erlenmeyer-flask.svg-D1TcAurA.js → ecology-science-erlenmeyer-flask.svg-DCqj3wuN.js} +1 -1
  83. package/web/assets/{fieldset-DpjemOKg.js → fieldset-Bmfuw85t.js} +1 -1
  84. package/web/assets/{freemarker2-vGwcFsrU.js → freemarker2-DcS0oW9c.js} +1 -1
  85. package/web/assets/{handlebars-CgczpBKv.js → handlebars-EYnEyJJj.js} +1 -1
  86. package/web/assets/{html-BFGITMD0.js → html-Cy3hBLsT.js} +1 -1
  87. package/web/assets/{htmlMode-B3rE7DS5.js → htmlMode-7YMQ7tB-.js} +1 -1
  88. package/web/assets/{image-flash-lightning.svg-xzLxZzA4.js → image-flash-lightning.svg-D6x2pDl8.js} +1 -1
  89. package/web/assets/{image-picture-flower.svg-pnrEOEKg.js → image-picture-flower.svg-qlZATukV.js} +1 -1
  90. package/web/assets/{index-gKo3WNkm.css → index-DtsVLZzz.css} +1 -1
  91. package/web/assets/{index-pgDYqJbK.js → index-ZFdBtCGG.js} +6 -6
  92. package/web/assets/{interface-alert-exclamation-diamond.svg-CI092Np8.js → interface-alert-exclamation-diamond.svg-Bt2YgBdz.js} +1 -1
  93. package/web/assets/{interface-alert-exclamation-triangle-warning.svg-C4mqQzrp.js → interface-alert-exclamation-triangle-warning.svg-BL6E9tsG.js} +1 -1
  94. package/web/assets/{interface-alert-information-circle.svg-BT4vnvBw.js → interface-alert-information-circle.svg-C2mU-Jrm.js} +1 -1
  95. package/web/assets/{interface-award-crown.svg-CRPOUMXT.js → interface-award-crown.svg-C_908siC.js} +1 -1
  96. package/web/assets/{interface-bookmark.svg-DTAetZsa.js → interface-bookmark-tag.svg-CdwmwagL.js} +1 -1
  97. package/web/assets/{interface-bookmark-tag.svg-DPVkmndo.js → interface-bookmark.svg-DiGis0Pq.js} +1 -1
  98. package/web/assets/{interface-calendar-date-one.svg-6dLyIX8s.js → interface-calendar-date-one.svg-DZJTVsRH.js} +1 -1
  99. package/web/assets/{interface-content-book-open-pages.svg-6XF6zc4V.js → interface-content-book-open-pages.svg-BWjmGbGN.js} +1 -1
  100. package/web/assets/{interface-content-book-page.svg-bdqhi6K9.js → interface-content-book-page.svg-HTArRhqF.js} +1 -1
  101. package/web/assets/{interface-content-file.svg-1G5vO-Bf.js → interface-content-file.svg-CEK-6Dir.js} +1 -1
  102. package/web/assets/{interface-content-folder.svg-D850sLcG.js → interface-content-folder.svg-CvFy9IIg.js} +1 -1
  103. package/web/assets/interface-content-folder.svg-D9a2SnRw.js +1 -0
  104. package/web/assets/{interface-copy-clipboard.svg-BccvE8VI.js → interface-copy-clipboard.svg-CA9ObKG2.js} +1 -1
  105. package/web/assets/{interface-edit-attachment.svg-Ce4FGCOQ.js → interface-edit-attachment.svg-BuZlaKV6.js} +1 -1
  106. package/web/assets/{interface-edit-binocular.svg-DPRn5hZu.js → interface-edit-binocular.svg-Bu-T_qRU.js} +1 -1
  107. package/web/assets/{interface-edit-magic-wand.svg-DXe8x6h5.js → interface-edit-magic-wand.svg-ZyOEyv4O.js} +1 -1
  108. package/web/assets/{interface-edit-tool-paint-roller.svg-DiSg_nu0.js → interface-edit-tool-paint-roller.svg-DBwhOf_F.js} +1 -1
  109. package/web/assets/{interface-edit-tool-pencil.svg-CJ7nntID.js → interface-edit-tool-pencil.svg-CMKU5EZ0.js} +1 -1
  110. package/web/assets/{interface-favorite-award.svg-Bp7EXD5O.js → interface-favorite-award.svg-Djfprlrh.js} +1 -1
  111. package/web/assets/{interface-favorite-flag.svg-X3mutHkA.js → interface-favorite-flag.svg-MM0Rm1Rf.js} +1 -1
  112. package/web/assets/{interface-favorite-heart.svg-BZN7wndr.js → interface-favorite-heart.svg-8eXxbVlD.js} +1 -1
  113. package/web/assets/{interface-favorite-star.svg-DLgGRGba.js → interface-favorite-star.svg-CYpNa-DM.js} +1 -1
  114. package/web/assets/{interface-favorite-stars-sparkles.svg-B4M9nCgv.js → interface-favorite-stars-sparkles.svg-KYu8S1Mc.js} +1 -1
  115. package/web/assets/{interface-hierarchy-flowchart.svg-CU5Tp_c9.js → interface-hierarchy-flowchart.svg-fr4rLXph.js} +1 -1
  116. package/web/assets/{interface-home-house.svg-B1qI4Bnk.js → interface-home-house.svg-UfcAwTPa.js} +1 -1
  117. package/web/assets/{interface-hyperlink.svg-DDLaWCwm.js → interface-hyperlink.svg-DLpXwEy6.js} +1 -1
  118. package/web/assets/{interface-lighting-brightness.svg-C0XYahxq.js → interface-lighting-brightness.svg-aY4osIqa.js} +1 -1
  119. package/web/assets/{interface-lock-closed.svg-BJGiYphz.js → interface-lock-closed.svg-CiMIugbj.js} +1 -1
  120. package/web/assets/{interface-lock-open-unlock.svg-B9mZbDai.js → interface-lock-open-unlock.svg-d5UkSt1y.js} +1 -1
  121. package/web/assets/{interface-login-key.svg-CLg9rb5N.js → interface-login-key.svg-C7Ml1iaN.js} +1 -1
  122. package/web/assets/{interface-search.svg-C_hyT038.js → interface-search.svg-D8jY9D2U.js} +1 -1
  123. package/web/assets/{interface-setting-cog.svg-CPJEcVaX.js → interface-setting-cog.svg-3DAxFuOM.js} +1 -1
  124. package/web/assets/{interface-share-megaphone-bullhorn.svg-D9mnWTl1.js → interface-share-megaphone-bullhorn.svg-BsbqqS8a.js} +1 -1
  125. package/web/assets/{interface-share-rocket.svg-Cv-mm6Sf.js → interface-share-rocket.svg-C_8HYujm.js} +1 -1
  126. package/web/assets/{interface-share-satellite.svg-KG8vUTu7.js → interface-share-satellite.svg-3O-1mL1W.js} +1 -1
  127. package/web/assets/{interface-share-space-ship.svg-G-gPwAXE.js → interface-share-space-ship.svg-BDge8YMa.js} +1 -1
  128. package/web/assets/{interface-share.svg-DqUCb7Ru.js → interface-share.svg-Fehxvv85.js} +1 -1
  129. package/web/assets/{interface-signal-square.svg-D3hMImVy.js → interface-signal-square.svg-C0c3wlFq.js} +1 -1
  130. package/web/assets/{interface-time-clock-circle.svg-BJygBdct.js → interface-time-clock-circle.svg-Bj3gcDKD.js} +1 -1
  131. package/web/assets/{interface-time-hour-glass.svg-C6VAxVap.js → interface-time-hour-glass.svg-DUim2QDE.js} +1 -1
  132. package/web/assets/{interface-users-multiple.svg-CoxyjUld.js → interface-users-multiple.svg-vooB7JL-.js} +1 -1
  133. package/web/assets/{interface-weather-moon.svg-D-X12JVO.js → interface-weather-moon.svg-BcUz22tg.js} +1 -1
  134. package/web/assets/{javascript-C84J6-4w.js → javascript-xFG-91vE.js} +1 -1
  135. package/web/assets/{jsonMode-C27w1Qms.js → jsonMode-CXRfjDm6.js} +1 -1
  136. package/web/assets/{liquid-DgfNbtcl.js → liquid-DFaP2Us7.js} +1 -1
  137. package/web/assets/{lspLanguageFeatures-C_7i29Bj.js → lspLanguageFeatures-Cj2beqH7.js} +1 -1
  138. package/web/assets/{mail-chat-bubble-square.svg-DkpMmHLK.js → mail-chat-bubble-square.svg-Q5_Wlk-h.js} +1 -1
  139. package/web/assets/{mail-send-email-paper-airplane.svg-D6NabH2T.js → mail-send-email-paper-airplane.svg-CjqQ7405.js} +1 -1
  140. package/web/assets/{mail-send-envelope.svg-BbPAyASY.js → mail-send-envelope.svg-MH4dR__N.js} +1 -1
  141. package/web/assets/{mdx-BCuKGABs.js → mdx-DDj1td2N.js} +1 -1
  142. package/web/assets/{message-CoRxRh0u.js → message-Dgvz1ZaX.js} +1 -1
  143. package/web/assets/{minus-5Bqt5ofK.js → minus-Hsxq04kB.js} +1 -1
  144. package/web/assets/modal-BCbrFXdF.js +1 -0
  145. package/web/assets/{modal-DwRiR841.js → modal-pAb11yGJ.js} +1 -1
  146. package/web/assets/{money-cashier-receipt.svg-VmdcIGRH.js → money-cashier-receipt.svg-W10QYjo6.js} +1 -1
  147. package/web/assets/{money-currency-dollar-pay.svg-BmWJQEO0.js → money-currency-dollar-pay.svg-jlzMCQus.js} +1 -1
  148. package/web/assets/{money-graph-arrow-increase.svg-D0-SVIVY.js → money-graph-arrow-increase.svg-DjiVgX3u.js} +1 -1
  149. package/web/assets/{money-graph-bar-chart-increase.svg-DTdIZ1yD.js → money-graph-bar-chart-increase.svg-BetO29r-.js} +1 -1
  150. package/web/assets/{multiselect-yuMT5FAw.js → multiselect-DAvUHXe1.js} +1 -1
  151. package/web/assets/{nature-ecology-leaf.svg-ftrud9Ee.js → nature-ecology-leaf.svg-68pXd-Nz.js} +1 -1
  152. package/web/assets/{password-Cw64wBy9.js → password-fBZDwzDL.js} +1 -1
  153. package/web/assets/{phone-telephone.svg-BukpdVe6.js → phone-telephone.svg-5-34SVF9.js} +1 -1
  154. package/web/assets/{plus-DUWBjv5i.js → plus-BybvY8Jc.js} +1 -1
  155. package/web/assets/process.store-e8DffExf.js +1 -0
  156. package/web/assets/{programming-bug.svg-BCduWuVf.js → programming-bug.svg-2bQdYECv.js} +1 -1
  157. package/web/assets/{programming-cloud.svg-BkuU9JZc.js → programming-cloud.svg-DZ2V0eJT.js} +1 -1
  158. package/web/assets/{programming-computer-database-server.svg-Dz36JAv6.js → programming-computer-database-server.svg-hDSuUD9Z.js} +1 -1
  159. package/web/assets/{programming-computer-database.svg-CgLUxdNj.js → programming-computer-database.svg-BySVZkMc.js} +1 -1
  160. package/web/assets/{programming-module-four-layout.svg-CUcqFbuN.js → programming-module-four-layout.svg-CKIgCJwc.js} +1 -1
  161. package/web/assets/{programming-module-three.svg-Drh_K9UP.js → programming-module-three.svg-DiWesNwV.js} +1 -1
  162. package/web/assets/{programming-module.svg-DpmnuolN.js → programming-module.svg-DU0zOvVK.js} +1 -1
  163. package/web/assets/{programming-script-code.svg-aLlzlZCt.js → programming-script-code.svg-DfSmaPH7.js} +1 -1
  164. package/web/assets/{python-Ch8jlEn0.js → python-C25OjXtn.js} +1 -1
  165. package/web/assets/{radiobutton-DG85qUd5.js → radiobutton-K1Libu7g.js} +1 -1
  166. package/web/assets/{razor-CUll3FMU.js → razor-DrRHsFwp.js} +1 -1
  167. package/web/assets/router-BQjVOlyD.js +1 -0
  168. package/web/assets/{settings.store-qZCJj_4D.js → settings.store-BCaFk23O.js} +1 -1
  169. package/web/assets/{shopping-cart.svg-yEPUTw_R.js → shopping-cart.svg-NMibYZ0k.js} +1 -1
  170. package/web/assets/{shopping-gift-present.svg-DaqJhwWl.js → shopping-gift-present.svg-dqvSn838.js} +1 -1
  171. package/web/assets/{shopping-shipping-box-parcel-package.svg-DV5YYoia.js → shopping-shipping-box-parcel-package.svg-CKYzVuYA.js} +1 -1
  172. package/web/assets/{src-CZvpZlaR.js → src-EWso2a1V.js} +1 -1
  173. package/web/assets/{src-mw3qp820.js → src-_-zc3-Cp.js} +1 -1
  174. package/web/assets/{tabpanel-Gp2kHree.js → tabpanel-BWhVX5cc.js} +1 -1
  175. package/web/assets/{tag-new-circle.svg-BHRX-TYk.js → tag-new-circle.svg-JFLA4g9w.js} +1 -1
  176. package/web/assets/{travel-map-earth-globe.svg-CmrszNdx.js → travel-map-earth-globe.svg-DdQN4a7G.js} +1 -1
  177. package/web/assets/trpc-BZfo9Cw2.js +1 -0
  178. package/web/assets/{tsMode-CjoWwALS.js → tsMode-Cii9XdsR.js} +1 -1
  179. package/web/assets/{typescript-BpONFNP8.js → typescript-zoLusRa0.js} +1 -1
  180. package/web/assets/useAiChatDrawer-CHmnbpKl.js +1 -0
  181. package/web/assets/{useCloudOrg-BEGIZ5Sw.css → useCloudOrg-CHCwXrRm.css} +1 -1
  182. package/web/assets/useCloudOrg-JZ6DFHrG.js +1 -0
  183. package/web/assets/{xml-CmjkohVQ.js → xml-BhaXJtQn.js} +1 -1
  184. package/web/assets/{yaml-CKv_rPtX.js → yaml-CDzjwB43.js} +1 -1
  185. package/web/favicon.svg +5 -0
  186. package/web/index.html +3 -3
  187. package/agent-manager-2P4THUVA.js +0 -7
  188. package/chunk-Y2R42AXQ.js.map +0 -1
  189. package/src-RMLLDYCE.js.map +0 -1
  190. package/web/assets/AiChatPage-CFc7KbNG.js +0 -1
  191. package/web/assets/CloudAccountPage-HTRjahHK.js +0 -1
  192. package/web/assets/KanbanBoardPage-BDzDCbzp.css +0 -1
  193. package/web/assets/KanbanBoardPage-Ca7RBQtm.js +0 -4
  194. package/web/assets/WikiPage-BEAjl3sE.js +0 -1
  195. package/web/assets/auth-errors-ePzxFx8g.js +0 -1
  196. package/web/assets/cloud-client-BNiN622M.js +0 -1
  197. package/web/assets/interface-content-folder.svg-CPgJrZEE.js +0 -1
  198. package/web/assets/modal-WUB9U4Dm.js +0 -1
  199. package/web/assets/process.store-f7QERgRI.js +0 -1
  200. package/web/assets/router-Ckd39-Uf.js +0 -1
  201. package/web/assets/trpc-C-XGFhkf.js +0 -1
  202. package/web/assets/useAiChatDrawer-DTJO3AGB.js +0 -1
  203. package/web/assets/useCloudOrg-Bbpui8U3.js +0 -1
  204. /package/{agent-manager-2P4THUVA.js.map → agent-manager-KGITN4AE.js.map} +0 -0
@@ -58,7 +58,7 @@ import {
58
58
  stableEncryptValue,
59
59
  traefikManager,
60
60
  writeEntity
61
- } from "./chunk-Y2R42AXQ.js";
61
+ } from "./chunk-PZHVJHTC.js";
62
62
 
63
63
  // ../server/src/create-server.ts
64
64
  import express from "express";
@@ -3440,7 +3440,7 @@ var RUNEYA_CAPABILITIES = [
3440
3440
  },
3441
3441
  {
3442
3442
  name: "kanban_get_board",
3443
- description: "Read one kanban board: its columns, and the cards in each (id, title, markdown body, assignees, comment count). Use the exact column names it returns when moving or adding a card.",
3443
+ description: "Read one kanban board: its columns, and the cards in each (id, title, markdown body, assignees, comment count, and attachment metadata \u2014 use kanban_download_attachment to fetch the bytes of a file). Use the exact column names it returns when moving or adding a card.",
3444
3444
  route: "kanban.getBoard",
3445
3445
  method: "GET",
3446
3446
  params: [
@@ -3464,6 +3464,16 @@ var RUNEYA_CAPABILITIES = [
3464
3464
  ...p.limit ? { limit: Number(p.limit) } : {}
3465
3465
  })
3466
3466
  },
3467
+ {
3468
+ name: "kanban_download_attachment",
3469
+ description: "Download a kanban card attachment (image, PDF, any file) onto this machine and return its local path, so it can be opened with file-reading tools. Attachment ids come from the card context or from kanban_get_board.",
3470
+ route: "kanban.downloadAttachment",
3471
+ method: "POST",
3472
+ params: [
3473
+ { name: "attachmentId", description: "The attachment ID, as listed on the card", required: true }
3474
+ ],
3475
+ buildInput: (p) => ({ attachmentId: p.attachmentId })
3476
+ },
3467
3477
  {
3468
3478
  name: "kanban_move_card",
3469
3479
  description: "Move a kanban card to another column. Use the exact column name.",
@@ -5571,7 +5581,8 @@ async function cloudFetch(path, init = {}) {
5571
5581
  ...init.body !== void 0 ? { "Content-Type": "application/json" } : {}
5572
5582
  },
5573
5583
  ...init.body !== void 0 ? { body: JSON.stringify(init.body) } : {},
5574
- signal: AbortSignal.timeout(15e3)
5584
+ // 15s suits a JSON call; attachment downloads pass a longer budget.
5585
+ signal: AbortSignal.timeout(init.timeoutMs ?? 15e3)
5575
5586
  });
5576
5587
  }
5577
5588
  var PROXY_PREFIXES = ["/organization/", "/project/", "/chat/", "/kanban/", "/user/prefs"];
@@ -5676,10 +5687,54 @@ var KanbanStore = class {
5676
5687
  const res = await callCloud(`/kanban/board/list${query}`);
5677
5688
  return res.data?.boards ?? [];
5678
5689
  }
5679
- async get(id) {
5680
- const res = await callCloud(`/kanban/board/get?id=${encodeURIComponent(id)}`);
5690
+ /**
5691
+ * Un tableau. Sans les journaux de ses cartes par défaut : c'est la moitié
5692
+ * lourde du document, et presque aucun appelant n'en a besoin — un agent qui
5693
+ * liste des cartes ne lit pas les commentaires. `withHistory` les redemande
5694
+ * pour les rares cas qui les veulent tous d'un coup.
5695
+ */
5696
+ async get(id, opts = {}) {
5697
+ const query = `?id=${encodeURIComponent(id)}${opts.withHistory ? "&withHistory=true" : ""}`;
5698
+ const res = await callCloud(`/kanban/board/get${query}`);
5681
5699
  return res.data?.board ?? null;
5682
5700
  }
5701
+ /** Le journal d'une seule carte — ce que le contexte d'un agent demande. */
5702
+ async cardHistory(boardId, cardId) {
5703
+ const res = await callCloud(
5704
+ `/kanban/card/history?boardId=${encodeURIComponent(boardId)}&cardId=${encodeURIComponent(cardId)}`
5705
+ );
5706
+ return res.data?.history ?? [];
5707
+ }
5708
+ /**
5709
+ * Commenter une carte, sans réécrire le tableau.
5710
+ *
5711
+ * C'est le geste que l'IA répète le plus, et souvent avec de longs textes :
5712
+ * le faire passer par une sauvegarde de tableau faisait transiter tout le
5713
+ * graphe de cartes à chaque phrase.
5714
+ */
5715
+ async addComment(boardId, cardId, detail, conversationId) {
5716
+ const res = await callCloud("/kanban/card/comment/add", {
5717
+ method: "POST",
5718
+ body: { boardId, cardId, detail, author: "ai", ...conversationId ? { conversationId } : {} }
5719
+ });
5720
+ return res.ok;
5721
+ }
5722
+ /** Poser une entrée de journal non-commentaire (une conversation qui s'ouvre). */
5723
+ async addCardEvent(boardId, cardId, type, detail) {
5724
+ const res = await callCloud("/kanban/card/event/add", {
5725
+ method: "POST",
5726
+ body: { boardId, cardId, type, detail }
5727
+ });
5728
+ return res.ok;
5729
+ }
5730
+ /** Déplacer une carte, sans réécrire le tableau. */
5731
+ async moveCard(boardId, cardId, toColumnId) {
5732
+ const res = await callCloud("/kanban/card/move", {
5733
+ method: "POST",
5734
+ body: { boardId, cardId, toColumnId }
5735
+ });
5736
+ return res.ok;
5737
+ }
5683
5738
  async create(input) {
5684
5739
  const organizationId = await resolveOrganizationId();
5685
5740
  if (!organizationId) return null;
@@ -5728,17 +5783,27 @@ async function executeKanbanCommands(boardId, cardId, commands, conversationId)
5728
5783
  return;
5729
5784
  }
5730
5785
  }
5786
+ let pendingBoardWrite = false;
5731
5787
  for (const cmd of commands) {
5732
5788
  if (cmd.type === "move_card" && cmd.columnTitle) {
5733
- const moved = moveCard(board, cardId, cmd.columnTitle);
5734
- if (!moved) console.warn(`[kanban-commands] move_card failed: card=${cardId} target="${cmd.columnTitle}"`);
5789
+ const target = board.columns.find(
5790
+ (c) => c.title.toLowerCase() === cmd.columnTitle.toLowerCase()
5791
+ );
5792
+ if (!target) {
5793
+ console.warn(`[kanban-commands] Target column "${cmd.columnTitle}" not found. Available: ${board.columns.map((c) => c.title).join(", ")}`);
5794
+ continue;
5795
+ }
5796
+ const ok = await kanbanStore.moveCard(board.id, cardId, target.id);
5797
+ if (!ok) console.warn(`[kanban-commands] move_card failed: card=${cardId} target="${cmd.columnTitle}"`);
5735
5798
  } else if (cmd.type === "add_comment" && cmd.comment) {
5736
- addComment(board, cardId, cmd.comment, conversationId);
5799
+ const ok = await kanbanStore.addComment(board.id, cardId, cmd.comment, conversationId);
5800
+ if (!ok) console.warn(`[kanban-commands] add_comment failed: card=${cardId}`);
5737
5801
  } else if (cmd.type === "add_card" && cmd.columnTitle && cmd.cardTitle) {
5738
5802
  addCardToColumn(board, cmd.columnTitle, cmd.cardTitle, cmd.cardContent);
5803
+ pendingBoardWrite = true;
5739
5804
  }
5740
5805
  }
5741
- await kanbanStore.update({ id: board.id, columns: board.columns });
5806
+ if (pendingBoardWrite) await kanbanStore.update({ id: board.id, columns: board.columns });
5742
5807
  }
5743
5808
  async function executeKanbanBoardCommands(boardId, commands) {
5744
5809
  if (commands.length === 0) return;
@@ -5751,43 +5816,6 @@ async function executeKanbanBoardCommands(boardId, commands) {
5751
5816
  }
5752
5817
  await kanbanStore.update({ id: board.id, columns: board.columns });
5753
5818
  }
5754
- function moveCard(board, cardId, targetColTitle) {
5755
- let sourceCol = "";
5756
- let card = null;
5757
- let sourceColIdx = -1;
5758
- let cardIdx = -1;
5759
- for (let ci = 0; ci < board.columns.length; ci++) {
5760
- const col = board.columns[ci];
5761
- const idx = col.cards.findIndex((c) => c.id === cardId);
5762
- if (idx !== -1) {
5763
- sourceCol = col.title;
5764
- card = col.cards[idx];
5765
- sourceColIdx = ci;
5766
- cardIdx = idx;
5767
- break;
5768
- }
5769
- }
5770
- if (!card || sourceColIdx === -1) return false;
5771
- const targetCol = board.columns.find(
5772
- (c) => c.title.toLowerCase() === targetColTitle.toLowerCase()
5773
- );
5774
- if (!targetCol) {
5775
- console.warn(`[kanban-commands] Target column "${targetColTitle}" not found. Available: ${board.columns.map((c) => c.title).join(", ")}`);
5776
- return false;
5777
- }
5778
- if (targetCol.id === board.columns[sourceColIdx].id) return true;
5779
- board.columns[sourceColIdx].cards.splice(cardIdx, 1);
5780
- card.order = targetCol.cards.length;
5781
- card.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
5782
- card.history = [...card.history ?? [], {
5783
- type: "moved",
5784
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
5785
- detail: `"${sourceCol}" \u2192 "${targetCol.title}"`,
5786
- author: "ai"
5787
- }];
5788
- targetCol.cards.push(card);
5789
- return true;
5790
- }
5791
5819
  function addCardToColumn(board, columnTitle, cardTitle, cardContent) {
5792
5820
  const col = board.columns.find((c) => c.title.toLowerCase() === columnTitle.toLowerCase());
5793
5821
  if (!col) return;
@@ -5804,23 +5832,12 @@ function addCardToColumn(board, columnTitle, cardTitle, cardContent) {
5804
5832
  };
5805
5833
  col.cards.push(card);
5806
5834
  }
5807
- function addComment(board, cardId, comment, conversationId) {
5808
- for (const col of board.columns) {
5809
- const card = col.cards.find((c) => c.id === cardId);
5810
- if (card) {
5811
- card.history = [...card.history ?? [], {
5812
- type: "comment",
5813
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
5814
- detail: comment,
5815
- author: "ai",
5816
- ...conversationId ? { conversationId } : {}
5817
- }];
5818
- card.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
5819
- return;
5820
- }
5821
- }
5835
+ function formatSize(bytes) {
5836
+ if (bytes < 1024) return `${bytes} o`;
5837
+ if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} Ko`;
5838
+ return `${(bytes / (1024 * 1024)).toFixed(1).replace(".", ",")} Mo`;
5822
5839
  }
5823
- function generateKanbanSystemPrompt(board, cardId) {
5840
+ function generateKanbanSystemPrompt(board, cardId, history) {
5824
5841
  let currentColTitle = "";
5825
5842
  let card = null;
5826
5843
  for (const col of board.columns) {
@@ -5850,16 +5867,33 @@ function generateKanbanSystemPrompt(board, cardId) {
5850
5867
  }
5851
5868
  lines.push("");
5852
5869
  if (card) {
5853
- const comments = (card.history ?? []).filter((e) => e.type === "comment");
5870
+ const events = history ?? card.history ?? [];
5871
+ const comments = events.filter((e) => e.type === "comment");
5854
5872
  if (comments.length > 0) {
5855
5873
  lines.push("### Commentaires existants sur cette carte :");
5856
5874
  lines.push("");
5857
5875
  for (const c of comments.slice(-20)) {
5858
5876
  const who = c.author === "ai" ? "AI" : "Utilisateur";
5859
5877
  const date = new Date(c.timestamp).toLocaleString("fr-FR", { day: "numeric", month: "short", hour: "2-digit", minute: "2-digit" });
5860
- lines.push(`- **${who}** (${date}) : ${c.detail}`);
5878
+ const files = (c.attachments ?? []).map((f) => `\`${f.id}\` ${f.name}`).join(", ");
5879
+ lines.push(`- **${who}** (${date}) : ${c.detail}${files ? ` \u2014 pi\xE8ces jointes : ${files}` : ""}`);
5880
+ }
5881
+ lines.push("");
5882
+ }
5883
+ }
5884
+ if (card) {
5885
+ const files = card.attachments ?? [];
5886
+ const commentFiles = (history ?? card.history ?? []).flatMap((e) => e.attachments ?? []);
5887
+ const all = [...files, ...commentFiles];
5888
+ if (all.length > 0) {
5889
+ lines.push(`### Pi\xE8ces jointes disponibles (${all.length})`);
5890
+ lines.push("");
5891
+ for (const f of all) {
5892
+ lines.push(`- \`${f.id}\` \u2014 ${f.name} (${f.contentType}, ${formatSize(f.size)})`);
5861
5893
  }
5862
5894
  lines.push("");
5895
+ lines.push("> Ces fichiers ne sont **pas** dans ce prompt. Appelle `kanban_download_attachment(attachmentId)` pour en r\xE9cup\xE9rer un sur le disque, puis ouvre le chemin renvoy\xE9 avec tes outils de lecture de fichiers.");
5896
+ lines.push("");
5863
5897
  }
5864
5898
  }
5865
5899
  lines.push("### Outils Kanban disponibles");
@@ -5870,6 +5904,7 @@ function generateKanbanSystemPrompt(board, cardId) {
5870
5904
  lines.push("Tu disposes des outils suivants pour interagir avec le board :");
5871
5905
  lines.push("- `kanban_move_card(boardId, cardId, targetColumn)` \u2014 D\xE9placer la carte vers une autre colonne");
5872
5906
  lines.push("- `kanban_add_comment(boardId, cardId, comment)` \u2014 Ajouter un commentaire sur la carte");
5907
+ lines.push("- `kanban_download_attachment(attachmentId)` \u2014 T\xE9l\xE9charger une pi\xE8ce jointe et obtenir son chemin local");
5873
5908
  lines.push("");
5874
5909
  lines.push("### OBLIGATOIRE \u2014 D\xE9cision Kanban");
5875
5910
  lines.push("");
@@ -6096,7 +6131,7 @@ function tailTranscript(opts) {
6096
6131
 
6097
6132
  // ../server/src/services/ai-runners/claude-pty-runner.ts
6098
6133
  async function getAgentManager() {
6099
- const { agentManager: agentManager2 } = await import("./agent-manager-2P4THUVA.js");
6134
+ const { agentManager: agentManager2 } = await import("./agent-manager-KGITN4AE.js");
6100
6135
  return agentManager2;
6101
6136
  }
6102
6137
  function buildPtyArgs(params, sessionId, opts) {
@@ -6749,7 +6784,7 @@ async function shutdownCodexAppServer() {
6749
6784
  }
6750
6785
  }
6751
6786
  async function getAgentManager2() {
6752
- const { agentManager: agentManager2 } = await import("./agent-manager-2P4THUVA.js");
6787
+ const { agentManager: agentManager2 } = await import("./agent-manager-KGITN4AE.js");
6753
6788
  return agentManager2;
6754
6789
  }
6755
6790
  function parseRuneyaCurlCommand(command) {
@@ -7433,7 +7468,13 @@ async function buildCliSystemContext(conv, jwt) {
7433
7468
  if (conv?.kanbanBoardId) {
7434
7469
  const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);
7435
7470
  if (kanbanBoard) {
7436
- systemContext += "\n\n" + (conv.kanbanCardId ? generateKanbanSystemPrompt(kanbanBoard, conv.kanbanCardId) : generateKanbanPopulatePrompt(kanbanBoard));
7471
+ systemContext += "\n\n" + (conv.kanbanCardId ? generateKanbanSystemPrompt(
7472
+ kanbanBoard,
7473
+ conv.kanbanCardId,
7474
+ // Le journal ne vient plus avec le tableau : le contexte de l'agent
7475
+ // le demande pour la seule carte qui le concerne.
7476
+ await kanbanStore.cardHistory(kanbanBoard.id, conv.kanbanCardId)
7477
+ ) : generateKanbanPopulatePrompt(kanbanBoard));
7437
7478
  }
7438
7479
  }
7439
7480
  return systemContext;
@@ -7834,7 +7875,13 @@ ${input.prompt}` : input.prompt;
7834
7875
  if (conv.kanbanBoardId) {
7835
7876
  const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);
7836
7877
  if (kanbanBoard) {
7837
- systemContext += "\n\n" + (conv.kanbanCardId ? generateKanbanSystemPrompt(kanbanBoard, conv.kanbanCardId) : generateKanbanPopulatePrompt(kanbanBoard));
7878
+ systemContext += "\n\n" + (conv.kanbanCardId ? generateKanbanSystemPrompt(
7879
+ kanbanBoard,
7880
+ conv.kanbanCardId,
7881
+ // Le journal ne vient plus avec le tableau : le contexte de l'agent
7882
+ // le demande pour la seule carte qui le concerne.
7883
+ await kanbanStore.cardHistory(kanbanBoard.id, conv.kanbanCardId)
7884
+ ) : generateKanbanPopulatePrompt(kanbanBoard));
7838
7885
  }
7839
7886
  }
7840
7887
  const mcpServerPath = fileURLToPath(new URL("../mcp-server/index.js", import.meta.url));
@@ -7949,7 +7996,13 @@ ${input.prompt}` : input.prompt;
7949
7996
  if (conv.kanbanBoardId) {
7950
7997
  const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);
7951
7998
  if (kanbanBoard) {
7952
- systemContext += "\n\n" + (conv.kanbanCardId ? generateKanbanSystemPrompt(kanbanBoard, conv.kanbanCardId) : generateKanbanPopulatePrompt(kanbanBoard));
7999
+ systemContext += "\n\n" + (conv.kanbanCardId ? generateKanbanSystemPrompt(
8000
+ kanbanBoard,
8001
+ conv.kanbanCardId,
8002
+ // Le journal ne vient plus avec le tableau : le contexte de l'agent
8003
+ // le demande pour la seule carte qui le concerne.
8004
+ await kanbanStore.cardHistory(kanbanBoard.id, conv.kanbanCardId)
8005
+ ) : generateKanbanPopulatePrompt(kanbanBoard));
7953
8006
  }
7954
8007
  }
7955
8008
  const resolvedImages = input.imageIds && input.imageIds.length > 0 ? await resolveImagesToBase64(input.imageIds.map((id) => ({ imageId: id, mimeType: "" })), input.conversationId) : [];
@@ -8042,7 +8095,13 @@ ${input.prompt}` : input.prompt;
8042
8095
  if (conv && conv.kanbanBoardId) {
8043
8096
  const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);
8044
8097
  if (kanbanBoard) {
8045
- system += "\n\n" + (conv.kanbanCardId ? generateKanbanSystemPrompt(kanbanBoard, conv.kanbanCardId) : generateKanbanPopulatePrompt(kanbanBoard));
8098
+ system += "\n\n" + (conv.kanbanCardId ? generateKanbanSystemPrompt(
8099
+ kanbanBoard,
8100
+ conv.kanbanCardId,
8101
+ // Le journal ne vient plus avec le tableau : le contexte de l'agent
8102
+ // le demande pour la seule carte qui le concerne.
8103
+ await kanbanStore.cardHistory(kanbanBoard.id, conv.kanbanCardId)
8104
+ ) : generateKanbanPopulatePrompt(kanbanBoard));
8046
8105
  }
8047
8106
  }
8048
8107
  const resolvedImages = input.imageIds && input.imageIds.length > 0 ? await resolveImagesToBase64(input.imageIds.map((id) => ({ imageId: id, mimeType: "" })), input.conversationId) : [];
@@ -10736,19 +10795,8 @@ var KanbanQueueService = class extends EventEmitter4 {
10736
10795
  this.running.push(runItem);
10737
10796
  this.emit("changed");
10738
10797
  const eventType = item.scenarioId ? "scenario_started" : "conversation_started";
10739
- for (const col of board.columns) {
10740
- const target = col.cards.find((c) => c.id === item.cardId);
10741
- if (target) {
10742
- target.history = [...target.history ?? [], {
10743
- type: eventType,
10744
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10745
- detail: conv.id
10746
- }];
10747
- kanbanStore.update({ id: board.id, columns: board.columns }).catch(() => {
10748
- });
10749
- break;
10750
- }
10751
- }
10798
+ kanbanStore.addCardEvent(board.id, item.cardId, eventType, conv.id).catch(() => {
10799
+ });
10752
10800
  if (item.scenarioId) {
10753
10801
  void runScenario(conv.id, item.scenarioId, cardContent, {
10754
10802
  runnerOverride: item.runner,
@@ -10855,7 +10903,12 @@ var kanbanQueueRouter = router({
10855
10903
  });
10856
10904
 
10857
10905
  // ../server/src/trpc/routers/kanban.ts
10906
+ import { mkdir as mkdir14, readdir as readdir5, rm as rm2, stat as stat3, writeFile as writeFile11 } from "fs/promises";
10907
+ import { createHash } from "crypto";
10908
+ import { tmpdir } from "os";
10909
+ import { join as join16 } from "path";
10858
10910
  import { z as z20 } from "zod";
10911
+ import { TRPCError as TRPCError17 } from "@trpc/server";
10859
10912
  function summarizeCard(card, boardId, columnTitle) {
10860
10913
  return {
10861
10914
  boardId,
@@ -10864,8 +10917,15 @@ function summarizeCard(card, boardId, columnTitle) {
10864
10917
  title: card.title,
10865
10918
  markdown: card.markdown ?? "",
10866
10919
  assignees: (card.assignees ?? []).map((a) => a.name),
10867
- commentCount: (card.history ?? []).filter((e) => e.type === "comment").length,
10920
+ commentCount: card.commentCount ?? (card.history ?? []).filter((e) => e.type === "comment").length,
10868
10921
  attachmentCount: (card.attachments ?? []).length,
10922
+ // Metadata only — the bytes are fetched on demand by `downloadAttachment`.
10923
+ attachments: (card.attachments ?? []).map((f) => ({
10924
+ id: f.id,
10925
+ name: f.name,
10926
+ contentType: f.contentType,
10927
+ size: f.size
10928
+ })),
10869
10929
  createdAt: card.createdAt,
10870
10930
  updatedAt: card.updatedAt
10871
10931
  };
@@ -10887,6 +10947,49 @@ function boardCounts(board) {
10887
10947
  function normalize(value) {
10888
10948
  return value.normalize("NFD").replace(new RegExp("\\p{Diacritic}", "gu"), "").toLowerCase();
10889
10949
  }
10950
+ var ATTACHMENT_ID_REGEX = /^[A-Za-z0-9_-]{1,128}$/;
10951
+ var MAX_ATTACHMENT_BYTES = 55 * 1024 * 1024;
10952
+ function attachmentCacheDir() {
10953
+ return join16(tmpdir(), "runeya-kanban-attachments");
10954
+ }
10955
+ var ATTACHMENT_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
10956
+ async function purgeStaleAttachments(dir, ttlMs = ATTACHMENT_CACHE_TTL_MS) {
10957
+ try {
10958
+ const cutoff = Date.now() - ttlMs;
10959
+ for (const name of await readdir5(dir)) {
10960
+ const path = join16(dir, name);
10961
+ const info = await stat3(path).catch(() => null);
10962
+ if (info && info.mtimeMs < cutoff) await rm2(path, { force: true });
10963
+ }
10964
+ } catch {
10965
+ }
10966
+ }
10967
+ function attachmentCacheDirs() {
10968
+ return [attachmentCacheDir(), join16(env.DATA_DIR, "kanban-attachments")];
10969
+ }
10970
+ async function storeAttachment(id, name, body, dirs = attachmentCacheDirs()) {
10971
+ const refusals = [];
10972
+ for (const dir of dirs) {
10973
+ try {
10974
+ await mkdir14(dir, { recursive: true });
10975
+ const path = join16(dir, safeLocalName(id, name));
10976
+ await writeFile11(path, body);
10977
+ void purgeStaleAttachments(dir);
10978
+ return path;
10979
+ } catch (err) {
10980
+ refusals.push(`${dir} (${err instanceof Error ? err.message : String(err)})`);
10981
+ }
10982
+ }
10983
+ throw new TRPCError17({
10984
+ code: "INTERNAL_SERVER_ERROR",
10985
+ message: `Impossible d'\xE9crire la pi\xE8ce jointe sur cette machine. Emplacements essay\xE9s : ${refusals.join(" ; ")}. V\xE9rifiez les droits d'\xE9criture, ou l'espace disque.`
10986
+ });
10987
+ }
10988
+ function safeLocalName(id, name) {
10989
+ const base = createHash("sha256").update(id).digest("hex").slice(0, 32);
10990
+ const ext = /\.([A-Za-z0-9]{1,12})$/.exec(name)?.[1];
10991
+ return ext ? `${base}.${ext.toLowerCase()}` : base;
10992
+ }
10890
10993
  var kanbanRouter = router({
10891
10994
  /**
10892
10995
  * The organization's boards, without their cards — a board carries its whole
@@ -10976,12 +11079,46 @@ var kanbanRouter = router({
10976
11079
  { type: "add_card", columnTitle: input.column, cardTitle: input.title, cardContent: input.content }
10977
11080
  ]);
10978
11081
  return { ok: true };
11082
+ }),
11083
+ /**
11084
+ * Fetch one card attachment from the cloud and drop it on this machine, so an
11085
+ * agent can open it with its own file tools. The bytes never go through the
11086
+ * prompt: the card context lists the attachments, this returns a path.
11087
+ */
11088
+ downloadAttachment: protectedProcedure.input(z20.object({ attachmentId: z20.string().max(128) })).mutation(async ({ input }) => {
11089
+ const id = input.attachmentId;
11090
+ if (!ATTACHMENT_ID_REGEX.test(id)) {
11091
+ throw new TRPCError17({ code: "BAD_REQUEST", message: "Invalid attachment id" });
11092
+ }
11093
+ const res = await cloudFetch(`/api/kanban/file/${id}`, { timeoutMs: 12e4 });
11094
+ if (res.status === 404) {
11095
+ throw new TRPCError17({ code: "NOT_FOUND", message: `Attachment ${id} not found` });
11096
+ }
11097
+ if (!res.ok) {
11098
+ throw new TRPCError17({
11099
+ code: res.status === 403 ? "FORBIDDEN" : "INTERNAL_SERVER_ERROR",
11100
+ message: `Cloud refused the attachment (HTTP ${res.status})`
11101
+ });
11102
+ }
11103
+ const declared = Number(res.headers.get("content-length") ?? 0);
11104
+ if (declared > MAX_ATTACHMENT_BYTES) {
11105
+ throw new TRPCError17({ code: "PAYLOAD_TOO_LARGE", message: "Attachment too large to download" });
11106
+ }
11107
+ const body = Buffer.from(await res.arrayBuffer());
11108
+ if (body.length > MAX_ATTACHMENT_BYTES) {
11109
+ throw new TRPCError17({ code: "PAYLOAD_TOO_LARGE", message: "Attachment too large to download" });
11110
+ }
11111
+ const contentType = res.headers.get("content-type") ?? "application/octet-stream";
11112
+ const disposition = res.headers.get("content-disposition") ?? "";
11113
+ const name = /filename="([^"]*)"/.exec(disposition)?.[1] || id;
11114
+ const path = await storeAttachment(id, name, body);
11115
+ return { path, name, contentType, size: body.length };
10979
11116
  })
10980
11117
  });
10981
11118
 
10982
11119
  // ../server/src/trpc/routers/terminal.ts
10983
11120
  import { z as z21 } from "zod";
10984
- import { TRPCError as TRPCError17 } from "@trpc/server";
11121
+ import { TRPCError as TRPCError18 } from "@trpc/server";
10985
11122
  var terminalRouter = router({
10986
11123
  /** Create a PTY shell session on the target agent */
10987
11124
  create: protectedProcedure.input(z21.object({
@@ -11066,7 +11203,7 @@ var terminalRouter = router({
11066
11203
  }
11067
11204
  );
11068
11205
  } catch (err) {
11069
- throw new TRPCError17({
11206
+ throw new TRPCError18({
11070
11207
  code: "BAD_REQUEST",
11071
11208
  message: `Cannot subscribe to terminal: ${err.message}`
11072
11209
  });
@@ -11101,9 +11238,9 @@ var utilityRouter = router({
11101
11238
 
11102
11239
  // ../server/src/trpc/routers/wiki.ts
11103
11240
  import { z as z23 } from "zod";
11104
- import { TRPCError as TRPCError18 } from "@trpc/server";
11105
- import { readFile as readFile13, readdir as readdir5, stat as stat3, realpath, writeFile as writeFile11, mkdir as mkdir14, rename as rename10, rm as rm2 } from "fs/promises";
11106
- import { resolve as resolvePath, join as join16, relative, sep as sep3, dirname as dirname3 } from "path";
11241
+ import { TRPCError as TRPCError19 } from "@trpc/server";
11242
+ import { readFile as readFile13, readdir as readdir6, stat as stat4, realpath, writeFile as writeFile12, mkdir as mkdir15, rename as rename10, rm as rm3 } from "fs/promises";
11243
+ import { resolve as resolvePath, join as join17, relative, sep as sep3, dirname as dirname3 } from "path";
11107
11244
  var SCOPE_SCHEMA = z23.union([
11108
11245
  z23.literal("global"),
11109
11246
  z23.string().regex(/^service:[A-Za-z0-9_-]{1,128}$/, "Invalid service scope")
@@ -11137,27 +11274,27 @@ async function resolveScope(scope) {
11137
11274
  const settings = await settingsManager.getSettings();
11138
11275
  const sub = (settings.globalDocsPath?.trim() || "wiki").replace(/^[\\/]+|[\\/]+$/g, "");
11139
11276
  if (sub.includes("..") || sub.includes("\0")) {
11140
- throw new TRPCError18({ code: "BAD_REQUEST", message: "Sous-chemin invalide" });
11277
+ throw new TRPCError19({ code: "BAD_REQUEST", message: "Sous-chemin invalide" });
11141
11278
  }
11142
11279
  const dataDirAbs = resolvePath(env.DATA_DIR);
11143
- await mkdir14(dataDirAbs, { recursive: true });
11280
+ await mkdir15(dataDirAbs, { recursive: true });
11144
11281
  const base = dirname3(await realpath(dataDirAbs));
11145
11282
  const target = resolvePath(base, sub);
11146
11283
  if (target !== base && !(target + sep3).startsWith(base + sep3)) {
11147
- throw new TRPCError18({ code: "FORBIDDEN", message: "Hors du dossier de donn\xE9es du serveur" });
11284
+ throw new TRPCError19({ code: "FORBIDDEN", message: "Hors du dossier de donn\xE9es du serveur" });
11148
11285
  }
11149
- await mkdir14(target, { recursive: true });
11286
+ await mkdir15(target, { recursive: true });
11150
11287
  const root = await realpath(target);
11151
11288
  if (root !== base && !(root + sep3).startsWith(base + sep3)) {
11152
- throw new TRPCError18({ code: "FORBIDDEN", message: "Le dossier wiki r\xE9sout hors du dossier de donn\xE9es" });
11289
+ throw new TRPCError19({ code: "FORBIDDEN", message: "Le dossier wiki r\xE9sout hors du dossier de donn\xE9es" });
11153
11290
  }
11154
11291
  return { mode: "local", root };
11155
11292
  }
11156
11293
  const serviceId = scope.slice("service:".length);
11157
11294
  const service = await serviceStore.get(serviceId);
11158
- if (!service) throw new TRPCError18({ code: "NOT_FOUND", message: "Service introuvable" });
11295
+ if (!service) throw new TRPCError19({ code: "NOT_FOUND", message: "Service introuvable" });
11159
11296
  const agentId = await resolveEffectiveAgentId(service);
11160
- if (!agentId) throw new TRPCError18({ code: "BAD_REQUEST", message: "Aucun agent configur\xE9 pour ce service" });
11297
+ if (!agentId) throw new TRPCError19({ code: "BAD_REQUEST", message: "Aucun agent configur\xE9 pour ce service" });
11161
11298
  const cwd = (service.docsPath?.trim() || service.cwd || ".").toString();
11162
11299
  return { mode: "agent", agentId, cwd };
11163
11300
  }
@@ -11165,7 +11302,7 @@ async function walkLocal(root, dir, depth, counter) {
11165
11302
  if (depth > MAX_DEPTH || counter.n >= MAX_FILES) return [];
11166
11303
  let entries;
11167
11304
  try {
11168
- entries = await readdir5(dir, { withFileTypes: true });
11305
+ entries = await readdir6(dir, { withFileTypes: true });
11169
11306
  } catch {
11170
11307
  return [];
11171
11308
  }
@@ -11173,7 +11310,7 @@ async function walkLocal(root, dir, depth, counter) {
11173
11310
  for (const e of entries) {
11174
11311
  if (counter.n >= MAX_FILES) break;
11175
11312
  if (e.name.startsWith(".") && e.name !== ".") continue;
11176
- const abs = join16(dir, e.name);
11313
+ const abs = join17(dir, e.name);
11177
11314
  const rel = relative(root, abs).split(sep3).join("/");
11178
11315
  if (e.isDirectory()) {
11179
11316
  if (IGNORED_DIRS.has(e.name)) continue;
@@ -11192,7 +11329,7 @@ async function walkLocal(root, dir, depth, counter) {
11192
11329
  }
11193
11330
  async function resolveSafeLocal(root, relPath, requireExist) {
11194
11331
  if (relPath.includes("..") || relPath.startsWith("/")) {
11195
- throw new TRPCError18({ code: "BAD_REQUEST", message: "Chemin invalide" });
11332
+ throw new TRPCError19({ code: "BAD_REQUEST", message: "Chemin invalide" });
11196
11333
  }
11197
11334
  const target = resolvePath(root, relPath);
11198
11335
  if (requireExist) {
@@ -11200,10 +11337,10 @@ async function resolveSafeLocal(root, relPath, requireExist) {
11200
11337
  try {
11201
11338
  real = await realpath(target);
11202
11339
  } catch {
11203
- throw new TRPCError18({ code: "NOT_FOUND", message: "Chemin introuvable" });
11340
+ throw new TRPCError19({ code: "NOT_FOUND", message: "Chemin introuvable" });
11204
11341
  }
11205
11342
  if (real !== root && !(real + sep3).startsWith(root + sep3)) {
11206
- throw new TRPCError18({ code: "FORBIDDEN", message: "Hors du dossier autoris\xE9" });
11343
+ throw new TRPCError19({ code: "FORBIDDEN", message: "Hors du dossier autoris\xE9" });
11207
11344
  }
11208
11345
  return real;
11209
11346
  }
@@ -11215,7 +11352,7 @@ async function resolveSafeLocal(root, relPath, requireExist) {
11215
11352
  realParent = parent;
11216
11353
  }
11217
11354
  if (realParent !== root && !(realParent + sep3).startsWith(root + sep3)) {
11218
- throw new TRPCError18({ code: "FORBIDDEN", message: "Hors du dossier autoris\xE9" });
11355
+ throw new TRPCError19({ code: "FORBIDDEN", message: "Hors du dossier autoris\xE9" });
11219
11356
  }
11220
11357
  return resolvePath(realParent, target.slice(parent.length).replace(/^[\\/]+/, ""));
11221
11358
  }
@@ -11231,35 +11368,35 @@ var wikiRouter = router({
11231
11368
  }),
11232
11369
  read: protectedProcedure.input(z23.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA })).output(z23.object({ path: z23.string(), content: z23.string() })).query(async ({ input }) => {
11233
11370
  if (!/\.(md|markdown)$/i.test(input.path)) {
11234
- throw new TRPCError18({ code: "BAD_REQUEST", message: "Seuls les .md/.markdown sont autoris\xE9s" });
11371
+ throw new TRPCError19({ code: "BAD_REQUEST", message: "Seuls les .md/.markdown sont autoris\xE9s" });
11235
11372
  }
11236
11373
  const target = await resolveScope(input.scope);
11237
11374
  if (target.mode === "agent") {
11238
11375
  return agentManager.agentQuery(target.agentId, "wiki.readRepoMarkdown", { cwd: target.cwd, path: input.path });
11239
11376
  }
11240
11377
  const file = await resolveSafeLocal(target.root, input.path, true);
11241
- const s = await stat3(file);
11242
- if (!s.isFile()) throw new TRPCError18({ code: "BAD_REQUEST", message: "Pas un fichier" });
11243
- if (s.size > MAX_FILE_BYTES) throw new TRPCError18({ code: "PAYLOAD_TOO_LARGE", message: "Fichier trop volumineux" });
11378
+ const s = await stat4(file);
11379
+ if (!s.isFile()) throw new TRPCError19({ code: "BAD_REQUEST", message: "Pas un fichier" });
11380
+ if (s.size > MAX_FILE_BYTES) throw new TRPCError19({ code: "PAYLOAD_TOO_LARGE", message: "Fichier trop volumineux" });
11244
11381
  const content = await readFile13(file, "utf-8");
11245
11382
  return { path: input.path, content };
11246
11383
  }),
11247
11384
  write: protectedProcedure.input(z23.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA, content: z23.string().max(5e6) })).mutation(async ({ input }) => {
11248
11385
  if (!/\.(md|markdown)$/i.test(input.path)) {
11249
- throw new TRPCError18({ code: "BAD_REQUEST", message: "Seuls les .md/.markdown sont autoris\xE9s" });
11386
+ throw new TRPCError19({ code: "BAD_REQUEST", message: "Seuls les .md/.markdown sont autoris\xE9s" });
11250
11387
  }
11251
11388
  const target = await resolveScope(input.scope);
11252
11389
  if (target.mode === "agent") {
11253
11390
  return agentManager.agentMutation(target.agentId, "wiki.writeMarkdown", { cwd: target.cwd, path: input.path, content: input.content });
11254
11391
  }
11255
11392
  const file = await resolveSafeLocal(target.root, input.path, false);
11256
- await mkdir14(dirname3(file), { recursive: true });
11257
- await writeFile11(file, input.content, "utf-8");
11393
+ await mkdir15(dirname3(file), { recursive: true });
11394
+ await writeFile12(file, input.content, "utf-8");
11258
11395
  return { path: input.path, ok: true };
11259
11396
  }),
11260
11397
  createFile: protectedProcedure.input(z23.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
11261
11398
  if (!/\.(md|markdown)$/i.test(input.path)) {
11262
- throw new TRPCError18({ code: "BAD_REQUEST", message: "Seuls les .md/.markdown sont autoris\xE9s" });
11399
+ throw new TRPCError19({ code: "BAD_REQUEST", message: "Seuls les .md/.markdown sont autoris\xE9s" });
11263
11400
  }
11264
11401
  const target = await resolveScope(input.scope);
11265
11402
  if (target.mode === "agent") {
@@ -11267,13 +11404,13 @@ var wikiRouter = router({
11267
11404
  }
11268
11405
  const file = await resolveSafeLocal(target.root, input.path, false);
11269
11406
  try {
11270
- await stat3(file);
11271
- throw new TRPCError18({ code: "CONFLICT", message: "Fichier d\xE9j\xE0 existant" });
11407
+ await stat4(file);
11408
+ throw new TRPCError19({ code: "CONFLICT", message: "Fichier d\xE9j\xE0 existant" });
11272
11409
  } catch (err) {
11273
- if (err instanceof TRPCError18) throw err;
11410
+ if (err instanceof TRPCError19) throw err;
11274
11411
  }
11275
- await mkdir14(dirname3(file), { recursive: true });
11276
- await writeFile11(file, "", "utf-8");
11412
+ await mkdir15(dirname3(file), { recursive: true });
11413
+ await writeFile12(file, "", "utf-8");
11277
11414
  return { path: input.path, ok: true };
11278
11415
  }),
11279
11416
  createDir: protectedProcedure.input(z23.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
@@ -11282,7 +11419,7 @@ var wikiRouter = router({
11282
11419
  return agentManager.agentMutation(target.agentId, "wiki.createDir", { cwd: target.cwd, path: input.path });
11283
11420
  }
11284
11421
  const dir = await resolveSafeLocal(target.root, input.path, false);
11285
- await mkdir14(dir, { recursive: true });
11422
+ await mkdir15(dir, { recursive: true });
11286
11423
  return { path: input.path, ok: true };
11287
11424
  }),
11288
11425
  rename: protectedProcedure.input(z23.object({ scope: SCOPE_SCHEMA, fromPath: REL_PATH_SCHEMA, toPath: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
@@ -11293,12 +11430,12 @@ var wikiRouter = router({
11293
11430
  const from = await resolveSafeLocal(target.root, input.fromPath, true);
11294
11431
  const to = await resolveSafeLocal(target.root, input.toPath, false);
11295
11432
  try {
11296
- await stat3(to);
11297
- throw new TRPCError18({ code: "CONFLICT", message: "La cible existe d\xE9j\xE0" });
11433
+ await stat4(to);
11434
+ throw new TRPCError19({ code: "CONFLICT", message: "La cible existe d\xE9j\xE0" });
11298
11435
  } catch (err) {
11299
- if (err instanceof TRPCError18) throw err;
11436
+ if (err instanceof TRPCError19) throw err;
11300
11437
  }
11301
- await mkdir14(dirname3(to), { recursive: true });
11438
+ await mkdir15(dirname3(to), { recursive: true });
11302
11439
  await rename10(from, to);
11303
11440
  return { fromPath: input.fromPath, toPath: input.toPath, ok: true };
11304
11441
  }),
@@ -11309,9 +11446,9 @@ var wikiRouter = router({
11309
11446
  }
11310
11447
  const serviceId = input.scope.slice("service:".length);
11311
11448
  const service = await serviceStore.get(serviceId);
11312
- if (!service) throw new TRPCError18({ code: "NOT_FOUND", message: "Service introuvable" });
11449
+ if (!service) throw new TRPCError19({ code: "NOT_FOUND", message: "Service introuvable" });
11313
11450
  const agentId = await resolveEffectiveAgentId(service);
11314
- if (!agentId) throw new TRPCError18({ code: "BAD_REQUEST", message: "Aucun agent configur\xE9" });
11451
+ if (!agentId) throw new TRPCError19({ code: "BAD_REQUEST", message: "Aucun agent configur\xE9" });
11315
11452
  const cwd = (service.docsPath?.trim() || service.cwd || ".").toString();
11316
11453
  return agentManager.agentMutation(agentId, "wiki.ensureRoot", { cwd });
11317
11454
  }),
@@ -11321,8 +11458,8 @@ var wikiRouter = router({
11321
11458
  return agentManager.agentMutation(target.agentId, "wiki.deletePath", { cwd: target.cwd, path: input.path });
11322
11459
  }
11323
11460
  const fp = await resolveSafeLocal(target.root, input.path, true);
11324
- if (fp === target.root) throw new TRPCError18({ code: "FORBIDDEN", message: "Impossible de supprimer la racine" });
11325
- await rm2(fp, { recursive: true, force: true });
11461
+ if (fp === target.root) throw new TRPCError19({ code: "FORBIDDEN", message: "Impossible de supprimer la racine" });
11462
+ await rm3(fp, { recursive: true, force: true });
11326
11463
  return { path: input.path, ok: true };
11327
11464
  })
11328
11465
  });
@@ -11337,17 +11474,17 @@ var configRouter = router({
11337
11474
 
11338
11475
  // ../server/src/trpc/routers/cloud-sync.ts
11339
11476
  import { z as z24 } from "zod";
11340
- import { TRPCError as TRPCError19 } from "@trpc/server";
11477
+ import { TRPCError as TRPCError20 } from "@trpc/server";
11341
11478
 
11342
11479
  // ../server/src/services/cloud-sync-store.ts
11343
- import { readFile as readFile14, writeFile as writeFile12, rename as rename11, mkdir as mkdir15, chmod as chmod9 } from "fs/promises";
11344
- import { join as join17 } from "path";
11480
+ import { readFile as readFile14, writeFile as writeFile13, rename as rename11, mkdir as mkdir16, chmod as chmod9 } from "fs/promises";
11481
+ import { join as join18 } from "path";
11345
11482
  var FILENAME5 = "cloud-sync.json";
11346
11483
  var CloudSyncStore = class {
11347
11484
  links = /* @__PURE__ */ new Map();
11348
11485
  loaded = false;
11349
11486
  getFilePath() {
11350
- return join17(env.DATA_DIR, FILENAME5);
11487
+ return join18(env.DATA_DIR, FILENAME5);
11351
11488
  }
11352
11489
  async load() {
11353
11490
  if (this.loaded) return;
@@ -11360,11 +11497,11 @@ var CloudSyncStore = class {
11360
11497
  this.loaded = true;
11361
11498
  }
11362
11499
  async save() {
11363
- await mkdir15(env.DATA_DIR, { recursive: true });
11500
+ await mkdir16(env.DATA_DIR, { recursive: true });
11364
11501
  const filePath = this.getFilePath();
11365
11502
  const tmpPath = filePath + ".tmp";
11366
11503
  const data = JSON.stringify(Array.from(this.links.values()), null, 2);
11367
- await writeFile12(tmpPath, data, "utf-8");
11504
+ await writeFile13(tmpPath, data, "utf-8");
11368
11505
  await rename11(tmpPath, filePath);
11369
11506
  await chmod9(filePath, 384);
11370
11507
  }
@@ -11760,8 +11897,8 @@ var cloudSyncBridge = new CloudSyncBridge();
11760
11897
 
11761
11898
  // ../server/src/services/master-password.ts
11762
11899
  import { randomBytes as randomBytes4, createCipheriv, createDecipheriv } from "crypto";
11763
- import { readFile as readFile15, writeFile as writeFile13, chmod as chmod10, stat as stat4, rename as rename12 } from "fs/promises";
11764
- import { join as join18 } from "path";
11900
+ import { readFile as readFile15, writeFile as writeFile14, chmod as chmod10, stat as stat5, rename as rename12 } from "fs/promises";
11901
+ import { join as join19 } from "path";
11765
11902
  import { Entry } from "@napi-rs/keyring";
11766
11903
  import { hashRaw as argon2HashRaw } from "@node-rs/argon2";
11767
11904
  var KEYRING_SERVICE = "runeya";
@@ -11773,7 +11910,7 @@ var CANARY_PLAINTEXT = "runeya:v1:key-verification";
11773
11910
  var MAX_KEY_FILE_SIZE = 1024;
11774
11911
  var ARGON2_OPTIONS = { memoryCost: 65536, timeCost: 3, parallelism: 4, outputLen: 32 };
11775
11912
  async function readKeyFile(filePath) {
11776
- const s = await stat4(filePath);
11913
+ const s = await stat5(filePath);
11777
11914
  if (s.size > MAX_KEY_FILE_SIZE) throw new Error(`Fichier suspect : ${filePath} (${s.size} octets)`);
11778
11915
  return readFile15(filePath);
11779
11916
  }
@@ -11794,7 +11931,7 @@ function aesDecrypt(key, data) {
11794
11931
  }
11795
11932
  async function getPepperFromFile(dataDir) {
11796
11933
  try {
11797
- const raw = await readKeyFile(join18(dataDir, PEPPER_FILENAME));
11934
+ const raw = await readKeyFile(join19(dataDir, PEPPER_FILENAME));
11798
11935
  const hex = raw.toString("utf-8").trim();
11799
11936
  if (/^[0-9a-f]{64}$/i.test(hex)) return Buffer.from(hex, "hex");
11800
11937
  } catch {
@@ -11802,9 +11939,9 @@ async function getPepperFromFile(dataDir) {
11802
11939
  return null;
11803
11940
  }
11804
11941
  async function writePepperToFile(dataDir, pepper) {
11805
- const filePath = join18(dataDir, PEPPER_FILENAME);
11942
+ const filePath = join19(dataDir, PEPPER_FILENAME);
11806
11943
  const tmpPath = filePath + ".tmp";
11807
- await writeFile13(tmpPath, pepper.toString("hex"), "utf-8");
11944
+ await writeFile14(tmpPath, pepper.toString("hex"), "utf-8");
11808
11945
  await chmod10(tmpPath, 384);
11809
11946
  await rename12(tmpPath, filePath);
11810
11947
  }
@@ -11853,14 +11990,14 @@ async function writeEncryptedKey(dataDir, masterPassword, encryptionKey) {
11853
11990
  const payload = aesEncrypt(derivedKey, encryptionKey);
11854
11991
  const fileContent = Buffer.concat([salt, payload]);
11855
11992
  const encoded = fileContent.toString("base64");
11856
- const filePath = join18(dataDir, ENCRYPTED_KEY_FILENAME);
11993
+ const filePath = join19(dataDir, ENCRYPTED_KEY_FILENAME);
11857
11994
  const tmpPath = filePath + ".tmp";
11858
- await writeFile13(tmpPath, encoded, "utf-8");
11995
+ await writeFile14(tmpPath, encoded, "utf-8");
11859
11996
  await chmod10(tmpPath, 384);
11860
11997
  await rename12(tmpPath, filePath);
11861
11998
  }
11862
11999
  async function readEncryptedKey(dataDir, masterPassword) {
11863
- const filePath = join18(dataDir, ENCRYPTED_KEY_FILENAME);
12000
+ const filePath = join19(dataDir, ENCRYPTED_KEY_FILENAME);
11864
12001
  const raw = await readKeyFile(filePath);
11865
12002
  const fileContent = Buffer.from(raw.toString("utf-8").trim(), "base64");
11866
12003
  const salt = fileContent.subarray(0, 16);
@@ -11880,13 +12017,13 @@ async function getPepperFromKeychain(dataDir) {
11880
12017
  }
11881
12018
  async function writeVerifyFile(dataDir, encryptionKey) {
11882
12019
  const payload = aesEncrypt(encryptionKey, Buffer.from(CANARY_PLAINTEXT, "utf-8"));
11883
- const filePath = join18(dataDir, VERIFY_FILENAME);
12020
+ const filePath = join19(dataDir, VERIFY_FILENAME);
11884
12021
  const tmpPath = filePath + ".tmp";
11885
- await writeFile13(tmpPath, payload.toString("base64"), "utf-8");
12022
+ await writeFile14(tmpPath, payload.toString("base64"), "utf-8");
11886
12023
  await rename12(tmpPath, filePath);
11887
12024
  }
11888
12025
  async function verifyEncryptionKey(dataDir, encryptionKey) {
11889
- const filePath = join18(dataDir, VERIFY_FILENAME);
12026
+ const filePath = join19(dataDir, VERIFY_FILENAME);
11890
12027
  const raw = await readKeyFile(filePath);
11891
12028
  if (!matchesCanary(raw.toString("utf-8"), encryptionKey)) {
11892
12029
  throw new Error("Cl\xE9 d'encryption incorrecte");
@@ -11902,14 +12039,14 @@ function matchesCanary(canaryBase64, encryptionKey) {
11902
12039
  }
11903
12040
  async function readVerifyFile(dataDir) {
11904
12041
  try {
11905
- return (await readKeyFile(join18(dataDir, VERIFY_FILENAME))).toString("utf-8").trim();
12042
+ return (await readKeyFile(join19(dataDir, VERIFY_FILENAME))).toString("utf-8").trim();
11906
12043
  } catch {
11907
12044
  return null;
11908
12045
  }
11909
12046
  }
11910
12047
  async function hasVerifyFile(dataDir) {
11911
12048
  try {
11912
- await stat4(join18(dataDir, VERIFY_FILENAME));
12049
+ await stat5(join19(dataDir, VERIFY_FILENAME));
11913
12050
  return true;
11914
12051
  } catch {
11915
12052
  return false;
@@ -11917,7 +12054,7 @@ async function hasVerifyFile(dataDir) {
11917
12054
  }
11918
12055
  async function hasEncryptedKeyFile(dataDir) {
11919
12056
  try {
11920
- await stat4(join18(dataDir, ENCRYPTED_KEY_FILENAME));
12057
+ await stat5(join19(dataDir, ENCRYPTED_KEY_FILENAME));
11921
12058
  return true;
11922
12059
  } catch {
11923
12060
  return false;
@@ -11928,25 +12065,25 @@ async function hasEncryptedKeyFile(dataDir) {
11928
12065
  async function reconcileOrgCanary(orgId) {
11929
12066
  const key = getEncryptionKey();
11930
12067
  if (!key) {
11931
- throw new TRPCError19({ code: "PRECONDITION_FAILED", message: "Encryption key not loaded." });
12068
+ throw new TRPCError20({ code: "PRECONDITION_FAILED", message: "Encryption key not loaded." });
11932
12069
  }
11933
12070
  const local = await readVerifyFile(env.DATA_DIR);
11934
12071
  if (!local) {
11935
- throw new TRPCError19({ code: "PRECONDITION_FAILED", message: "This machine has no key canary yet." });
12072
+ throw new TRPCError20({ code: "PRECONDITION_FAILED", message: "This machine has no key canary yet." });
11936
12073
  }
11937
12074
  const res = await cloudFetch("/api/auth/organization/canary", {
11938
12075
  method: "POST",
11939
12076
  body: { organizationId: orgId, canary: local }
11940
12077
  });
11941
12078
  if (!res.ok) {
11942
- throw new TRPCError19({ code: "BAD_GATEWAY", message: "Could not reach the organization on the cloud." });
12079
+ throw new TRPCError20({ code: "BAD_GATEWAY", message: "Could not reach the organization on the cloud." });
11943
12080
  }
11944
12081
  const { canary } = await res.json();
11945
12082
  if (typeof canary !== "string") {
11946
- throw new TRPCError19({ code: "BAD_GATEWAY", message: "The cloud returned no key canary." });
12083
+ throw new TRPCError20({ code: "BAD_GATEWAY", message: "The cloud returned no key canary." });
11947
12084
  }
11948
12085
  if (!matchesCanary(canary, key)) {
11949
- throw new TRPCError19({
12086
+ throw new TRPCError20({
11950
12087
  code: "FORBIDDEN",
11951
12088
  message: "This organization uses a different encryption key. Ask a member for the key already in use, then set it up on this machine before syncing."
11952
12089
  });
@@ -12050,8 +12187,8 @@ var MigrationEngine = class {
12050
12187
  var migrationEngine = new MigrationEngine();
12051
12188
 
12052
12189
  // ../server/src/services/file-security.ts
12053
- import { chmod as chmod11, stat as stat5 } from "fs/promises";
12054
- import { join as join19 } from "path";
12190
+ import { chmod as chmod11, stat as stat6 } from "fs/promises";
12191
+ import { join as join20 } from "path";
12055
12192
  var SENSITIVE_FILES = [
12056
12193
  "agents.json",
12057
12194
  "settings.json",
@@ -12063,9 +12200,9 @@ var SENSITIVE_FILES = [
12063
12200
  var SECURE_MODE = 384;
12064
12201
  async function ensureFilePermissions() {
12065
12202
  for (const filename of SENSITIVE_FILES) {
12066
- const filepath = join19(env.DATA_DIR, filename);
12203
+ const filepath = join20(env.DATA_DIR, filename);
12067
12204
  try {
12068
- const stats = await stat5(filepath);
12205
+ const stats = await stat6(filepath);
12069
12206
  const mode = stats.mode & 511;
12070
12207
  if (mode !== SECURE_MODE) {
12071
12208
  console.warn("[security] File", filename, "has mode", mode.toString(8) + ", fixing to 600");
@@ -12080,8 +12217,8 @@ async function ensureFilePermissions() {
12080
12217
  }
12081
12218
 
12082
12219
  // ../server/src/utils/ensure-data-gitignore.ts
12083
- import { writeFile as writeFile14 } from "fs/promises";
12084
- import { join as join20 } from "path";
12220
+ import { writeFile as writeFile15 } from "fs/promises";
12221
+ import { join as join21 } from "path";
12085
12222
  var GITIGNORE_CONTENT = `
12086
12223
  #################
12087
12224
  # Do not edit this file #
@@ -12118,8 +12255,8 @@ conversations.private.json
12118
12255
  *.log.*
12119
12256
  `;
12120
12257
  async function ensureDataGitignore(dataDir) {
12121
- const gitignorePath = join20(dataDir, ".gitignore");
12122
- await writeFile14(gitignorePath, GITIGNORE_CONTENT, "utf-8");
12258
+ const gitignorePath = join21(dataDir, ".gitignore");
12259
+ await writeFile15(gitignorePath, GITIGNORE_CONTENT, "utf-8");
12123
12260
  }
12124
12261
 
12125
12262
  // ../server/src/migrations/migrate-from-legacy.ts
@@ -12128,13 +12265,13 @@ import { randomBytes as randomBytes5, createCipheriv as createCipheriv2, createD
12128
12265
  import { randomUUID as randomUUID12 } from "crypto";
12129
12266
  import {
12130
12267
  readFile as readFile16,
12131
- writeFile as writeFile15,
12268
+ writeFile as writeFile16,
12132
12269
  rename as rename13,
12133
- mkdir as mkdir16,
12270
+ mkdir as mkdir17,
12134
12271
  access as access2,
12135
- readdir as readdir6
12272
+ readdir as readdir7
12136
12273
  } from "fs/promises";
12137
- import { join as join21 } from "path";
12274
+ import { join as join22 } from "path";
12138
12275
  var _require = createRequire(import.meta.url);
12139
12276
  var PARSER_ID_MAP = {
12140
12277
  "stack-monitor-parser-jsons": "native:json",
@@ -12263,14 +12400,14 @@ async function decryptLegacyFile(filePath, key, sodium) {
12263
12400
  }
12264
12401
  async function atomicWrite(path, data) {
12265
12402
  const tmp = path + ".tmp";
12266
- await writeFile15(tmp, JSON.stringify(data, null, 2), "utf-8");
12403
+ await writeFile16(tmp, JSON.stringify(data, null, 2), "utf-8");
12267
12404
  await rename13(tmp, path);
12268
12405
  }
12269
12406
  async function runLegacyMigration(dataDir) {
12270
12407
  const { resolve: resolve6 } = await import("path");
12271
12408
  const abCwd = resolve6(process.cwd());
12272
- const legacyRoot = join21(abCwd, env.DATA_DIR);
12273
- const legacyKeyPath = join21(legacyRoot, "dbs", "encryption-key.json");
12409
+ const legacyRoot = join22(abCwd, env.DATA_DIR);
12410
+ const legacyKeyPath = join22(legacyRoot, "dbs", "encryption-key.json");
12274
12411
  try {
12275
12412
  await access2(legacyKeyPath);
12276
12413
  } catch {
@@ -12278,20 +12415,20 @@ async function runLegacyMigration(dataDir) {
12278
12415
  }
12279
12416
  console.log("[legacy-migration] Legacy Runeya data detected, starting migration\u2026");
12280
12417
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").substring(0, 19);
12281
- const legacyTmp = join21(abCwd, ".runeya-tmp");
12418
+ const legacyTmp = join22(abCwd, ".runeya-tmp");
12282
12419
  await rename13(legacyRoot, legacyTmp);
12283
- await mkdir16(dataDir, { recursive: true });
12284
- const legacyOld = join21(dataDir, `backup-${timestamp}`);
12420
+ await mkdir17(dataDir, { recursive: true });
12421
+ const legacyOld = join22(dataDir, `backup-${timestamp}`);
12285
12422
  await rename13(legacyTmp, legacyOld);
12286
12423
  console.log(`[legacy-migration] Legacy data backed up to ${legacyOld}`);
12287
- const keyJson = JSON.parse(await readFile16(join21(legacyOld, "dbs", "encryption-key.json"), "utf-8"));
12424
+ const keyJson = JSON.parse(await readFile16(join22(legacyOld, "dbs", "encryption-key.json"), "utf-8"));
12288
12425
  const sodium = await getSodium();
12289
12426
  const sodiumKey = sodium.from_base64(keyJson.encryptionKey);
12290
12427
  const keyBuffer = Buffer.from(sodiumKey);
12291
12428
  const runyeaKeyHex = keyBuffer.toString("hex");
12292
12429
  await setEncryptionKey(runyeaKeyHex);
12293
12430
  console.log("[legacy-migration] Encryption key loaded in memory (temporary)");
12294
- const dbsDir = join21(legacyOld, "dbs");
12431
+ const dbsDir = join22(legacyOld, "dbs");
12295
12432
  async function readEncrypted(filePath) {
12296
12433
  try {
12297
12434
  return await decryptLegacyFile(filePath, sodiumKey, sodium);
@@ -12300,29 +12437,29 @@ async function runLegacyMigration(dataDir) {
12300
12437
  return null;
12301
12438
  }
12302
12439
  }
12303
- const envsDir = join21(dbsDir, "envs");
12304
- const envFiles = (await readdir6(envsDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
12440
+ const envsDir = join22(dbsDir, "envs");
12441
+ const envFiles = (await readdir7(envsDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
12305
12442
  const legacyEnvs = {};
12306
12443
  for (const file of envFiles) {
12307
12444
  const name = file.replace(".encrypted.json", "");
12308
- legacyEnvs[name] = await readEncrypted(join21(envsDir, file));
12445
+ legacyEnvs[name] = await readEncrypted(join22(envsDir, file));
12309
12446
  }
12310
- const servicesDir = join21(dbsDir, "services");
12311
- const serviceFiles = (await readdir6(servicesDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
12447
+ const servicesDir = join22(dbsDir, "services");
12448
+ const serviceFiles = (await readdir7(servicesDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
12312
12449
  const legacyServices = {};
12313
12450
  for (const file of serviceFiles) {
12314
12451
  const name = file.replace(".encrypted.json", "");
12315
12452
  if (!name) continue;
12316
- const data = await readEncrypted(join21(servicesDir, file));
12453
+ const data = await readEncrypted(join22(servicesDir, file));
12317
12454
  if (data?.label) legacyServices[name] = data;
12318
12455
  }
12319
- const overridesDir = join21(dbsDir, "overrides");
12320
- const overrideFiles = (await readdir6(overridesDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
12456
+ const overridesDir = join22(dbsDir, "overrides");
12457
+ const overrideFiles = (await readdir7(overridesDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
12321
12458
  const legacyServiceOverrides = {};
12322
12459
  const legacyEnvOverrides = {};
12323
12460
  for (const file of overrideFiles) {
12324
12461
  const baseName = file.replace(".encrypted.json", "");
12325
- const data = await readEncrypted(join21(overridesDir, file));
12462
+ const data = await readEncrypted(join22(overridesDir, file));
12326
12463
  if (!data) continue;
12327
12464
  if (baseName.endsWith("-envs")) {
12328
12465
  legacyServiceOverrides[baseName.slice(0, -5)] = data;
@@ -12330,11 +12467,11 @@ async function runLegacyMigration(dataDir) {
12330
12467
  legacyEnvOverrides[baseName.slice(0, -12)] = data;
12331
12468
  }
12332
12469
  }
12333
- const parsersDir = join21(dbsDir, "parsers");
12334
- const parserFiles = (await readdir6(parsersDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
12470
+ const parsersDir = join22(dbsDir, "parsers");
12471
+ const parserFiles = (await readdir7(parsersDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
12335
12472
  const legacyParsers = [];
12336
12473
  for (const file of parserFiles) {
12337
- const data = await readEncrypted(join21(parsersDir, file));
12474
+ const data = await readEncrypted(join22(parsersDir, file));
12338
12475
  if (data?.id) legacyParsers.push(data);
12339
12476
  }
12340
12477
  const projectMonoId = randomUUID12();
@@ -12675,7 +12812,7 @@ async function runLegacyMigration(dataDir) {
12675
12812
  }
12676
12813
  let existingSettings = {};
12677
12814
  try {
12678
- existingSettings = JSON.parse(await readFile16(join21(dataDir, "settings.json"), "utf-8"));
12815
+ existingSettings = JSON.parse(await readFile16(join22(dataDir, "settings.json"), "utf-8"));
12679
12816
  } catch {
12680
12817
  }
12681
12818
  const migratedParsers = legacyParsers.map((p) => ({
@@ -12696,11 +12833,11 @@ ${p.transform ?? ""}`,
12696
12833
  ...migratedParsers
12697
12834
  ]
12698
12835
  };
12699
- await atomicWrite(join21(dataDir, "projects.json"), runeProjects);
12700
- await atomicWrite(join21(dataDir, "services.json"), runeServices);
12701
- await atomicWrite(join21(dataDir, "environments.json"), runeEnvs);
12702
- await atomicWrite(join21(dataDir, "environment-overrides.json"), flatOverrides);
12703
- await atomicWrite(join21(dataDir, "settings.json"), newSettings);
12836
+ await atomicWrite(join22(dataDir, "projects.json"), runeProjects);
12837
+ await atomicWrite(join22(dataDir, "services.json"), runeServices);
12838
+ await atomicWrite(join22(dataDir, "environments.json"), runeEnvs);
12839
+ await atomicWrite(join22(dataDir, "environment-overrides.json"), flatOverrides);
12840
+ await atomicWrite(join22(dataDir, "settings.json"), newSettings);
12704
12841
  const svcEnvCount = runeEnvs.filter((e) => e.scope === "service").length;
12705
12842
  console.log(`[legacy-migration] Written: ${runeProjects.length} projects, ${runeServices.length} services, ${runeEnvs.length} environments (${svcEnvCount} service-scoped)`);
12706
12843
  console.log(`[legacy-migration] Overrides: ${Object.keys(flatOverrides).length}, custom parsers: ${migratedParsers.length} (all disabled \u2014 rewrite required)`);
@@ -12711,10 +12848,10 @@ ${p.transform ?? ""}`,
12711
12848
  }
12712
12849
  async function findLegacyKeyInBackup(dataDir) {
12713
12850
  try {
12714
- const entries = await readdir6(dataDir);
12851
+ const entries = await readdir7(dataDir);
12715
12852
  const backupDirs = entries.filter((e) => e.startsWith("backup-")).sort((a, b) => a < b ? -1 : a > b ? 1 : 0).reverse();
12716
12853
  for (const dir of backupDirs) {
12717
- const keyJsonPath = join21(dataDir, dir, "dbs", "encryption-key.json");
12854
+ const keyJsonPath = join22(dataDir, dir, "dbs", "encryption-key.json");
12718
12855
  try {
12719
12856
  const raw = await readFile16(keyJsonPath, "utf-8");
12720
12857
  const parsed = JSON.parse(raw);
@@ -12738,14 +12875,14 @@ async function runOverrideOnlyMigration(dataDir) {
12738
12875
  const abDataDir = resolve6(dataDir);
12739
12876
  const abCwd = resolve6(process.cwd());
12740
12877
  const candidateDirs = [
12741
- join21(abCwd, ".runeya", "dbs", "overrides"),
12742
- join21(abDataDir, "dbs", "overrides")
12878
+ join22(abCwd, ".runeya", "dbs", "overrides"),
12879
+ join22(abDataDir, "dbs", "overrides")
12743
12880
  ];
12744
12881
  let overridesDir = null;
12745
12882
  let overrideFiles = [];
12746
12883
  for (const dir of candidateDirs) {
12747
12884
  try {
12748
- const files = (await readdir6(dir)).filter((f) => f.endsWith(".encrypted.json"));
12885
+ const files = (await readdir7(dir)).filter((f) => f.endsWith(".encrypted.json"));
12749
12886
  if (files.length > 0) {
12750
12887
  overridesDir = dir;
12751
12888
  overrideFiles = files;
@@ -12755,7 +12892,7 @@ async function runOverrideOnlyMigration(dataDir) {
12755
12892
  }
12756
12893
  }
12757
12894
  if (!overridesDir || overrideFiles.length === 0) return false;
12758
- const legacyKeyPath = join21(overridesDir, "..", "encryption-key.json");
12895
+ const legacyKeyPath = join22(overridesDir, "..", "encryption-key.json");
12759
12896
  try {
12760
12897
  await access2(legacyKeyPath);
12761
12898
  return false;
@@ -12773,7 +12910,7 @@ async function runOverrideOnlyMigration(dataDir) {
12773
12910
  const envNameToId = {};
12774
12911
  let envsRaw;
12775
12912
  try {
12776
- envsRaw = JSON.parse(await readFile16(join21(abDataDir, "environments.json"), "utf-8"));
12913
+ envsRaw = JSON.parse(await readFile16(join22(abDataDir, "environments.json"), "utf-8"));
12777
12914
  for (const _env of envsRaw) {
12778
12915
  const env2 = _env;
12779
12916
  if (env2["name"] && env2["id"]) {
@@ -12792,7 +12929,7 @@ async function runOverrideOnlyMigration(dataDir) {
12792
12929
  let servicesRaw = [];
12793
12930
  const serviceNameToId = {};
12794
12931
  try {
12795
- servicesRaw = JSON.parse(await readFile16(join21(abDataDir, "services.json"), "utf-8"));
12932
+ servicesRaw = JSON.parse(await readFile16(join22(abDataDir, "services.json"), "utf-8"));
12796
12933
  for (const _svc of servicesRaw) {
12797
12934
  const svc = _svc;
12798
12935
  if (svc["name"] && svc["id"]) serviceNameToId[svc["name"]] = svc["id"];
@@ -12809,7 +12946,7 @@ async function runOverrideOnlyMigration(dataDir) {
12809
12946
  const envName = baseName.slice(0, -"-environment".length);
12810
12947
  let data;
12811
12948
  try {
12812
- data = await decryptLegacyFile(join21(overridesDir, file), sodiumKey, sodium);
12949
+ data = await decryptLegacyFile(join22(overridesDir, file), sodiumKey, sodium);
12813
12950
  } catch (err) {
12814
12951
  console.warn(`[override-migration] Failed to decrypt ${file}: ${err.message}`);
12815
12952
  continue;
@@ -12836,7 +12973,7 @@ async function runOverrideOnlyMigration(dataDir) {
12836
12973
  }
12837
12974
  }
12838
12975
  if (Object.keys(flatOverrides).length > 0) {
12839
- await atomicWrite(join21(abDataDir, "environment-overrides.json"), flatOverrides);
12976
+ await atomicWrite(join22(abDataDir, "environment-overrides.json"), flatOverrides);
12840
12977
  console.log(`[override-migration] Written ${Object.keys(flatOverrides).length} override(s) to environment-overrides.json`);
12841
12978
  }
12842
12979
  let envsModified = false;
@@ -12846,7 +12983,7 @@ async function runOverrideOnlyMigration(dataDir) {
12846
12983
  const serviceName = baseName.slice(0, -"-envs".length);
12847
12984
  let data;
12848
12985
  try {
12849
- data = await decryptLegacyFile(join21(overridesDir, file), sodiumKey, sodium);
12986
+ data = await decryptLegacyFile(join22(overridesDir, file), sodiumKey, sodium);
12850
12987
  } catch (err) {
12851
12988
  console.warn(`[override-migration] Failed to decrypt ${file}: ${err.message}`);
12852
12989
  continue;
@@ -12905,7 +13042,7 @@ async function runOverrideOnlyMigration(dataDir) {
12905
13042
  }
12906
13043
  }
12907
13044
  if (envsModified) {
12908
- await atomicWrite(join21(abDataDir, "environments.json"), envsRaw);
13045
+ await atomicWrite(join22(abDataDir, "environments.json"), envsRaw);
12909
13046
  console.log("[override-migration] Merged service overrides into environments.json");
12910
13047
  }
12911
13048
  const migratedDir = overridesDir.replace(/overrides$/, "overrides-migrated");
@@ -12920,8 +13057,8 @@ async function runOverrideOnlyMigration(dataDir) {
12920
13057
  }
12921
13058
 
12922
13059
  // ../server/src/services/server-state.ts
12923
- import { join as join22 } from "path";
12924
- import { stat as stat6 } from "fs/promises";
13060
+ import { join as join23 } from "path";
13061
+ import { stat as stat7 } from "fs/promises";
12925
13062
  var ENCRYPTED_KEY_FILENAME2 = ".encryption.key.enc";
12926
13063
  var VERIFY_FILENAME2 = ".runeya-verify";
12927
13064
  async function getServerState() {
@@ -12930,17 +13067,17 @@ async function getServerState() {
12930
13067
  let hasVerify = false;
12931
13068
  let hasData = false;
12932
13069
  try {
12933
- await stat6(join22(dataDir, ENCRYPTED_KEY_FILENAME2));
13070
+ await stat7(join23(dataDir, ENCRYPTED_KEY_FILENAME2));
12934
13071
  hasEncFile = true;
12935
13072
  } catch {
12936
13073
  }
12937
13074
  try {
12938
- await stat6(join22(dataDir, VERIFY_FILENAME2));
13075
+ await stat7(join23(dataDir, VERIFY_FILENAME2));
12939
13076
  hasVerify = true;
12940
13077
  } catch {
12941
13078
  }
12942
13079
  try {
12943
- await stat6(join22(dataDir, "projects.json"));
13080
+ await stat7(join23(dataDir, "projects.json"));
12944
13081
  hasData = true;
12945
13082
  } catch {
12946
13083
  }
@@ -13232,7 +13369,7 @@ function getOpenApiDocument() {
13232
13369
  // ../server/src/create-server.ts
13233
13370
  import rateLimit from "express-rate-limit";
13234
13371
  import { existsSync as existsSync2, createReadStream } from "fs";
13235
- import { mkdir as mkdir17 } from "fs/promises";
13372
+ import { mkdir as mkdir18 } from "fs/promises";
13236
13373
  import multer from "multer";
13237
13374
 
13238
13375
  // ../server/src/services/image-cleanup.service.ts
@@ -13338,7 +13475,7 @@ async function createLocalServer() {
13338
13475
  console.log("[server] Premier lancement \u2014 setup requis");
13339
13476
  }
13340
13477
  }
13341
- if (!existsSync2(env.DATA_DIR)) await mkdir17(env.DATA_DIR);
13478
+ if (!existsSync2(env.DATA_DIR)) await mkdir18(env.DATA_DIR);
13342
13479
  const absoluteDataDir = resolve5(env.DATA_DIR);
13343
13480
  console.log(`[server] Data directory: ${absoluteDataDir}`);
13344
13481
  await ensureDataGitignore(env.DATA_DIR);
@@ -14090,4 +14227,4 @@ export {
14090
14227
  createLocalServer,
14091
14228
  pullEnv
14092
14229
  };
14093
- //# sourceMappingURL=src-RMLLDYCE.js.map
14230
+ //# sourceMappingURL=src-W64XJTN5.js.map