@runeya/runeya 2.0.26 → 2.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +1 -1
- package/mcp-server/index.js +11 -1
- package/mcp-server/index.js.map +1 -1
- package/package.json +1 -1
- package/{src-RMLLDYCE.js → src-ZYEDS2TT.js} +200 -111
- package/src-ZYEDS2TT.js.map +1 -0
- package/web/assets/{AgentScalarChatInterface.vue-B_KZzo-8.js → AgentScalarChatInterface.vue-CvVAU4_Z.js} +1 -1
- package/web/assets/{AgentTerminalPage-ndvticKx.js → AgentTerminalPage-DJbjkS_P.js} +1 -1
- package/web/assets/AiChatPage-yheFOLqq.js +1 -0
- package/web/assets/{AppLayout-CnFRkZTj.js → AppLayout-CmgZhtWb.js} +1 -1
- package/web/assets/{AuditPage-YVDtFtXU.js → AuditPage-CIQXRIah.js} +1 -1
- package/web/assets/{CloudAccountPage-ClJB0qU5.js → CloudAccountPage-B-ediB1R.js} +1 -1
- package/web/assets/CloudAccountPage-CPzIsKlw.js +1 -0
- package/web/assets/{CloudMessagingPage-DgENvWzA.js → CloudMessagingPage-DvZuiSk3.js} +1 -1
- package/web/assets/{DashboardPage-C482eiCv.js → DashboardPage-Dx7xHCCP.js} +1 -1
- package/web/assets/{EditorIcon-Dg8ySf_s.js → EditorIcon-4f28vJdz.js} +1 -1
- package/web/assets/{EnvironmentForm-CiTRUTBJ.js → EnvironmentForm-CR0xHO9G.js} +1 -1
- package/web/assets/{EnvironmentFormPage-Dqa5hnlW.js → EnvironmentFormPage-qc4WT8Xk.js} +1 -1
- package/web/assets/{EnvironmentListPage-B3OqVI_j.js → EnvironmentListPage-DIjYKLDE.js} +1 -1
- package/web/assets/{EnvironmentSelector-Dal9XWeK.js → EnvironmentSelector-C3yA1kHZ.js} +1 -1
- package/web/assets/{KanbanBoardPage-nW71mkhe.js → KanbanBoardPage-DWbeil-K.js} +3 -3
- package/web/assets/{KanbanListPage-qFm1qVea.js → KanbanListPage-Drt3lxBT.js} +1 -1
- package/web/assets/{LaunchProjectPage-BEh2l7vg.js → LaunchProjectPage-DQDogPxL.js} +1 -1
- package/web/assets/{LaunchServicesPage-8t0HCM1b.js → LaunchServicesPage-Jg18jEbK.js} +1 -1
- package/web/assets/{LogViewer-hnvzA24j.js → LogViewer-DF9GVFWC.js} +1 -1
- package/web/assets/{ProcessControls-BslmIb8d.js → ProcessControls-Umt6f5xy.js} +1 -1
- package/web/assets/{ProcessDetailPage-sx7zCiOL.js → ProcessDetailPage-CTljkKd4.js} +1 -1
- package/web/assets/{ProcessMetrics-5B5NTsgM.js → ProcessMetrics-XANBf0Qk.js} +1 -1
- package/web/assets/{ProjectDetailPage-BBs_J0v9.js → ProjectDetailPage-tYK7WVg5.js} +1 -1
- package/web/assets/{ProjectListPage-DhSuz5cs.js → ProjectListPage-Bl2xRUn8.js} +1 -1
- package/web/assets/{RandomJobTestPage-CWQxTxLF.js → RandomJobTestPage-D-1h_Jn0.js} +1 -1
- package/web/assets/{ScenarioEditorPage-g75I_CUT.js → ScenarioEditorPage-AYudLHpb.js} +1 -1
- package/web/assets/{SendToChatDialog-BP9nGBEk.js → SendToChatDialog-Cy3nX2xD.js} +1 -1
- package/web/assets/{ServiceControlsBar-whVRwpUj.js → ServiceControlsBar-CXk2ltIc.js} +1 -1
- package/web/assets/{ServiceDetailPage-Dh29DyAa.js → ServiceDetailPage-guE9lv3J.js} +1 -1
- package/web/assets/{ServiceFormPage-CFL2nxZR.js → ServiceFormPage-BfhD3cHh.js} +1 -1
- package/web/assets/{SettingsPage-nr9OZJIz.js → SettingsPage-B1egv0Qi.js} +4 -4
- package/web/assets/{SetupPage-Dcy0GjX7.js → SetupPage-DDqjtbHe.js} +1 -1
- package/web/assets/{UnlockPage-tYJaGOvI.js → UnlockPage-B9V18Hw8.js} +1 -1
- package/web/assets/{VariablesTable-BBDWTOYZ.js → VariablesTable-B4z_Cvs6.js} +1 -1
- package/web/assets/{VersionBadge-CGyYH_by.js → VersionBadge-D5Im-g6k.js} +1 -1
- package/web/assets/WikiPage-CwULGndV.js +1 -0
- package/web/assets/{WikiView-5wBXk2lk.js → WikiView-BkAYyIky.js} +1 -1
- package/web/assets/{add-scalar-classes-C7nbOHKD.js → add-scalar-classes-wf0v84bl.js} +3 -3
- package/web/assets/auth-errors-_nnUuMls.js +1 -0
- package/web/assets/{autocomplete-CHr6XiGG.js → autocomplete-Cl85AjsC.js} +1 -1
- package/web/assets/{basic-shape-diamond.svg-CQFXP3CL.js → basic-shape-diamond.svg-EjFsbEU6.js} +1 -1
- package/web/assets/{basic-shape-hexagon.svg-C2hTaagp.js → basic-shape-hexagon.svg-BSGF96h_.js} +1 -1
- package/web/assets/{basic-shape-primary-circle-ellipse-round.svg-Lp9PV6vm.js → basic-shape-primary-circle-ellipse-round.svg-DzhBsSTr.js} +1 -1
- package/web/assets/{basic-shape-primary-square-rectangle.svg-DMA94QXi.js → basic-shape-primary-square-rectangle.svg-D8s7AAg0.js} +1 -1
- package/web/assets/{basic-shape-shield.svg-Cp-URfqN.js → basic-shape-shield.svg-CZVfGGSa.js} +1 -1
- package/web/assets/{browser-R78oyZdY.js → browser-BJbPa5wA.js} +1 -1
- package/web/assets/{browser-DM3iXlbN.js → browser-DeK7cxfP.js} +1 -1
- package/web/assets/{card-CcZ0arNi.js → card-C8VZemYn.js} +1 -1
- package/web/assets/{checkbox-BCOmnJDd.js → checkbox-CHlXPfVG.js} +1 -1
- package/web/assets/{chip-CLglXPrW.js → chip-BIf8nQZp.js} +1 -1
- package/web/assets/{client-BRARg69s.js → client-Ck5Tf_q2.js} +1 -1
- package/web/assets/{cloud-chat.store-DsBjdn8r.js → cloud-chat.store-qtVT5SrP.js} +1 -1
- package/web/assets/{cloud-client-BjhezdPl.js → cloud-client-DZDFCmz5.js} +1 -1
- package/web/assets/{column-FgSQ7Ooe.js → column-DzFOwR4r.js} +1 -1
- package/web/assets/{computer-device-desktop-monitor.svg-CYL6u5mH.js → computer-device-desktop-monitor.svg-DZQuEpZF.js} +1 -1
- package/web/assets/{computer-device-desktop.svg-CciCwLWn.js → computer-device-desktop.svg-CEjLM8aJ.js} +1 -1
- package/web/assets/{computer-device-laptop.svg-D8BtF9-Q.js → computer-device-laptop.svg-DXtolGzW.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-android-samsung-back.svg-BmEWWRuj.js → computer-device-mobile-phone-android-samsung-back.svg-BSwre-M8.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-android-samsung.svg-D3qSNQ6Y.js → computer-device-mobile-phone-android-samsung.svg-BGERJFfo.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-iphone-x-back.svg-CLQN3uCp.js → computer-device-mobile-phone-iphone-x-back.svg-B4hZe_83.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-iphone-x.svg-D3cl8j8P.js → computer-device-mobile-phone-iphone-x.svg-CWALzaq5.js} +1 -1
- package/web/assets/{computer-device-mobile-tablet-touch.svg-DgXs1pg2.js → computer-device-mobile-tablet-touch.svg-CKFDix2A.js} +1 -1
- package/web/assets/{computer-device-mobile-tablet.svg-CfvVaE3u.js → computer-device-mobile-tablet.svg-PW6AfYK8.js} +1 -1
- package/web/assets/{computer-device-network-ethernet-cat6.svg-iYYvLcHU.js → computer-device-network-ethernet-cat6.svg-Mv5w5TOF.js} +1 -1
- package/web/assets/{computer-device-network-lan-www.svg-toPtLNio.js → computer-device-network-lan-www.svg-8StLkiX8.js} +1 -1
- package/web/assets/{computer-device-network-wifi-connection.svg-BKG_lmw-.js → computer-device-network-wifi-connection.svg-BeLrrgP7.js} +1 -1
- package/web/assets/{computer-device-network-wifi-router.svg-C_LasCGv.js → computer-device-network-wifi-router.svg-CJiZPTY7.js} +1 -1
- package/web/assets/{cssMode-DwX_16yK.js → cssMode-BhLSG915.js} +1 -1
- package/web/assets/{divider-BHEOMimj.js → divider-Bqt4F4Qp.js} +1 -1
- package/web/assets/{ecology-science-erlenmeyer-flask.svg-nXdT6R9m.js → ecology-science-erlenmeyer-flask.svg-BbZXykYT.js} +1 -1
- package/web/assets/{fieldset-QLx4mQkZ.js → fieldset-Ckk9RxbZ.js} +1 -1
- package/web/assets/{freemarker2-CSMe-vN6.js → freemarker2-BMY7vTsn.js} +1 -1
- package/web/assets/{handlebars-Bis7UE_1.js → handlebars-dL1R3--H.js} +1 -1
- package/web/assets/{html-FpLm2caJ.js → html-344qni_p.js} +1 -1
- package/web/assets/{htmlMode-Baynpw1v.js → htmlMode-DofkmDyO.js} +1 -1
- package/web/assets/{image-flash-lightning.svg-C7Bnv9Mm.js → image-flash-lightning.svg-CUKVp-AP.js} +1 -1
- package/web/assets/{image-picture-flower.svg-BL5-DHnt.js → image-picture-flower.svg-D8v_AWKn.js} +1 -1
- package/web/assets/{index-Cs0Kif7Q.js → index-0h6-JSBE.js} +5 -5
- package/web/assets/{index-gKo3WNkm.css → index-DtsVLZzz.css} +1 -1
- package/web/assets/{interface-alert-exclamation-diamond.svg-D9nvt_Hu.js → interface-alert-exclamation-diamond.svg-Svf3SQNi.js} +1 -1
- package/web/assets/{interface-alert-exclamation-triangle-warning.svg-sdDhzltb.js → interface-alert-exclamation-triangle-warning.svg-BONYDBCR.js} +1 -1
- package/web/assets/{interface-alert-information-circle.svg-DOUCLFeO.js → interface-alert-information-circle.svg-DjtyOApC.js} +1 -1
- package/web/assets/{interface-award-crown.svg-Wow8nL3E.js → interface-award-crown.svg-CYsHquI5.js} +1 -1
- package/web/assets/{interface-bookmark.svg-BR9pVTGo.js → interface-bookmark-tag.svg-BuQVffZJ.js} +1 -1
- package/web/assets/{interface-bookmark-tag.svg-PCXmDEX1.js → interface-bookmark.svg-Dq6ycrvL.js} +1 -1
- package/web/assets/{interface-calendar-date-one.svg-D351Q6D_.js → interface-calendar-date-one.svg-DByu3wOg.js} +1 -1
- package/web/assets/{interface-content-book-open-pages.svg-LauiqjTE.js → interface-content-book-open-pages.svg-B26NylpB.js} +1 -1
- package/web/assets/{interface-content-book-page.svg-B6Zfht7n.js → interface-content-book-page.svg-BB2ivXh0.js} +1 -1
- package/web/assets/{interface-content-file.svg-Cc5_wl5Z.js → interface-content-file.svg-gFnNuymA.js} +1 -1
- package/web/assets/{interface-content-folder.svg-Ciep79Ki.js → interface-content-folder.svg-DvbImJww.js} +1 -1
- package/web/assets/interface-content-folder.svg-oUFH-WWC.js +1 -0
- package/web/assets/{interface-copy-clipboard.svg-Bi8uG7D0.js → interface-copy-clipboard.svg-Bp4l9Qod.js} +1 -1
- package/web/assets/{interface-edit-attachment.svg-BNMsIztI.js → interface-edit-attachment.svg-cayiblt2.js} +1 -1
- package/web/assets/{interface-edit-binocular.svg-D882_fLM.js → interface-edit-binocular.svg-BvIiESbT.js} +1 -1
- package/web/assets/{interface-edit-magic-wand.svg-kUvxy3Ks.js → interface-edit-magic-wand.svg-Bvfkkoft.js} +1 -1
- package/web/assets/{interface-edit-tool-paint-roller.svg-8nu7qB8G.js → interface-edit-tool-paint-roller.svg-Dnoz9W9m.js} +1 -1
- package/web/assets/{interface-edit-tool-pencil.svg-DZB0qoKo.js → interface-edit-tool-pencil.svg-aKau4_Jj.js} +1 -1
- package/web/assets/{interface-favorite-award.svg-DHqTPxV_.js → interface-favorite-award.svg-DBvY_ky_.js} +1 -1
- package/web/assets/{interface-favorite-flag.svg-YKqwesbX.js → interface-favorite-flag.svg-CBdbLlXI.js} +1 -1
- package/web/assets/{interface-favorite-heart.svg-cBkyRnE5.js → interface-favorite-heart.svg-CB_C7DqH.js} +1 -1
- package/web/assets/{interface-favorite-star.svg-GoY_laGz.js → interface-favorite-star.svg-CtD9k4PE.js} +1 -1
- package/web/assets/{interface-favorite-stars-sparkles.svg-BqdOFD5D.js → interface-favorite-stars-sparkles.svg-tL8H5LKH.js} +1 -1
- package/web/assets/{interface-hierarchy-flowchart.svg-Ds0On5Qa.js → interface-hierarchy-flowchart.svg-DDZfke0l.js} +1 -1
- package/web/assets/{interface-home-house.svg-DF-MwqfJ.js → interface-home-house.svg-928LKnoh.js} +1 -1
- package/web/assets/{interface-hyperlink.svg-DDtgdY8L.js → interface-hyperlink.svg-BVJBa9KF.js} +1 -1
- package/web/assets/{interface-lighting-brightness.svg-DfnVOk46.js → interface-lighting-brightness.svg-C6DvgPRs.js} +1 -1
- package/web/assets/{interface-lock-closed.svg-2p6rXOTh.js → interface-lock-closed.svg-NFylzPTC.js} +1 -1
- package/web/assets/{interface-lock-open-unlock.svg-CB9k9qWL.js → interface-lock-open-unlock.svg-EmxIAQyQ.js} +1 -1
- package/web/assets/{interface-login-key.svg-pHYzdJ1o.js → interface-login-key.svg-C0nFw-iu.js} +1 -1
- package/web/assets/{interface-search.svg-D8hHBPas.js → interface-search.svg-1Gq_uSPL.js} +1 -1
- package/web/assets/{interface-setting-cog.svg-B_jKaveW.js → interface-setting-cog.svg-3dq-AXqL.js} +1 -1
- package/web/assets/{interface-share-megaphone-bullhorn.svg-Ci3LdXFu.js → interface-share-megaphone-bullhorn.svg-Bb4qoyBo.js} +1 -1
- package/web/assets/{interface-share-rocket.svg-CzO2_rpx.js → interface-share-rocket.svg-1hUkfTAV.js} +1 -1
- package/web/assets/{interface-share-satellite.svg-fKexToHv.js → interface-share-satellite.svg-C1fkGxMj.js} +1 -1
- package/web/assets/{interface-share-space-ship.svg-BT1Lk7Tt.js → interface-share-space-ship.svg-DCtyIZvd.js} +1 -1
- package/web/assets/{interface-share.svg-hZMfrZ-3.js → interface-share.svg-D27oW8Dd.js} +1 -1
- package/web/assets/{interface-signal-square.svg-DgUPwC3Q.js → interface-signal-square.svg-DHNLXoLB.js} +1 -1
- package/web/assets/{interface-time-clock-circle.svg-Drt6jIhl.js → interface-time-clock-circle.svg-DVFfhzi_.js} +1 -1
- package/web/assets/{interface-time-hour-glass.svg-s9MiHuuW.js → interface-time-hour-glass.svg-J2kAIY5_.js} +1 -1
- package/web/assets/{interface-users-multiple.svg-nNndHPrE.js → interface-users-multiple.svg-CT_rq2cA.js} +1 -1
- package/web/assets/{interface-weather-moon.svg-NldiRdQl.js → interface-weather-moon.svg-DmUulEez.js} +1 -1
- package/web/assets/{javascript-CM-wGFHc.js → javascript-DJEY0PGT.js} +1 -1
- package/web/assets/{jsonMode-aOR4N_b0.js → jsonMode-Bf1QPhve.js} +1 -1
- package/web/assets/{liquid-BOq1gC95.js → liquid-BvlkiSX0.js} +1 -1
- package/web/assets/{lspLanguageFeatures-DkYyaTsO.js → lspLanguageFeatures-Blscl7vz.js} +1 -1
- package/web/assets/{mail-chat-bubble-square.svg-DvVS1XL8.js → mail-chat-bubble-square.svg-oLN5_z0h.js} +1 -1
- package/web/assets/{mail-send-email-paper-airplane.svg-CuW-5AUM.js → mail-send-email-paper-airplane.svg-B__7_Vor.js} +1 -1
- package/web/assets/{mail-send-envelope.svg-BYjdrhQf.js → mail-send-envelope.svg-DUobbjXC.js} +1 -1
- package/web/assets/{mdx-YUd1hDI8.js → mdx-fAQ2xk7o.js} +1 -1
- package/web/assets/{message-RIbjiwWI.js → message-V1S0zxyl.js} +1 -1
- package/web/assets/{minus-Zsjs3YsO.js → minus-DQocLKZ2.js} +1 -1
- package/web/assets/modal-Cun3B13H.js +1 -0
- package/web/assets/{modal-BHrcmOl4.js → modal-Jd8c3A1o.js} +1 -1
- package/web/assets/{money-cashier-receipt.svg-DEW1cqpI.js → money-cashier-receipt.svg-Cj5pLd3R.js} +1 -1
- package/web/assets/{money-currency-dollar-pay.svg-BFtCVQ4S.js → money-currency-dollar-pay.svg-D85nPq3p.js} +1 -1
- package/web/assets/{money-graph-arrow-increase.svg-CS3r0Qo6.js → money-graph-arrow-increase.svg-B-jecr0K.js} +1 -1
- package/web/assets/{money-graph-bar-chart-increase.svg-DNIgFkKV.js → money-graph-bar-chart-increase.svg-mL9YQSKx.js} +1 -1
- package/web/assets/{multiselect-CwmFqved.js → multiselect-BDZrrJVC.js} +1 -1
- package/web/assets/{nature-ecology-leaf.svg-cPeHW34n.js → nature-ecology-leaf.svg-C5PATFHo.js} +1 -1
- package/web/assets/{password-7qWpH9BB.js → password-CBpcX5yn.js} +1 -1
- package/web/assets/{phone-telephone.svg-h2lh8fwJ.js → phone-telephone.svg-6VIpvy-y.js} +1 -1
- package/web/assets/{plus-DqPH0Iv8.js → plus-B2jxpOLU.js} +1 -1
- package/web/assets/process.store-IRJbG3V3.js +1 -0
- package/web/assets/{programming-bug.svg-D0ITlO1h.js → programming-bug.svg-BcxVR8s8.js} +1 -1
- package/web/assets/{programming-cloud.svg-BNlUQPiK.js → programming-cloud.svg-k8vesSUP.js} +1 -1
- package/web/assets/{programming-computer-database-server.svg-DNCYdfSh.js → programming-computer-database-server.svg-C3BxhLIn.js} +1 -1
- package/web/assets/{programming-computer-database.svg-C2PW1bUW.js → programming-computer-database.svg-D5JgkHxk.js} +1 -1
- package/web/assets/{programming-module-four-layout.svg-CKY7NXvl.js → programming-module-four-layout.svg-QPzWv5-h.js} +1 -1
- package/web/assets/{programming-module-three.svg-NcqUbSS6.js → programming-module-three.svg-C8sC64dR.js} +1 -1
- package/web/assets/{programming-module.svg-BX5p0lLV.js → programming-module.svg-3IM9Ieau.js} +1 -1
- package/web/assets/{programming-script-code.svg-FHWm2rne.js → programming-script-code.svg-CcSjILXf.js} +1 -1
- package/web/assets/{python-C37IESl6.js → python-izcQtunc.js} +1 -1
- package/web/assets/{radiobutton-F-xRsgnr.js → radiobutton-DkaY7vPf.js} +1 -1
- package/web/assets/{razor-_Te1Aj6k.js → razor-B8B2Hdv1.js} +1 -1
- package/web/assets/router-DVcld2uT.js +1 -0
- package/web/assets/{settings.store-CksXXR3U.js → settings.store-BnyuJ8Z0.js} +1 -1
- package/web/assets/{shopping-cart.svg-nxP9rCyK.js → shopping-cart.svg-Cd1oC6MU.js} +1 -1
- package/web/assets/{shopping-gift-present.svg-ClmlE4Uh.js → shopping-gift-present.svg-DADsc6IL.js} +1 -1
- package/web/assets/{shopping-shipping-box-parcel-package.svg-DXq6ggt9.js → shopping-shipping-box-parcel-package.svg-RgU1qCOk.js} +1 -1
- package/web/assets/{src-BrtEkCm_.js → src-DWLyvNxu.js} +1 -1
- package/web/assets/{src-Bbg8H9bl.js → src-DaE_IxON.js} +1 -1
- package/web/assets/{tabpanel-2V5hCrRK.js → tabpanel-ps1UcMpu.js} +1 -1
- package/web/assets/{tag-new-circle.svg-DBcjhg2n.js → tag-new-circle.svg-Ct1vN4KR.js} +1 -1
- package/web/assets/{travel-map-earth-globe.svg-DK0DzkkV.js → travel-map-earth-globe.svg-DES-h7fX.js} +1 -1
- package/web/assets/trpc-DL-TIO_-.js +1 -0
- package/web/assets/{tsMode-CRQCVE9O.js → tsMode-n-LTfcYC.js} +1 -1
- package/web/assets/{typescript-CPx1WzXO.js → typescript-2xBvBpwO.js} +1 -1
- package/web/assets/useAiChatDrawer-9vufna_G.js +1 -0
- package/web/assets/useCloudOrg-9Z9ojaI7.js +1 -0
- package/web/assets/useCloudOrg-BEGIZ5Sw.css +1 -0
- package/web/assets/{xml-Cnip_4it.js → xml-DNDCpyoa.js} +1 -1
- package/web/assets/{yaml-7jJDr7sS.js → yaml-BWEYJIfa.js} +1 -1
- package/web/favicon.svg +5 -0
- package/web/index.html +3 -3
- package/src-RMLLDYCE.js.map +0 -1
- package/web/assets/AiChatPage-DVKgrycM.js +0 -1
- package/web/assets/CloudAccountPage-F7I3BMuf.js +0 -1
- package/web/assets/WikiPage-DB4eTOyt.js +0 -1
- package/web/assets/auth-errors-B9MBlYUv.js +0 -1
- package/web/assets/interface-content-folder.svg-Bp_Aw__A.js +0 -1
- package/web/assets/modal-D_7Abefo.js +0 -1
- package/web/assets/process.store-6-gnKm4b.js +0 -1
- package/web/assets/router-DMhgRTT4.js +0 -1
- package/web/assets/trpc-BVEjpY_n.js +0 -1
- package/web/assets/useAiChatDrawer-Bv5obLR8.js +0 -1
- package/web/assets/useCloudOrg-19tv3A6Y.css +0 -1
- package/web/assets/useCloudOrg-Bm3KQ05h.js +0 -1
|
@@ -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
|
-
|
|
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"];
|
|
@@ -5820,6 +5831,11 @@ function addComment(board, cardId, comment, conversationId) {
|
|
|
5820
5831
|
}
|
|
5821
5832
|
}
|
|
5822
5833
|
}
|
|
5834
|
+
function formatSize(bytes) {
|
|
5835
|
+
if (bytes < 1024) return `${bytes} o`;
|
|
5836
|
+
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} Ko`;
|
|
5837
|
+
return `${(bytes / (1024 * 1024)).toFixed(1).replace(".", ",")} Mo`;
|
|
5838
|
+
}
|
|
5823
5839
|
function generateKanbanSystemPrompt(board, cardId) {
|
|
5824
5840
|
let currentColTitle = "";
|
|
5825
5841
|
let card = null;
|
|
@@ -5857,11 +5873,27 @@ function generateKanbanSystemPrompt(board, cardId) {
|
|
|
5857
5873
|
for (const c of comments.slice(-20)) {
|
|
5858
5874
|
const who = c.author === "ai" ? "AI" : "Utilisateur";
|
|
5859
5875
|
const date = new Date(c.timestamp).toLocaleString("fr-FR", { day: "numeric", month: "short", hour: "2-digit", minute: "2-digit" });
|
|
5860
|
-
|
|
5876
|
+
const files = (c.attachments ?? []).map((f) => `\`${f.id}\` ${f.name}`).join(", ");
|
|
5877
|
+
lines.push(`- **${who}** (${date}) : ${c.detail}${files ? ` \u2014 pi\xE8ces jointes : ${files}` : ""}`);
|
|
5861
5878
|
}
|
|
5862
5879
|
lines.push("");
|
|
5863
5880
|
}
|
|
5864
5881
|
}
|
|
5882
|
+
if (card) {
|
|
5883
|
+
const files = card.attachments ?? [];
|
|
5884
|
+
const commentFiles = (card.history ?? []).flatMap((e) => e.attachments ?? []);
|
|
5885
|
+
const all = [...files, ...commentFiles];
|
|
5886
|
+
if (all.length > 0) {
|
|
5887
|
+
lines.push(`### Pi\xE8ces jointes disponibles (${all.length})`);
|
|
5888
|
+
lines.push("");
|
|
5889
|
+
for (const f of all) {
|
|
5890
|
+
lines.push(`- \`${f.id}\` \u2014 ${f.name} (${f.contentType}, ${formatSize(f.size)})`);
|
|
5891
|
+
}
|
|
5892
|
+
lines.push("");
|
|
5893
|
+
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.");
|
|
5894
|
+
lines.push("");
|
|
5895
|
+
}
|
|
5896
|
+
}
|
|
5865
5897
|
lines.push("### Outils Kanban disponibles");
|
|
5866
5898
|
lines.push("");
|
|
5867
5899
|
lines.push(`- **boardId** (\xE0 passer dans tous les outils) : \`${board.id}\``);
|
|
@@ -5870,6 +5902,7 @@ function generateKanbanSystemPrompt(board, cardId) {
|
|
|
5870
5902
|
lines.push("Tu disposes des outils suivants pour interagir avec le board :");
|
|
5871
5903
|
lines.push("- `kanban_move_card(boardId, cardId, targetColumn)` \u2014 D\xE9placer la carte vers une autre colonne");
|
|
5872
5904
|
lines.push("- `kanban_add_comment(boardId, cardId, comment)` \u2014 Ajouter un commentaire sur la carte");
|
|
5905
|
+
lines.push("- `kanban_download_attachment(attachmentId)` \u2014 T\xE9l\xE9charger une pi\xE8ce jointe et obtenir son chemin local");
|
|
5873
5906
|
lines.push("");
|
|
5874
5907
|
lines.push("### OBLIGATOIRE \u2014 D\xE9cision Kanban");
|
|
5875
5908
|
lines.push("");
|
|
@@ -10855,7 +10888,10 @@ var kanbanQueueRouter = router({
|
|
|
10855
10888
|
});
|
|
10856
10889
|
|
|
10857
10890
|
// ../server/src/trpc/routers/kanban.ts
|
|
10891
|
+
import { mkdir as mkdir14, writeFile as writeFile11 } from "fs/promises";
|
|
10892
|
+
import { join as join16 } from "path";
|
|
10858
10893
|
import { z as z20 } from "zod";
|
|
10894
|
+
import { TRPCError as TRPCError17 } from "@trpc/server";
|
|
10859
10895
|
function summarizeCard(card, boardId, columnTitle) {
|
|
10860
10896
|
return {
|
|
10861
10897
|
boardId,
|
|
@@ -10866,6 +10902,13 @@ function summarizeCard(card, boardId, columnTitle) {
|
|
|
10866
10902
|
assignees: (card.assignees ?? []).map((a) => a.name),
|
|
10867
10903
|
commentCount: (card.history ?? []).filter((e) => e.type === "comment").length,
|
|
10868
10904
|
attachmentCount: (card.attachments ?? []).length,
|
|
10905
|
+
// Metadata only — the bytes are fetched on demand by `downloadAttachment`.
|
|
10906
|
+
attachments: (card.attachments ?? []).map((f) => ({
|
|
10907
|
+
id: f.id,
|
|
10908
|
+
name: f.name,
|
|
10909
|
+
contentType: f.contentType,
|
|
10910
|
+
size: f.size
|
|
10911
|
+
})),
|
|
10869
10912
|
createdAt: card.createdAt,
|
|
10870
10913
|
updatedAt: card.updatedAt
|
|
10871
10914
|
};
|
|
@@ -10887,6 +10930,15 @@ function boardCounts(board) {
|
|
|
10887
10930
|
function normalize(value) {
|
|
10888
10931
|
return value.normalize("NFD").replace(new RegExp("\\p{Diacritic}", "gu"), "").toLowerCase();
|
|
10889
10932
|
}
|
|
10933
|
+
var ATTACHMENT_ID_REGEX = /^[A-Za-z0-9_-]{1,128}$/;
|
|
10934
|
+
var MAX_ATTACHMENT_BYTES = 55 * 1024 * 1024;
|
|
10935
|
+
function attachmentCacheDir() {
|
|
10936
|
+
return join16(env.DATA_DIR, "kanban-attachments");
|
|
10937
|
+
}
|
|
10938
|
+
function safeLocalName(id, name) {
|
|
10939
|
+
const ext = /\.([A-Za-z0-9]{1,12})$/.exec(name)?.[1];
|
|
10940
|
+
return ext ? `${id}.${ext.toLowerCase()}` : id;
|
|
10941
|
+
}
|
|
10890
10942
|
var kanbanRouter = router({
|
|
10891
10943
|
/**
|
|
10892
10944
|
* The organization's boards, without their cards — a board carries its whole
|
|
@@ -10976,12 +11028,49 @@ var kanbanRouter = router({
|
|
|
10976
11028
|
{ type: "add_card", columnTitle: input.column, cardTitle: input.title, cardContent: input.content }
|
|
10977
11029
|
]);
|
|
10978
11030
|
return { ok: true };
|
|
11031
|
+
}),
|
|
11032
|
+
/**
|
|
11033
|
+
* Fetch one card attachment from the cloud and drop it on this machine, so an
|
|
11034
|
+
* agent can open it with its own file tools. The bytes never go through the
|
|
11035
|
+
* prompt: the card context lists the attachments, this returns a path.
|
|
11036
|
+
*/
|
|
11037
|
+
downloadAttachment: protectedProcedure.input(z20.object({ attachmentId: z20.string().max(128) })).mutation(async ({ input }) => {
|
|
11038
|
+
const id = input.attachmentId;
|
|
11039
|
+
if (!ATTACHMENT_ID_REGEX.test(id)) {
|
|
11040
|
+
throw new TRPCError17({ code: "BAD_REQUEST", message: "Invalid attachment id" });
|
|
11041
|
+
}
|
|
11042
|
+
const res = await cloudFetch(`/api/kanban/file/${id}`, { timeoutMs: 12e4 });
|
|
11043
|
+
if (res.status === 404) {
|
|
11044
|
+
throw new TRPCError17({ code: "NOT_FOUND", message: `Attachment ${id} not found` });
|
|
11045
|
+
}
|
|
11046
|
+
if (!res.ok) {
|
|
11047
|
+
throw new TRPCError17({
|
|
11048
|
+
code: res.status === 403 ? "FORBIDDEN" : "INTERNAL_SERVER_ERROR",
|
|
11049
|
+
message: `Cloud refused the attachment (HTTP ${res.status})`
|
|
11050
|
+
});
|
|
11051
|
+
}
|
|
11052
|
+
const declared = Number(res.headers.get("content-length") ?? 0);
|
|
11053
|
+
if (declared > MAX_ATTACHMENT_BYTES) {
|
|
11054
|
+
throw new TRPCError17({ code: "PAYLOAD_TOO_LARGE", message: "Attachment too large to download" });
|
|
11055
|
+
}
|
|
11056
|
+
const body = Buffer.from(await res.arrayBuffer());
|
|
11057
|
+
if (body.length > MAX_ATTACHMENT_BYTES) {
|
|
11058
|
+
throw new TRPCError17({ code: "PAYLOAD_TOO_LARGE", message: "Attachment too large to download" });
|
|
11059
|
+
}
|
|
11060
|
+
const contentType = res.headers.get("content-type") ?? "application/octet-stream";
|
|
11061
|
+
const disposition = res.headers.get("content-disposition") ?? "";
|
|
11062
|
+
const name = /filename="([^"]*)"/.exec(disposition)?.[1] || id;
|
|
11063
|
+
const dir = attachmentCacheDir();
|
|
11064
|
+
await mkdir14(dir, { recursive: true });
|
|
11065
|
+
const path = join16(dir, safeLocalName(id, name));
|
|
11066
|
+
await writeFile11(path, body);
|
|
11067
|
+
return { path, name, contentType, size: body.length };
|
|
10979
11068
|
})
|
|
10980
11069
|
});
|
|
10981
11070
|
|
|
10982
11071
|
// ../server/src/trpc/routers/terminal.ts
|
|
10983
11072
|
import { z as z21 } from "zod";
|
|
10984
|
-
import { TRPCError as
|
|
11073
|
+
import { TRPCError as TRPCError18 } from "@trpc/server";
|
|
10985
11074
|
var terminalRouter = router({
|
|
10986
11075
|
/** Create a PTY shell session on the target agent */
|
|
10987
11076
|
create: protectedProcedure.input(z21.object({
|
|
@@ -11066,7 +11155,7 @@ var terminalRouter = router({
|
|
|
11066
11155
|
}
|
|
11067
11156
|
);
|
|
11068
11157
|
} catch (err) {
|
|
11069
|
-
throw new
|
|
11158
|
+
throw new TRPCError18({
|
|
11070
11159
|
code: "BAD_REQUEST",
|
|
11071
11160
|
message: `Cannot subscribe to terminal: ${err.message}`
|
|
11072
11161
|
});
|
|
@@ -11101,9 +11190,9 @@ var utilityRouter = router({
|
|
|
11101
11190
|
|
|
11102
11191
|
// ../server/src/trpc/routers/wiki.ts
|
|
11103
11192
|
import { z as z23 } from "zod";
|
|
11104
|
-
import { TRPCError as
|
|
11105
|
-
import { readFile as readFile13, readdir as readdir5, stat as stat3, realpath, writeFile as
|
|
11106
|
-
import { resolve as resolvePath, join as
|
|
11193
|
+
import { TRPCError as TRPCError19 } from "@trpc/server";
|
|
11194
|
+
import { readFile as readFile13, readdir as readdir5, stat as stat3, realpath, writeFile as writeFile12, mkdir as mkdir15, rename as rename10, rm as rm2 } from "fs/promises";
|
|
11195
|
+
import { resolve as resolvePath, join as join17, relative, sep as sep3, dirname as dirname3 } from "path";
|
|
11107
11196
|
var SCOPE_SCHEMA = z23.union([
|
|
11108
11197
|
z23.literal("global"),
|
|
11109
11198
|
z23.string().regex(/^service:[A-Za-z0-9_-]{1,128}$/, "Invalid service scope")
|
|
@@ -11137,27 +11226,27 @@ async function resolveScope(scope) {
|
|
|
11137
11226
|
const settings = await settingsManager.getSettings();
|
|
11138
11227
|
const sub = (settings.globalDocsPath?.trim() || "wiki").replace(/^[\\/]+|[\\/]+$/g, "");
|
|
11139
11228
|
if (sub.includes("..") || sub.includes("\0")) {
|
|
11140
|
-
throw new
|
|
11229
|
+
throw new TRPCError19({ code: "BAD_REQUEST", message: "Sous-chemin invalide" });
|
|
11141
11230
|
}
|
|
11142
11231
|
const dataDirAbs = resolvePath(env.DATA_DIR);
|
|
11143
|
-
await
|
|
11232
|
+
await mkdir15(dataDirAbs, { recursive: true });
|
|
11144
11233
|
const base = dirname3(await realpath(dataDirAbs));
|
|
11145
11234
|
const target = resolvePath(base, sub);
|
|
11146
11235
|
if (target !== base && !(target + sep3).startsWith(base + sep3)) {
|
|
11147
|
-
throw new
|
|
11236
|
+
throw new TRPCError19({ code: "FORBIDDEN", message: "Hors du dossier de donn\xE9es du serveur" });
|
|
11148
11237
|
}
|
|
11149
|
-
await
|
|
11238
|
+
await mkdir15(target, { recursive: true });
|
|
11150
11239
|
const root = await realpath(target);
|
|
11151
11240
|
if (root !== base && !(root + sep3).startsWith(base + sep3)) {
|
|
11152
|
-
throw new
|
|
11241
|
+
throw new TRPCError19({ code: "FORBIDDEN", message: "Le dossier wiki r\xE9sout hors du dossier de donn\xE9es" });
|
|
11153
11242
|
}
|
|
11154
11243
|
return { mode: "local", root };
|
|
11155
11244
|
}
|
|
11156
11245
|
const serviceId = scope.slice("service:".length);
|
|
11157
11246
|
const service = await serviceStore.get(serviceId);
|
|
11158
|
-
if (!service) throw new
|
|
11247
|
+
if (!service) throw new TRPCError19({ code: "NOT_FOUND", message: "Service introuvable" });
|
|
11159
11248
|
const agentId = await resolveEffectiveAgentId(service);
|
|
11160
|
-
if (!agentId) throw new
|
|
11249
|
+
if (!agentId) throw new TRPCError19({ code: "BAD_REQUEST", message: "Aucun agent configur\xE9 pour ce service" });
|
|
11161
11250
|
const cwd = (service.docsPath?.trim() || service.cwd || ".").toString();
|
|
11162
11251
|
return { mode: "agent", agentId, cwd };
|
|
11163
11252
|
}
|
|
@@ -11173,7 +11262,7 @@ async function walkLocal(root, dir, depth, counter) {
|
|
|
11173
11262
|
for (const e of entries) {
|
|
11174
11263
|
if (counter.n >= MAX_FILES) break;
|
|
11175
11264
|
if (e.name.startsWith(".") && e.name !== ".") continue;
|
|
11176
|
-
const abs =
|
|
11265
|
+
const abs = join17(dir, e.name);
|
|
11177
11266
|
const rel = relative(root, abs).split(sep3).join("/");
|
|
11178
11267
|
if (e.isDirectory()) {
|
|
11179
11268
|
if (IGNORED_DIRS.has(e.name)) continue;
|
|
@@ -11192,7 +11281,7 @@ async function walkLocal(root, dir, depth, counter) {
|
|
|
11192
11281
|
}
|
|
11193
11282
|
async function resolveSafeLocal(root, relPath, requireExist) {
|
|
11194
11283
|
if (relPath.includes("..") || relPath.startsWith("/")) {
|
|
11195
|
-
throw new
|
|
11284
|
+
throw new TRPCError19({ code: "BAD_REQUEST", message: "Chemin invalide" });
|
|
11196
11285
|
}
|
|
11197
11286
|
const target = resolvePath(root, relPath);
|
|
11198
11287
|
if (requireExist) {
|
|
@@ -11200,10 +11289,10 @@ async function resolveSafeLocal(root, relPath, requireExist) {
|
|
|
11200
11289
|
try {
|
|
11201
11290
|
real = await realpath(target);
|
|
11202
11291
|
} catch {
|
|
11203
|
-
throw new
|
|
11292
|
+
throw new TRPCError19({ code: "NOT_FOUND", message: "Chemin introuvable" });
|
|
11204
11293
|
}
|
|
11205
11294
|
if (real !== root && !(real + sep3).startsWith(root + sep3)) {
|
|
11206
|
-
throw new
|
|
11295
|
+
throw new TRPCError19({ code: "FORBIDDEN", message: "Hors du dossier autoris\xE9" });
|
|
11207
11296
|
}
|
|
11208
11297
|
return real;
|
|
11209
11298
|
}
|
|
@@ -11215,7 +11304,7 @@ async function resolveSafeLocal(root, relPath, requireExist) {
|
|
|
11215
11304
|
realParent = parent;
|
|
11216
11305
|
}
|
|
11217
11306
|
if (realParent !== root && !(realParent + sep3).startsWith(root + sep3)) {
|
|
11218
|
-
throw new
|
|
11307
|
+
throw new TRPCError19({ code: "FORBIDDEN", message: "Hors du dossier autoris\xE9" });
|
|
11219
11308
|
}
|
|
11220
11309
|
return resolvePath(realParent, target.slice(parent.length).replace(/^[\\/]+/, ""));
|
|
11221
11310
|
}
|
|
@@ -11231,7 +11320,7 @@ var wikiRouter = router({
|
|
|
11231
11320
|
}),
|
|
11232
11321
|
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
11322
|
if (!/\.(md|markdown)$/i.test(input.path)) {
|
|
11234
|
-
throw new
|
|
11323
|
+
throw new TRPCError19({ code: "BAD_REQUEST", message: "Seuls les .md/.markdown sont autoris\xE9s" });
|
|
11235
11324
|
}
|
|
11236
11325
|
const target = await resolveScope(input.scope);
|
|
11237
11326
|
if (target.mode === "agent") {
|
|
@@ -11239,27 +11328,27 @@ var wikiRouter = router({
|
|
|
11239
11328
|
}
|
|
11240
11329
|
const file = await resolveSafeLocal(target.root, input.path, true);
|
|
11241
11330
|
const s = await stat3(file);
|
|
11242
|
-
if (!s.isFile()) throw new
|
|
11243
|
-
if (s.size > MAX_FILE_BYTES) throw new
|
|
11331
|
+
if (!s.isFile()) throw new TRPCError19({ code: "BAD_REQUEST", message: "Pas un fichier" });
|
|
11332
|
+
if (s.size > MAX_FILE_BYTES) throw new TRPCError19({ code: "PAYLOAD_TOO_LARGE", message: "Fichier trop volumineux" });
|
|
11244
11333
|
const content = await readFile13(file, "utf-8");
|
|
11245
11334
|
return { path: input.path, content };
|
|
11246
11335
|
}),
|
|
11247
11336
|
write: protectedProcedure.input(z23.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA, content: z23.string().max(5e6) })).mutation(async ({ input }) => {
|
|
11248
11337
|
if (!/\.(md|markdown)$/i.test(input.path)) {
|
|
11249
|
-
throw new
|
|
11338
|
+
throw new TRPCError19({ code: "BAD_REQUEST", message: "Seuls les .md/.markdown sont autoris\xE9s" });
|
|
11250
11339
|
}
|
|
11251
11340
|
const target = await resolveScope(input.scope);
|
|
11252
11341
|
if (target.mode === "agent") {
|
|
11253
11342
|
return agentManager.agentMutation(target.agentId, "wiki.writeMarkdown", { cwd: target.cwd, path: input.path, content: input.content });
|
|
11254
11343
|
}
|
|
11255
11344
|
const file = await resolveSafeLocal(target.root, input.path, false);
|
|
11256
|
-
await
|
|
11257
|
-
await
|
|
11345
|
+
await mkdir15(dirname3(file), { recursive: true });
|
|
11346
|
+
await writeFile12(file, input.content, "utf-8");
|
|
11258
11347
|
return { path: input.path, ok: true };
|
|
11259
11348
|
}),
|
|
11260
11349
|
createFile: protectedProcedure.input(z23.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
|
|
11261
11350
|
if (!/\.(md|markdown)$/i.test(input.path)) {
|
|
11262
|
-
throw new
|
|
11351
|
+
throw new TRPCError19({ code: "BAD_REQUEST", message: "Seuls les .md/.markdown sont autoris\xE9s" });
|
|
11263
11352
|
}
|
|
11264
11353
|
const target = await resolveScope(input.scope);
|
|
11265
11354
|
if (target.mode === "agent") {
|
|
@@ -11268,12 +11357,12 @@ var wikiRouter = router({
|
|
|
11268
11357
|
const file = await resolveSafeLocal(target.root, input.path, false);
|
|
11269
11358
|
try {
|
|
11270
11359
|
await stat3(file);
|
|
11271
|
-
throw new
|
|
11360
|
+
throw new TRPCError19({ code: "CONFLICT", message: "Fichier d\xE9j\xE0 existant" });
|
|
11272
11361
|
} catch (err) {
|
|
11273
|
-
if (err instanceof
|
|
11362
|
+
if (err instanceof TRPCError19) throw err;
|
|
11274
11363
|
}
|
|
11275
|
-
await
|
|
11276
|
-
await
|
|
11364
|
+
await mkdir15(dirname3(file), { recursive: true });
|
|
11365
|
+
await writeFile12(file, "", "utf-8");
|
|
11277
11366
|
return { path: input.path, ok: true };
|
|
11278
11367
|
}),
|
|
11279
11368
|
createDir: protectedProcedure.input(z23.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
|
|
@@ -11282,7 +11371,7 @@ var wikiRouter = router({
|
|
|
11282
11371
|
return agentManager.agentMutation(target.agentId, "wiki.createDir", { cwd: target.cwd, path: input.path });
|
|
11283
11372
|
}
|
|
11284
11373
|
const dir = await resolveSafeLocal(target.root, input.path, false);
|
|
11285
|
-
await
|
|
11374
|
+
await mkdir15(dir, { recursive: true });
|
|
11286
11375
|
return { path: input.path, ok: true };
|
|
11287
11376
|
}),
|
|
11288
11377
|
rename: protectedProcedure.input(z23.object({ scope: SCOPE_SCHEMA, fromPath: REL_PATH_SCHEMA, toPath: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
|
|
@@ -11294,11 +11383,11 @@ var wikiRouter = router({
|
|
|
11294
11383
|
const to = await resolveSafeLocal(target.root, input.toPath, false);
|
|
11295
11384
|
try {
|
|
11296
11385
|
await stat3(to);
|
|
11297
|
-
throw new
|
|
11386
|
+
throw new TRPCError19({ code: "CONFLICT", message: "La cible existe d\xE9j\xE0" });
|
|
11298
11387
|
} catch (err) {
|
|
11299
|
-
if (err instanceof
|
|
11388
|
+
if (err instanceof TRPCError19) throw err;
|
|
11300
11389
|
}
|
|
11301
|
-
await
|
|
11390
|
+
await mkdir15(dirname3(to), { recursive: true });
|
|
11302
11391
|
await rename10(from, to);
|
|
11303
11392
|
return { fromPath: input.fromPath, toPath: input.toPath, ok: true };
|
|
11304
11393
|
}),
|
|
@@ -11309,9 +11398,9 @@ var wikiRouter = router({
|
|
|
11309
11398
|
}
|
|
11310
11399
|
const serviceId = input.scope.slice("service:".length);
|
|
11311
11400
|
const service = await serviceStore.get(serviceId);
|
|
11312
|
-
if (!service) throw new
|
|
11401
|
+
if (!service) throw new TRPCError19({ code: "NOT_FOUND", message: "Service introuvable" });
|
|
11313
11402
|
const agentId = await resolveEffectiveAgentId(service);
|
|
11314
|
-
if (!agentId) throw new
|
|
11403
|
+
if (!agentId) throw new TRPCError19({ code: "BAD_REQUEST", message: "Aucun agent configur\xE9" });
|
|
11315
11404
|
const cwd = (service.docsPath?.trim() || service.cwd || ".").toString();
|
|
11316
11405
|
return agentManager.agentMutation(agentId, "wiki.ensureRoot", { cwd });
|
|
11317
11406
|
}),
|
|
@@ -11321,7 +11410,7 @@ var wikiRouter = router({
|
|
|
11321
11410
|
return agentManager.agentMutation(target.agentId, "wiki.deletePath", { cwd: target.cwd, path: input.path });
|
|
11322
11411
|
}
|
|
11323
11412
|
const fp = await resolveSafeLocal(target.root, input.path, true);
|
|
11324
|
-
if (fp === target.root) throw new
|
|
11413
|
+
if (fp === target.root) throw new TRPCError19({ code: "FORBIDDEN", message: "Impossible de supprimer la racine" });
|
|
11325
11414
|
await rm2(fp, { recursive: true, force: true });
|
|
11326
11415
|
return { path: input.path, ok: true };
|
|
11327
11416
|
})
|
|
@@ -11337,17 +11426,17 @@ var configRouter = router({
|
|
|
11337
11426
|
|
|
11338
11427
|
// ../server/src/trpc/routers/cloud-sync.ts
|
|
11339
11428
|
import { z as z24 } from "zod";
|
|
11340
|
-
import { TRPCError as
|
|
11429
|
+
import { TRPCError as TRPCError20 } from "@trpc/server";
|
|
11341
11430
|
|
|
11342
11431
|
// ../server/src/services/cloud-sync-store.ts
|
|
11343
|
-
import { readFile as readFile14, writeFile as
|
|
11344
|
-
import { join as
|
|
11432
|
+
import { readFile as readFile14, writeFile as writeFile13, rename as rename11, mkdir as mkdir16, chmod as chmod9 } from "fs/promises";
|
|
11433
|
+
import { join as join18 } from "path";
|
|
11345
11434
|
var FILENAME5 = "cloud-sync.json";
|
|
11346
11435
|
var CloudSyncStore = class {
|
|
11347
11436
|
links = /* @__PURE__ */ new Map();
|
|
11348
11437
|
loaded = false;
|
|
11349
11438
|
getFilePath() {
|
|
11350
|
-
return
|
|
11439
|
+
return join18(env.DATA_DIR, FILENAME5);
|
|
11351
11440
|
}
|
|
11352
11441
|
async load() {
|
|
11353
11442
|
if (this.loaded) return;
|
|
@@ -11360,11 +11449,11 @@ var CloudSyncStore = class {
|
|
|
11360
11449
|
this.loaded = true;
|
|
11361
11450
|
}
|
|
11362
11451
|
async save() {
|
|
11363
|
-
await
|
|
11452
|
+
await mkdir16(env.DATA_DIR, { recursive: true });
|
|
11364
11453
|
const filePath = this.getFilePath();
|
|
11365
11454
|
const tmpPath = filePath + ".tmp";
|
|
11366
11455
|
const data = JSON.stringify(Array.from(this.links.values()), null, 2);
|
|
11367
|
-
await
|
|
11456
|
+
await writeFile13(tmpPath, data, "utf-8");
|
|
11368
11457
|
await rename11(tmpPath, filePath);
|
|
11369
11458
|
await chmod9(filePath, 384);
|
|
11370
11459
|
}
|
|
@@ -11760,8 +11849,8 @@ var cloudSyncBridge = new CloudSyncBridge();
|
|
|
11760
11849
|
|
|
11761
11850
|
// ../server/src/services/master-password.ts
|
|
11762
11851
|
import { randomBytes as randomBytes4, createCipheriv, createDecipheriv } from "crypto";
|
|
11763
|
-
import { readFile as readFile15, writeFile as
|
|
11764
|
-
import { join as
|
|
11852
|
+
import { readFile as readFile15, writeFile as writeFile14, chmod as chmod10, stat as stat4, rename as rename12 } from "fs/promises";
|
|
11853
|
+
import { join as join19 } from "path";
|
|
11765
11854
|
import { Entry } from "@napi-rs/keyring";
|
|
11766
11855
|
import { hashRaw as argon2HashRaw } from "@node-rs/argon2";
|
|
11767
11856
|
var KEYRING_SERVICE = "runeya";
|
|
@@ -11794,7 +11883,7 @@ function aesDecrypt(key, data) {
|
|
|
11794
11883
|
}
|
|
11795
11884
|
async function getPepperFromFile(dataDir) {
|
|
11796
11885
|
try {
|
|
11797
|
-
const raw = await readKeyFile(
|
|
11886
|
+
const raw = await readKeyFile(join19(dataDir, PEPPER_FILENAME));
|
|
11798
11887
|
const hex = raw.toString("utf-8").trim();
|
|
11799
11888
|
if (/^[0-9a-f]{64}$/i.test(hex)) return Buffer.from(hex, "hex");
|
|
11800
11889
|
} catch {
|
|
@@ -11802,9 +11891,9 @@ async function getPepperFromFile(dataDir) {
|
|
|
11802
11891
|
return null;
|
|
11803
11892
|
}
|
|
11804
11893
|
async function writePepperToFile(dataDir, pepper) {
|
|
11805
|
-
const filePath =
|
|
11894
|
+
const filePath = join19(dataDir, PEPPER_FILENAME);
|
|
11806
11895
|
const tmpPath = filePath + ".tmp";
|
|
11807
|
-
await
|
|
11896
|
+
await writeFile14(tmpPath, pepper.toString("hex"), "utf-8");
|
|
11808
11897
|
await chmod10(tmpPath, 384);
|
|
11809
11898
|
await rename12(tmpPath, filePath);
|
|
11810
11899
|
}
|
|
@@ -11853,14 +11942,14 @@ async function writeEncryptedKey(dataDir, masterPassword, encryptionKey) {
|
|
|
11853
11942
|
const payload = aesEncrypt(derivedKey, encryptionKey);
|
|
11854
11943
|
const fileContent = Buffer.concat([salt, payload]);
|
|
11855
11944
|
const encoded = fileContent.toString("base64");
|
|
11856
|
-
const filePath =
|
|
11945
|
+
const filePath = join19(dataDir, ENCRYPTED_KEY_FILENAME);
|
|
11857
11946
|
const tmpPath = filePath + ".tmp";
|
|
11858
|
-
await
|
|
11947
|
+
await writeFile14(tmpPath, encoded, "utf-8");
|
|
11859
11948
|
await chmod10(tmpPath, 384);
|
|
11860
11949
|
await rename12(tmpPath, filePath);
|
|
11861
11950
|
}
|
|
11862
11951
|
async function readEncryptedKey(dataDir, masterPassword) {
|
|
11863
|
-
const filePath =
|
|
11952
|
+
const filePath = join19(dataDir, ENCRYPTED_KEY_FILENAME);
|
|
11864
11953
|
const raw = await readKeyFile(filePath);
|
|
11865
11954
|
const fileContent = Buffer.from(raw.toString("utf-8").trim(), "base64");
|
|
11866
11955
|
const salt = fileContent.subarray(0, 16);
|
|
@@ -11880,13 +11969,13 @@ async function getPepperFromKeychain(dataDir) {
|
|
|
11880
11969
|
}
|
|
11881
11970
|
async function writeVerifyFile(dataDir, encryptionKey) {
|
|
11882
11971
|
const payload = aesEncrypt(encryptionKey, Buffer.from(CANARY_PLAINTEXT, "utf-8"));
|
|
11883
|
-
const filePath =
|
|
11972
|
+
const filePath = join19(dataDir, VERIFY_FILENAME);
|
|
11884
11973
|
const tmpPath = filePath + ".tmp";
|
|
11885
|
-
await
|
|
11974
|
+
await writeFile14(tmpPath, payload.toString("base64"), "utf-8");
|
|
11886
11975
|
await rename12(tmpPath, filePath);
|
|
11887
11976
|
}
|
|
11888
11977
|
async function verifyEncryptionKey(dataDir, encryptionKey) {
|
|
11889
|
-
const filePath =
|
|
11978
|
+
const filePath = join19(dataDir, VERIFY_FILENAME);
|
|
11890
11979
|
const raw = await readKeyFile(filePath);
|
|
11891
11980
|
if (!matchesCanary(raw.toString("utf-8"), encryptionKey)) {
|
|
11892
11981
|
throw new Error("Cl\xE9 d'encryption incorrecte");
|
|
@@ -11902,14 +11991,14 @@ function matchesCanary(canaryBase64, encryptionKey) {
|
|
|
11902
11991
|
}
|
|
11903
11992
|
async function readVerifyFile(dataDir) {
|
|
11904
11993
|
try {
|
|
11905
|
-
return (await readKeyFile(
|
|
11994
|
+
return (await readKeyFile(join19(dataDir, VERIFY_FILENAME))).toString("utf-8").trim();
|
|
11906
11995
|
} catch {
|
|
11907
11996
|
return null;
|
|
11908
11997
|
}
|
|
11909
11998
|
}
|
|
11910
11999
|
async function hasVerifyFile(dataDir) {
|
|
11911
12000
|
try {
|
|
11912
|
-
await stat4(
|
|
12001
|
+
await stat4(join19(dataDir, VERIFY_FILENAME));
|
|
11913
12002
|
return true;
|
|
11914
12003
|
} catch {
|
|
11915
12004
|
return false;
|
|
@@ -11917,7 +12006,7 @@ async function hasVerifyFile(dataDir) {
|
|
|
11917
12006
|
}
|
|
11918
12007
|
async function hasEncryptedKeyFile(dataDir) {
|
|
11919
12008
|
try {
|
|
11920
|
-
await stat4(
|
|
12009
|
+
await stat4(join19(dataDir, ENCRYPTED_KEY_FILENAME));
|
|
11921
12010
|
return true;
|
|
11922
12011
|
} catch {
|
|
11923
12012
|
return false;
|
|
@@ -11928,25 +12017,25 @@ async function hasEncryptedKeyFile(dataDir) {
|
|
|
11928
12017
|
async function reconcileOrgCanary(orgId) {
|
|
11929
12018
|
const key = getEncryptionKey();
|
|
11930
12019
|
if (!key) {
|
|
11931
|
-
throw new
|
|
12020
|
+
throw new TRPCError20({ code: "PRECONDITION_FAILED", message: "Encryption key not loaded." });
|
|
11932
12021
|
}
|
|
11933
12022
|
const local = await readVerifyFile(env.DATA_DIR);
|
|
11934
12023
|
if (!local) {
|
|
11935
|
-
throw new
|
|
12024
|
+
throw new TRPCError20({ code: "PRECONDITION_FAILED", message: "This machine has no key canary yet." });
|
|
11936
12025
|
}
|
|
11937
12026
|
const res = await cloudFetch("/api/auth/organization/canary", {
|
|
11938
12027
|
method: "POST",
|
|
11939
12028
|
body: { organizationId: orgId, canary: local }
|
|
11940
12029
|
});
|
|
11941
12030
|
if (!res.ok) {
|
|
11942
|
-
throw new
|
|
12031
|
+
throw new TRPCError20({ code: "BAD_GATEWAY", message: "Could not reach the organization on the cloud." });
|
|
11943
12032
|
}
|
|
11944
12033
|
const { canary } = await res.json();
|
|
11945
12034
|
if (typeof canary !== "string") {
|
|
11946
|
-
throw new
|
|
12035
|
+
throw new TRPCError20({ code: "BAD_GATEWAY", message: "The cloud returned no key canary." });
|
|
11947
12036
|
}
|
|
11948
12037
|
if (!matchesCanary(canary, key)) {
|
|
11949
|
-
throw new
|
|
12038
|
+
throw new TRPCError20({
|
|
11950
12039
|
code: "FORBIDDEN",
|
|
11951
12040
|
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
12041
|
});
|
|
@@ -12051,7 +12140,7 @@ var migrationEngine = new MigrationEngine();
|
|
|
12051
12140
|
|
|
12052
12141
|
// ../server/src/services/file-security.ts
|
|
12053
12142
|
import { chmod as chmod11, stat as stat5 } from "fs/promises";
|
|
12054
|
-
import { join as
|
|
12143
|
+
import { join as join20 } from "path";
|
|
12055
12144
|
var SENSITIVE_FILES = [
|
|
12056
12145
|
"agents.json",
|
|
12057
12146
|
"settings.json",
|
|
@@ -12063,7 +12152,7 @@ var SENSITIVE_FILES = [
|
|
|
12063
12152
|
var SECURE_MODE = 384;
|
|
12064
12153
|
async function ensureFilePermissions() {
|
|
12065
12154
|
for (const filename of SENSITIVE_FILES) {
|
|
12066
|
-
const filepath =
|
|
12155
|
+
const filepath = join20(env.DATA_DIR, filename);
|
|
12067
12156
|
try {
|
|
12068
12157
|
const stats = await stat5(filepath);
|
|
12069
12158
|
const mode = stats.mode & 511;
|
|
@@ -12080,8 +12169,8 @@ async function ensureFilePermissions() {
|
|
|
12080
12169
|
}
|
|
12081
12170
|
|
|
12082
12171
|
// ../server/src/utils/ensure-data-gitignore.ts
|
|
12083
|
-
import { writeFile as
|
|
12084
|
-
import { join as
|
|
12172
|
+
import { writeFile as writeFile15 } from "fs/promises";
|
|
12173
|
+
import { join as join21 } from "path";
|
|
12085
12174
|
var GITIGNORE_CONTENT = `
|
|
12086
12175
|
#################
|
|
12087
12176
|
# Do not edit this file #
|
|
@@ -12118,8 +12207,8 @@ conversations.private.json
|
|
|
12118
12207
|
*.log.*
|
|
12119
12208
|
`;
|
|
12120
12209
|
async function ensureDataGitignore(dataDir) {
|
|
12121
|
-
const gitignorePath =
|
|
12122
|
-
await
|
|
12210
|
+
const gitignorePath = join21(dataDir, ".gitignore");
|
|
12211
|
+
await writeFile15(gitignorePath, GITIGNORE_CONTENT, "utf-8");
|
|
12123
12212
|
}
|
|
12124
12213
|
|
|
12125
12214
|
// ../server/src/migrations/migrate-from-legacy.ts
|
|
@@ -12128,13 +12217,13 @@ import { randomBytes as randomBytes5, createCipheriv as createCipheriv2, createD
|
|
|
12128
12217
|
import { randomUUID as randomUUID12 } from "crypto";
|
|
12129
12218
|
import {
|
|
12130
12219
|
readFile as readFile16,
|
|
12131
|
-
writeFile as
|
|
12220
|
+
writeFile as writeFile16,
|
|
12132
12221
|
rename as rename13,
|
|
12133
|
-
mkdir as
|
|
12222
|
+
mkdir as mkdir17,
|
|
12134
12223
|
access as access2,
|
|
12135
12224
|
readdir as readdir6
|
|
12136
12225
|
} from "fs/promises";
|
|
12137
|
-
import { join as
|
|
12226
|
+
import { join as join22 } from "path";
|
|
12138
12227
|
var _require = createRequire(import.meta.url);
|
|
12139
12228
|
var PARSER_ID_MAP = {
|
|
12140
12229
|
"stack-monitor-parser-jsons": "native:json",
|
|
@@ -12263,14 +12352,14 @@ async function decryptLegacyFile(filePath, key, sodium) {
|
|
|
12263
12352
|
}
|
|
12264
12353
|
async function atomicWrite(path, data) {
|
|
12265
12354
|
const tmp = path + ".tmp";
|
|
12266
|
-
await
|
|
12355
|
+
await writeFile16(tmp, JSON.stringify(data, null, 2), "utf-8");
|
|
12267
12356
|
await rename13(tmp, path);
|
|
12268
12357
|
}
|
|
12269
12358
|
async function runLegacyMigration(dataDir) {
|
|
12270
12359
|
const { resolve: resolve6 } = await import("path");
|
|
12271
12360
|
const abCwd = resolve6(process.cwd());
|
|
12272
|
-
const legacyRoot =
|
|
12273
|
-
const legacyKeyPath =
|
|
12361
|
+
const legacyRoot = join22(abCwd, env.DATA_DIR);
|
|
12362
|
+
const legacyKeyPath = join22(legacyRoot, "dbs", "encryption-key.json");
|
|
12274
12363
|
try {
|
|
12275
12364
|
await access2(legacyKeyPath);
|
|
12276
12365
|
} catch {
|
|
@@ -12278,20 +12367,20 @@ async function runLegacyMigration(dataDir) {
|
|
|
12278
12367
|
}
|
|
12279
12368
|
console.log("[legacy-migration] Legacy Runeya data detected, starting migration\u2026");
|
|
12280
12369
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").substring(0, 19);
|
|
12281
|
-
const legacyTmp =
|
|
12370
|
+
const legacyTmp = join22(abCwd, ".runeya-tmp");
|
|
12282
12371
|
await rename13(legacyRoot, legacyTmp);
|
|
12283
|
-
await
|
|
12284
|
-
const legacyOld =
|
|
12372
|
+
await mkdir17(dataDir, { recursive: true });
|
|
12373
|
+
const legacyOld = join22(dataDir, `backup-${timestamp}`);
|
|
12285
12374
|
await rename13(legacyTmp, legacyOld);
|
|
12286
12375
|
console.log(`[legacy-migration] Legacy data backed up to ${legacyOld}`);
|
|
12287
|
-
const keyJson = JSON.parse(await readFile16(
|
|
12376
|
+
const keyJson = JSON.parse(await readFile16(join22(legacyOld, "dbs", "encryption-key.json"), "utf-8"));
|
|
12288
12377
|
const sodium = await getSodium();
|
|
12289
12378
|
const sodiumKey = sodium.from_base64(keyJson.encryptionKey);
|
|
12290
12379
|
const keyBuffer = Buffer.from(sodiumKey);
|
|
12291
12380
|
const runyeaKeyHex = keyBuffer.toString("hex");
|
|
12292
12381
|
await setEncryptionKey(runyeaKeyHex);
|
|
12293
12382
|
console.log("[legacy-migration] Encryption key loaded in memory (temporary)");
|
|
12294
|
-
const dbsDir =
|
|
12383
|
+
const dbsDir = join22(legacyOld, "dbs");
|
|
12295
12384
|
async function readEncrypted(filePath) {
|
|
12296
12385
|
try {
|
|
12297
12386
|
return await decryptLegacyFile(filePath, sodiumKey, sodium);
|
|
@@ -12300,29 +12389,29 @@ async function runLegacyMigration(dataDir) {
|
|
|
12300
12389
|
return null;
|
|
12301
12390
|
}
|
|
12302
12391
|
}
|
|
12303
|
-
const envsDir =
|
|
12392
|
+
const envsDir = join22(dbsDir, "envs");
|
|
12304
12393
|
const envFiles = (await readdir6(envsDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
|
|
12305
12394
|
const legacyEnvs = {};
|
|
12306
12395
|
for (const file of envFiles) {
|
|
12307
12396
|
const name = file.replace(".encrypted.json", "");
|
|
12308
|
-
legacyEnvs[name] = await readEncrypted(
|
|
12397
|
+
legacyEnvs[name] = await readEncrypted(join22(envsDir, file));
|
|
12309
12398
|
}
|
|
12310
|
-
const servicesDir =
|
|
12399
|
+
const servicesDir = join22(dbsDir, "services");
|
|
12311
12400
|
const serviceFiles = (await readdir6(servicesDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
|
|
12312
12401
|
const legacyServices = {};
|
|
12313
12402
|
for (const file of serviceFiles) {
|
|
12314
12403
|
const name = file.replace(".encrypted.json", "");
|
|
12315
12404
|
if (!name) continue;
|
|
12316
|
-
const data = await readEncrypted(
|
|
12405
|
+
const data = await readEncrypted(join22(servicesDir, file));
|
|
12317
12406
|
if (data?.label) legacyServices[name] = data;
|
|
12318
12407
|
}
|
|
12319
|
-
const overridesDir =
|
|
12408
|
+
const overridesDir = join22(dbsDir, "overrides");
|
|
12320
12409
|
const overrideFiles = (await readdir6(overridesDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
|
|
12321
12410
|
const legacyServiceOverrides = {};
|
|
12322
12411
|
const legacyEnvOverrides = {};
|
|
12323
12412
|
for (const file of overrideFiles) {
|
|
12324
12413
|
const baseName = file.replace(".encrypted.json", "");
|
|
12325
|
-
const data = await readEncrypted(
|
|
12414
|
+
const data = await readEncrypted(join22(overridesDir, file));
|
|
12326
12415
|
if (!data) continue;
|
|
12327
12416
|
if (baseName.endsWith("-envs")) {
|
|
12328
12417
|
legacyServiceOverrides[baseName.slice(0, -5)] = data;
|
|
@@ -12330,11 +12419,11 @@ async function runLegacyMigration(dataDir) {
|
|
|
12330
12419
|
legacyEnvOverrides[baseName.slice(0, -12)] = data;
|
|
12331
12420
|
}
|
|
12332
12421
|
}
|
|
12333
|
-
const parsersDir =
|
|
12422
|
+
const parsersDir = join22(dbsDir, "parsers");
|
|
12334
12423
|
const parserFiles = (await readdir6(parsersDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
|
|
12335
12424
|
const legacyParsers = [];
|
|
12336
12425
|
for (const file of parserFiles) {
|
|
12337
|
-
const data = await readEncrypted(
|
|
12426
|
+
const data = await readEncrypted(join22(parsersDir, file));
|
|
12338
12427
|
if (data?.id) legacyParsers.push(data);
|
|
12339
12428
|
}
|
|
12340
12429
|
const projectMonoId = randomUUID12();
|
|
@@ -12675,7 +12764,7 @@ async function runLegacyMigration(dataDir) {
|
|
|
12675
12764
|
}
|
|
12676
12765
|
let existingSettings = {};
|
|
12677
12766
|
try {
|
|
12678
|
-
existingSettings = JSON.parse(await readFile16(
|
|
12767
|
+
existingSettings = JSON.parse(await readFile16(join22(dataDir, "settings.json"), "utf-8"));
|
|
12679
12768
|
} catch {
|
|
12680
12769
|
}
|
|
12681
12770
|
const migratedParsers = legacyParsers.map((p) => ({
|
|
@@ -12696,11 +12785,11 @@ ${p.transform ?? ""}`,
|
|
|
12696
12785
|
...migratedParsers
|
|
12697
12786
|
]
|
|
12698
12787
|
};
|
|
12699
|
-
await atomicWrite(
|
|
12700
|
-
await atomicWrite(
|
|
12701
|
-
await atomicWrite(
|
|
12702
|
-
await atomicWrite(
|
|
12703
|
-
await atomicWrite(
|
|
12788
|
+
await atomicWrite(join22(dataDir, "projects.json"), runeProjects);
|
|
12789
|
+
await atomicWrite(join22(dataDir, "services.json"), runeServices);
|
|
12790
|
+
await atomicWrite(join22(dataDir, "environments.json"), runeEnvs);
|
|
12791
|
+
await atomicWrite(join22(dataDir, "environment-overrides.json"), flatOverrides);
|
|
12792
|
+
await atomicWrite(join22(dataDir, "settings.json"), newSettings);
|
|
12704
12793
|
const svcEnvCount = runeEnvs.filter((e) => e.scope === "service").length;
|
|
12705
12794
|
console.log(`[legacy-migration] Written: ${runeProjects.length} projects, ${runeServices.length} services, ${runeEnvs.length} environments (${svcEnvCount} service-scoped)`);
|
|
12706
12795
|
console.log(`[legacy-migration] Overrides: ${Object.keys(flatOverrides).length}, custom parsers: ${migratedParsers.length} (all disabled \u2014 rewrite required)`);
|
|
@@ -12714,7 +12803,7 @@ async function findLegacyKeyInBackup(dataDir) {
|
|
|
12714
12803
|
const entries = await readdir6(dataDir);
|
|
12715
12804
|
const backupDirs = entries.filter((e) => e.startsWith("backup-")).sort((a, b) => a < b ? -1 : a > b ? 1 : 0).reverse();
|
|
12716
12805
|
for (const dir of backupDirs) {
|
|
12717
|
-
const keyJsonPath =
|
|
12806
|
+
const keyJsonPath = join22(dataDir, dir, "dbs", "encryption-key.json");
|
|
12718
12807
|
try {
|
|
12719
12808
|
const raw = await readFile16(keyJsonPath, "utf-8");
|
|
12720
12809
|
const parsed = JSON.parse(raw);
|
|
@@ -12738,8 +12827,8 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
12738
12827
|
const abDataDir = resolve6(dataDir);
|
|
12739
12828
|
const abCwd = resolve6(process.cwd());
|
|
12740
12829
|
const candidateDirs = [
|
|
12741
|
-
|
|
12742
|
-
|
|
12830
|
+
join22(abCwd, ".runeya", "dbs", "overrides"),
|
|
12831
|
+
join22(abDataDir, "dbs", "overrides")
|
|
12743
12832
|
];
|
|
12744
12833
|
let overridesDir = null;
|
|
12745
12834
|
let overrideFiles = [];
|
|
@@ -12755,7 +12844,7 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
12755
12844
|
}
|
|
12756
12845
|
}
|
|
12757
12846
|
if (!overridesDir || overrideFiles.length === 0) return false;
|
|
12758
|
-
const legacyKeyPath =
|
|
12847
|
+
const legacyKeyPath = join22(overridesDir, "..", "encryption-key.json");
|
|
12759
12848
|
try {
|
|
12760
12849
|
await access2(legacyKeyPath);
|
|
12761
12850
|
return false;
|
|
@@ -12773,7 +12862,7 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
12773
12862
|
const envNameToId = {};
|
|
12774
12863
|
let envsRaw;
|
|
12775
12864
|
try {
|
|
12776
|
-
envsRaw = JSON.parse(await readFile16(
|
|
12865
|
+
envsRaw = JSON.parse(await readFile16(join22(abDataDir, "environments.json"), "utf-8"));
|
|
12777
12866
|
for (const _env of envsRaw) {
|
|
12778
12867
|
const env2 = _env;
|
|
12779
12868
|
if (env2["name"] && env2["id"]) {
|
|
@@ -12792,7 +12881,7 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
12792
12881
|
let servicesRaw = [];
|
|
12793
12882
|
const serviceNameToId = {};
|
|
12794
12883
|
try {
|
|
12795
|
-
servicesRaw = JSON.parse(await readFile16(
|
|
12884
|
+
servicesRaw = JSON.parse(await readFile16(join22(abDataDir, "services.json"), "utf-8"));
|
|
12796
12885
|
for (const _svc of servicesRaw) {
|
|
12797
12886
|
const svc = _svc;
|
|
12798
12887
|
if (svc["name"] && svc["id"]) serviceNameToId[svc["name"]] = svc["id"];
|
|
@@ -12809,7 +12898,7 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
12809
12898
|
const envName = baseName.slice(0, -"-environment".length);
|
|
12810
12899
|
let data;
|
|
12811
12900
|
try {
|
|
12812
|
-
data = await decryptLegacyFile(
|
|
12901
|
+
data = await decryptLegacyFile(join22(overridesDir, file), sodiumKey, sodium);
|
|
12813
12902
|
} catch (err) {
|
|
12814
12903
|
console.warn(`[override-migration] Failed to decrypt ${file}: ${err.message}`);
|
|
12815
12904
|
continue;
|
|
@@ -12836,7 +12925,7 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
12836
12925
|
}
|
|
12837
12926
|
}
|
|
12838
12927
|
if (Object.keys(flatOverrides).length > 0) {
|
|
12839
|
-
await atomicWrite(
|
|
12928
|
+
await atomicWrite(join22(abDataDir, "environment-overrides.json"), flatOverrides);
|
|
12840
12929
|
console.log(`[override-migration] Written ${Object.keys(flatOverrides).length} override(s) to environment-overrides.json`);
|
|
12841
12930
|
}
|
|
12842
12931
|
let envsModified = false;
|
|
@@ -12846,7 +12935,7 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
12846
12935
|
const serviceName = baseName.slice(0, -"-envs".length);
|
|
12847
12936
|
let data;
|
|
12848
12937
|
try {
|
|
12849
|
-
data = await decryptLegacyFile(
|
|
12938
|
+
data = await decryptLegacyFile(join22(overridesDir, file), sodiumKey, sodium);
|
|
12850
12939
|
} catch (err) {
|
|
12851
12940
|
console.warn(`[override-migration] Failed to decrypt ${file}: ${err.message}`);
|
|
12852
12941
|
continue;
|
|
@@ -12905,7 +12994,7 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
12905
12994
|
}
|
|
12906
12995
|
}
|
|
12907
12996
|
if (envsModified) {
|
|
12908
|
-
await atomicWrite(
|
|
12997
|
+
await atomicWrite(join22(abDataDir, "environments.json"), envsRaw);
|
|
12909
12998
|
console.log("[override-migration] Merged service overrides into environments.json");
|
|
12910
12999
|
}
|
|
12911
13000
|
const migratedDir = overridesDir.replace(/overrides$/, "overrides-migrated");
|
|
@@ -12920,7 +13009,7 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
12920
13009
|
}
|
|
12921
13010
|
|
|
12922
13011
|
// ../server/src/services/server-state.ts
|
|
12923
|
-
import { join as
|
|
13012
|
+
import { join as join23 } from "path";
|
|
12924
13013
|
import { stat as stat6 } from "fs/promises";
|
|
12925
13014
|
var ENCRYPTED_KEY_FILENAME2 = ".encryption.key.enc";
|
|
12926
13015
|
var VERIFY_FILENAME2 = ".runeya-verify";
|
|
@@ -12930,17 +13019,17 @@ async function getServerState() {
|
|
|
12930
13019
|
let hasVerify = false;
|
|
12931
13020
|
let hasData = false;
|
|
12932
13021
|
try {
|
|
12933
|
-
await stat6(
|
|
13022
|
+
await stat6(join23(dataDir, ENCRYPTED_KEY_FILENAME2));
|
|
12934
13023
|
hasEncFile = true;
|
|
12935
13024
|
} catch {
|
|
12936
13025
|
}
|
|
12937
13026
|
try {
|
|
12938
|
-
await stat6(
|
|
13027
|
+
await stat6(join23(dataDir, VERIFY_FILENAME2));
|
|
12939
13028
|
hasVerify = true;
|
|
12940
13029
|
} catch {
|
|
12941
13030
|
}
|
|
12942
13031
|
try {
|
|
12943
|
-
await stat6(
|
|
13032
|
+
await stat6(join23(dataDir, "projects.json"));
|
|
12944
13033
|
hasData = true;
|
|
12945
13034
|
} catch {
|
|
12946
13035
|
}
|
|
@@ -13232,7 +13321,7 @@ function getOpenApiDocument() {
|
|
|
13232
13321
|
// ../server/src/create-server.ts
|
|
13233
13322
|
import rateLimit from "express-rate-limit";
|
|
13234
13323
|
import { existsSync as existsSync2, createReadStream } from "fs";
|
|
13235
|
-
import { mkdir as
|
|
13324
|
+
import { mkdir as mkdir18 } from "fs/promises";
|
|
13236
13325
|
import multer from "multer";
|
|
13237
13326
|
|
|
13238
13327
|
// ../server/src/services/image-cleanup.service.ts
|
|
@@ -13338,7 +13427,7 @@ async function createLocalServer() {
|
|
|
13338
13427
|
console.log("[server] Premier lancement \u2014 setup requis");
|
|
13339
13428
|
}
|
|
13340
13429
|
}
|
|
13341
|
-
if (!existsSync2(env.DATA_DIR)) await
|
|
13430
|
+
if (!existsSync2(env.DATA_DIR)) await mkdir18(env.DATA_DIR);
|
|
13342
13431
|
const absoluteDataDir = resolve5(env.DATA_DIR);
|
|
13343
13432
|
console.log(`[server] Data directory: ${absoluteDataDir}`);
|
|
13344
13433
|
await ensureDataGitignore(env.DATA_DIR);
|
|
@@ -14090,4 +14179,4 @@ export {
|
|
|
14090
14179
|
createLocalServer,
|
|
14091
14180
|
pullEnv
|
|
14092
14181
|
};
|
|
14093
|
-
//# sourceMappingURL=src-
|
|
14182
|
+
//# sourceMappingURL=src-ZYEDS2TT.js.map
|