@runeya/runeya 2.0.71 → 2.0.72
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/agent/index.js +203 -160
- package/agent/index.js.map +1 -1
- package/agent-manager-YDLSYZE3.js +7 -0
- package/{chunk-Z3KAXI7V.js → chunk-HPYBAUAH.js} +235 -29
- package/chunk-HPYBAUAH.js.map +1 -0
- package/index.js +3 -2
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/{src-Q3PSCMS7.js → src-53OQNM27.js} +850 -677
- package/src-53OQNM27.js.map +1 -0
- package/web/assets/AgentScalarChatInterface.vue-DdIfThmp.js +13 -0
- package/web/assets/AgentTerminalPage-v9fFc2Kd.js +1 -0
- package/web/assets/AiChatPage-BvrKlLxc.js +1 -0
- package/web/assets/AppLayout-CLzy-QOZ.js +1 -0
- package/web/assets/{AppLayout-BqXoW05V.css → AppLayout-Dj8VrBzz.css} +1 -1
- package/web/assets/AuditPage-DgJIcr0c.js +1 -0
- package/web/assets/CloudAccountPage-CoJV3YCA.js +1 -0
- package/web/assets/CloudAccountPage-DGtKCmXL.js +1 -0
- package/web/assets/CloudMessagingPage-Bql34zJU.js +2 -0
- package/web/assets/DashboardPage-BSvJxrcT.js +1 -0
- package/web/assets/DirectoryPickerDialog-BfLLfUQy.js +1 -0
- package/web/assets/{EditorIcon-JRryeySJ.js → EditorIcon-BbilRWLq.js} +2 -2
- package/web/assets/EnvironmentForm-BIHXK18r.js +108 -0
- package/web/assets/EnvironmentFormPage-oLAwLJ1b.js +1 -0
- package/web/assets/EnvironmentListPage-tJfB0q_E.js +1 -0
- package/web/assets/KanbanBoardPage-DpyYe6jx.js +4 -0
- package/web/assets/KanbanListPage-DjXWjWgU.js +1 -0
- package/web/assets/LaunchProjectPage-Bqgsa2z1.js +1 -0
- package/web/assets/LaunchProjectPage-BrmWhutG.css +1 -0
- package/web/assets/LaunchServicesPage-BCNDSuuN.js +1 -0
- package/web/assets/LaunchServicesPage-CMxUWoNQ.css +1 -0
- package/web/assets/LogViewer-gTNzyao0.js +3 -0
- package/web/assets/OrgKeyPrompt-BdNV_cve.js +1 -0
- package/web/assets/{ProcessControls-BPQXGKib.js → ProcessControls-BzMrd-2c.js} +1 -1
- package/web/assets/ProcessDetailPage-Rg5zyPYJ.js +1 -0
- package/web/assets/{ProcessMetrics-D7L708Em.js → ProcessMetrics-hZWAa3gi.js} +2 -2
- package/web/assets/ProjectDetailPage-NbxG6AIr.js +1 -0
- package/web/assets/ProjectListPage-COMYMVbr.js +1 -0
- package/web/assets/RandomJobTestPage-DTK2RLln.js +2 -0
- package/web/assets/ScenarioEditorPage-DIx_Nzbh.js +14 -0
- package/web/assets/SendToChatDialog-BAalryU3.js +1 -0
- package/web/assets/ServiceControlsBar-CgR8yFZb.js +1 -0
- package/web/assets/ServiceDetailPage-Cvqftndf.js +2 -0
- package/web/assets/ServiceFormPage-CGgCwNM3.js +1 -0
- package/web/assets/{SettingsPage-CScovMi5.css → SettingsPage-ClUsbLPy.css} +1 -1
- package/web/assets/SettingsPage-Dx5xoAS7.js +2063 -0
- package/web/assets/UnlockPage-BkqsC0ML.css +1 -0
- package/web/assets/UnlockPage-Dlp8kXD-.js +1 -0
- package/web/assets/VariablesTable-Dr1C6hg4.js +1 -0
- package/web/assets/VaultMigrationPage-1zZCTKgS.js +1 -0
- package/web/assets/VaultMigrationPage-B20L2W_w.css +1 -0
- package/web/assets/VersionBadge-BiLjqi8I.js +1 -0
- package/web/assets/WikiPage-B51w0xOX.js +1 -0
- package/web/assets/WikiView-CGQrkGH4.js +1 -0
- package/web/assets/add-scalar-classes-ChVyhgpT.js +387 -0
- package/web/assets/auth-errors-BdfA61wA.js +1 -0
- package/web/assets/autocomplete-wqj_ORBH.js +308 -0
- package/web/assets/{basic-shape-diamond.svg-C8K6YjGj.js → basic-shape-diamond.svg-CWwnQ30s.js} +1 -1
- package/web/assets/{basic-shape-hexagon.svg-C9PeXR6S.js → basic-shape-hexagon.svg-C9JMDUIK.js} +1 -1
- package/web/assets/{basic-shape-primary-circle-ellipse-round.svg-CfBLN6Yj.js → basic-shape-primary-circle-ellipse-round.svg-Do0Ewbp-.js} +1 -1
- package/web/assets/{basic-shape-primary-square-rectangle.svg-D2QPBP5_.js → basic-shape-primary-square-rectangle.svg-CRq767cD.js} +1 -1
- package/web/assets/{basic-shape-shield.svg-ClsEFdja.js → basic-shape-shield.svg-BuxJBs70.js} +1 -1
- package/web/assets/{browser-CF5_9QqR.js → browser-BEEW2obM.js} +1 -1
- package/web/assets/{browser-D7ZckEFz.js → browser-BhZAIVa8.js} +1 -1
- package/web/assets/card-C1iS2wAN.js +32 -0
- package/web/assets/{checkbox-CfwNXlF_.js → checkbox-CCU9xze9.js} +3 -3
- package/web/assets/{chip-3tOoBrD7.js → chip-DsJBorBp.js} +2 -2
- package/web/assets/client-BFK39Zab.js +24 -0
- package/web/assets/cloud-chat.store-D39vo5xT.js +1 -0
- package/web/assets/cloud-session-B7G8xhKC.js +1 -0
- package/web/assets/column-CPU5Jg0n.js +907 -0
- package/web/assets/{computer-device-desktop-monitor.svg-9f4DSNLj.js → computer-device-desktop-monitor.svg-XWEWhL0y.js} +1 -1
- package/web/assets/{computer-device-desktop.svg-BYoXiEOE.js → computer-device-desktop.svg-COkZClBv.js} +1 -1
- package/web/assets/{computer-device-laptop.svg-DR1sEMdL.js → computer-device-laptop.svg-C4EfJUqO.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-android-samsung-back.svg-B-AOaBuq.js → computer-device-mobile-phone-android-samsung-back.svg-Bb2_2tyI.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-android-samsung.svg-Dw4z_H5H.js → computer-device-mobile-phone-android-samsung.svg-CEUhXP7K.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-iphone-x-back.svg-BtqMb2Wo.js → computer-device-mobile-phone-iphone-x-back.svg-B3rxizbE.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-iphone-x.svg-eYEM_VXA.js → computer-device-mobile-phone-iphone-x.svg-BSKpZFCN.js} +1 -1
- package/web/assets/{computer-device-mobile-tablet-touch.svg-jLD41nvm.js → computer-device-mobile-tablet-touch.svg-CZvb3YX2.js} +1 -1
- package/web/assets/{computer-device-mobile-tablet.svg-D_7_M1GK.js → computer-device-mobile-tablet.svg-BM4_YZYi.js} +1 -1
- package/web/assets/{computer-device-network-ethernet-cat6.svg-B_527QGY.js → computer-device-network-ethernet-cat6.svg-CK0v-Rjf.js} +1 -1
- package/web/assets/{computer-device-network-lan-www.svg-ClZIaUOH.js → computer-device-network-lan-www.svg-DvhO71Lq.js} +1 -1
- package/web/assets/{computer-device-network-wifi-connection.svg-DC4OCJY0.js → computer-device-network-wifi-connection.svg--olUYsgv.js} +1 -1
- package/web/assets/{computer-device-network-wifi-router.svg-BWPpobCc.js → computer-device-network-wifi-router.svg-D5HKSWTi.js} +1 -1
- package/web/assets/{cssMode-CXUrkdrQ.js → cssMode-CTjKNOiX.js} +1 -1
- package/web/assets/{divider-BrO5nkpd.js → divider-VFAPax5_.js} +2 -2
- package/web/assets/{docx-preview-tE714WSD.js → docx-preview-gNYLz3FX.js} +1 -1
- package/web/assets/{ecology-science-erlenmeyer-flask.svg-o8D0ASmr.js → ecology-science-erlenmeyer-flask.svg-THkDG-tj.js} +1 -1
- package/web/assets/{fieldset-LX5cdTvN.js → fieldset-DZGy449H.js} +2 -2
- package/web/assets/{freemarker2-DJ82s0fP.js → freemarker2-CNSvFpVF.js} +1 -1
- package/web/assets/{handlebars-BXFlY2Lu.js → handlebars-BeRu48NI.js} +1 -1
- package/web/assets/{html-CqDVypOC.js → html-DrTiGPjE.js} +1 -1
- package/web/assets/{htmlMode-DrHxdTQP.js → htmlMode-DpbDpbjK.js} +1 -1
- package/web/assets/{image-flash-lightning.svg-BDPMOynq.js → image-flash-lightning.svg-DrkyfdIV.js} +1 -1
- package/web/assets/{image-picture-flower.svg-D-AJaery.js → image-picture-flower.svg-BqFj1xcR.js} +1 -1
- package/web/assets/{index-CICxLkjp.css → index-B___lI4D.css} +1 -1
- package/web/assets/{index-a6DAapTb.js → index-y5bguEQB.js} +238 -238
- package/web/assets/{interface-alert-exclamation-diamond.svg-CV7M0IVQ.js → interface-alert-exclamation-diamond.svg-B40BfW6d.js} +1 -1
- package/web/assets/{interface-alert-exclamation-triangle-warning.svg-B8NapiB7.js → interface-alert-exclamation-triangle-warning.svg-DeIlksL4.js} +1 -1
- package/web/assets/{interface-alert-information-circle.svg-eQIFULjG.js → interface-alert-information-circle.svg-SwVdV-Z6.js} +1 -1
- package/web/assets/{interface-award-crown.svg-D-4fclUD.js → interface-award-crown.svg-DZHf0EHC.js} +1 -1
- package/web/assets/{interface-bookmark.svg-XdbYDqqk.js → interface-bookmark-tag.svg-CiaV2Cjo.js} +1 -1
- package/web/assets/{interface-bookmark-tag.svg-Jy6EOdau.js → interface-bookmark.svg-DBEqa-8W.js} +1 -1
- package/web/assets/{interface-calendar-date-one.svg-BIoXVZrz.js → interface-calendar-date-one.svg-C_afKyyz.js} +1 -1
- package/web/assets/{interface-content-book-open-pages.svg-DHwJbBvQ.js → interface-content-book-open-pages.svg-D5d9ilSu.js} +1 -1
- package/web/assets/{interface-content-book-page.svg-47msUBN_.js → interface-content-book-page.svg-B6hlaLP5.js} +1 -1
- package/web/assets/{interface-content-file.svg-DXw9W8QM.js → interface-content-file.svg-COWMwejF.js} +1 -1
- package/web/assets/interface-content-folder.svg-BCIUgpD4.js +1 -0
- package/web/assets/{interface-content-folder.svg-BmK_IJv8.js → interface-content-folder.svg-K7DTqQH-.js} +1 -1
- package/web/assets/{interface-copy-clipboard.svg-CQ1rQN0L.js → interface-copy-clipboard.svg-BFQ6eajI.js} +1 -1
- package/web/assets/{interface-edit-attachment.svg-C3aTaTh_.js → interface-edit-attachment.svg-B-LsB4cM.js} +1 -1
- package/web/assets/{interface-edit-binocular.svg-B2Ue_tgs.js → interface-edit-binocular.svg-CnVjKyrn.js} +1 -1
- package/web/assets/{interface-edit-magic-wand.svg-DDKse-Wy.js → interface-edit-magic-wand.svg-CUY6vVJT.js} +1 -1
- package/web/assets/{interface-edit-tool-paint-roller.svg-C2ABby1f.js → interface-edit-tool-paint-roller.svg-B1tSdIxN.js} +1 -1
- package/web/assets/{interface-edit-tool-pencil.svg-CNjYbknQ.js → interface-edit-tool-pencil.svg-BHFULT75.js} +1 -1
- package/web/assets/{interface-favorite-award.svg-DWqSHfIa.js → interface-favorite-award.svg-CcOLoF8I.js} +1 -1
- package/web/assets/{interface-favorite-flag.svg-CNUsr98g.js → interface-favorite-flag.svg-CAW6LmLW.js} +1 -1
- package/web/assets/{interface-favorite-heart.svg-3Eb366FO.js → interface-favorite-heart.svg-BEz4zlNs.js} +1 -1
- package/web/assets/{interface-favorite-star.svg-CVJ3aq1n.js → interface-favorite-star.svg-DKFuvYge.js} +1 -1
- package/web/assets/{interface-favorite-stars-sparkles.svg-BfXhPBbs.js → interface-favorite-stars-sparkles.svg-BfzccoPz.js} +1 -1
- package/web/assets/{interface-hierarchy-flowchart.svg-DzsqKrYq.js → interface-hierarchy-flowchart.svg-BT8QX161.js} +1 -1
- package/web/assets/{interface-home-house.svg-BnXbuyZn.js → interface-home-house.svg-B264pTPi.js} +1 -1
- package/web/assets/{interface-hyperlink.svg-BsmSmyP5.js → interface-hyperlink.svg-DhUgNKkr.js} +1 -1
- package/web/assets/{interface-lighting-brightness.svg-BywVQRo9.js → interface-lighting-brightness.svg-CPKb40uB.js} +1 -1
- package/web/assets/{interface-lock-closed.svg-BLPORc_h.js → interface-lock-closed.svg-CvXhgCtt.js} +1 -1
- package/web/assets/{interface-lock-open-unlock.svg-CaYlbVmU.js → interface-lock-open-unlock.svg-B0PMKRhP.js} +1 -1
- package/web/assets/{interface-login-key.svg-D5F_9MJ0.js → interface-login-key.svg-DJUm3vhg.js} +1 -1
- package/web/assets/{interface-search.svg-CF1D8GIV.js → interface-search.svg-ByW98ez_.js} +1 -1
- package/web/assets/{interface-setting-cog.svg-D4AOKG2g.js → interface-setting-cog.svg-DYOmJ9It.js} +1 -1
- package/web/assets/{interface-share-megaphone-bullhorn.svg-BIfr2_va.js → interface-share-megaphone-bullhorn.svg-YOCUHa3i.js} +1 -1
- package/web/assets/{interface-share-rocket.svg-NDd3dv1t.js → interface-share-rocket.svg-C5kj5dSu.js} +1 -1
- package/web/assets/{interface-share-satellite.svg-CVDJbmT-.js → interface-share-satellite.svg-C0svPxG6.js} +1 -1
- package/web/assets/{interface-share-space-ship.svg-D0ZLJNO2.js → interface-share-space-ship.svg-8Nw02n1Q.js} +1 -1
- package/web/assets/{interface-share.svg-WpwbpOes.js → interface-share.svg-eDW294tn.js} +1 -1
- package/web/assets/{interface-signal-square.svg-DnfzUw_B.js → interface-signal-square.svg-CxB5mcJQ.js} +1 -1
- package/web/assets/{interface-time-clock-circle.svg-BhxciNvX.js → interface-time-clock-circle.svg-CEnlQi79.js} +1 -1
- package/web/assets/{interface-time-hour-glass.svg-DBzSaSHQ.js → interface-time-hour-glass.svg-qL3_s19Q.js} +1 -1
- package/web/assets/{interface-users-multiple.svg-BULh1giq.js → interface-users-multiple.svg-Cz2iA33z.js} +1 -1
- package/web/assets/{interface-weather-moon.svg-D377V2os.js → interface-weather-moon.svg-BoT9GUK_.js} +1 -1
- package/web/assets/{javascript-BTXoJ3Qy.js → javascript-DWdA0-HW.js} +1 -1
- package/web/assets/{jsonMode-D4a3Khim.js → jsonMode-DxGrVlm0.js} +2 -2
- package/web/assets/{liquid-DfO0R4Mk.js → liquid-COqLk0mR.js} +1 -1
- package/web/assets/{lspLanguageFeatures-BvPWuQFt.js → lspLanguageFeatures--0hj1ZV4.js} +3 -3
- package/web/assets/{mail-chat-bubble-square.svg-SK3IJ6QN.js → mail-chat-bubble-square.svg-eiKzTBOv.js} +1 -1
- package/web/assets/{mail-send-email-paper-airplane.svg-CJFA7B2E.js → mail-send-email-paper-airplane.svg-CCI77Gk8.js} +1 -1
- package/web/assets/{mail-send-envelope.svg-eO_-QNyE.js → mail-send-envelope.svg-ChM5k_N7.js} +1 -1
- package/web/assets/{mdx-G_vwFSSe.js → mdx-CwXNREAO.js} +1 -1
- package/web/assets/{message-CxPw04rG.js → message-CSxReshg.js} +2 -2
- package/web/assets/{minus-Dp5ez1-1.js → minus-Cg0lH8Mn.js} +2 -2
- package/web/assets/modal-D3dkRJqD.js +1 -0
- package/web/assets/modal-ix4Amfqv.js +5 -0
- package/web/assets/{money-cashier-receipt.svg-EutWthy8.js → money-cashier-receipt.svg-WMIW7vxg.js} +1 -1
- package/web/assets/{money-currency-dollar-pay.svg-MnLj-orw.js → money-currency-dollar-pay.svg-qTcGSVX2.js} +1 -1
- package/web/assets/{money-graph-arrow-increase.svg-CVCZ3TyJ.js → money-graph-arrow-increase.svg-B-TQKOW-.js} +1 -1
- package/web/assets/{money-graph-bar-chart-increase.svg-DiUmCuhj.js → money-graph-bar-chart-increase.svg-CWCIjQcI.js} +1 -1
- package/web/assets/multiselect-C7U34xql.js +251 -0
- package/web/assets/{nature-ecology-leaf.svg-ByaLs72Y.js → nature-ecology-leaf.svg-CL26IBv2.js} +1 -1
- package/web/assets/{password-CxtOqagM.js → password-ZOY0bqV1.js} +4 -4
- package/web/assets/{phone-telephone.svg-BKz6Jkwn.js → phone-telephone.svg-BhzxDLVX.js} +1 -1
- package/web/assets/{plus-BPT_7GGk.js → plus-DsBv8bgd.js} +6 -6
- package/web/assets/process.store-DPp7dk63.js +1 -0
- package/web/assets/{programming-bug.svg-BwSc8f0s.js → programming-bug.svg-CBNm3E3F.js} +1 -1
- package/web/assets/{programming-cloud.svg-CEIulNEp.js → programming-cloud.svg-BrVRbl9B.js} +1 -1
- package/web/assets/{programming-computer-database-server.svg-Bc_F3NH0.js → programming-computer-database-server.svg-LQp6n-du.js} +1 -1
- package/web/assets/{programming-computer-database.svg-AYLkzJJE.js → programming-computer-database.svg-CSbhcIMU.js} +1 -1
- package/web/assets/{programming-module-four-layout.svg-DLpzPxNB.js → programming-module-four-layout.svg-DYEAcL2j.js} +1 -1
- package/web/assets/{programming-module-three.svg-CcuZn8dz.js → programming-module-three.svg-CCQXCU-e.js} +1 -1
- package/web/assets/{programming-module.svg-BjbGpQeu.js → programming-module.svg-Chrmf7k4.js} +1 -1
- package/web/assets/{programming-script-code.svg-poyfodgC.js → programming-script-code.svg-DPhhp3IW.js} +1 -1
- package/web/assets/{python-DpMMlrWM.js → python-B7ePhfsS.js} +1 -1
- package/web/assets/{razor-Ba_mg6U5.js → razor-ChpzroOv.js} +1 -1
- package/web/assets/router-Df972Ysi.js +1 -0
- package/web/assets/settings-scope-CC3oHq2H.js +1 -0
- package/web/assets/settings.store-B31_cRNl.js +1 -0
- package/web/assets/{shopping-cart.svg-BX2KYVCw.js → shopping-cart.svg-bmefzlOu.js} +1 -1
- package/web/assets/{shopping-gift-present.svg-BOl2vYLg.js → shopping-gift-present.svg-aUOleva0.js} +1 -1
- package/web/assets/{shopping-shipping-box-parcel-package.svg-gxfbOgnM.js → shopping-shipping-box-parcel-package.svg-BLsRP4dg.js} +1 -1
- package/web/assets/{src-D0LXRijj.js → src-BPSr9dU2.js} +34 -34
- package/web/assets/src-Dt37H-VN.js +1 -0
- package/web/assets/tabpanel-DZQ_g__B.js +150 -0
- package/web/assets/{tag-new-circle.svg-CTRMBJyc.js → tag-new-circle.svg-kTMMMv-0.js} +1 -1
- package/web/assets/{toggleswitch-DcDrXRKn.js → toggleswitch-BWXDXl37.js} +2 -2
- package/web/assets/{travel-map-earth-globe.svg-BPp4IapC.js → travel-map-earth-globe.svg-BdQmz8_b.js} +1 -1
- package/web/assets/trpc-aSS7b3jh.js +1 -0
- package/web/assets/{tsMode-HfLOT-e5.js → tsMode-arHIUQbZ.js} +6 -6
- package/web/assets/{typescript-DJAEsDnw.js → typescript-Ds9kgbPd.js} +1 -1
- package/web/assets/useAiChatDrawer-C1xrMtLl.js +1 -0
- package/web/assets/useCloudOrg-BexK510D.js +97 -0
- package/web/assets/{useProjectCatalog-C95cDPIr.js → useProjectCatalog-BbSaTBSS.js} +1 -1
- package/web/assets/{xml-1frg7aol.js → xml-CO56TgpZ.js} +1 -1
- package/web/assets/{yaml-DXzDcMOS.js → yaml-DueFV2-x.js} +1 -1
- package/web/index.html +2 -2
- package/agent-manager-UUSQK6S2.js +0 -7
- package/chunk-Z3KAXI7V.js.map +0 -1
- package/src-Q3PSCMS7.js.map +0 -1
- package/web/assets/AgentScalarChatInterface.vue-Cin_Rbay.js +0 -13
- package/web/assets/AgentTerminalPage-YgCQj_Mj.js +0 -1
- package/web/assets/AiChatPage-cIE_ZdF6.js +0 -1
- package/web/assets/AppLayout-dYfSESzv.js +0 -1
- package/web/assets/AuditPage-Bw3-G8ZM.js +0 -1
- package/web/assets/CloudAccountPage-CA4dMsIm.js +0 -1
- package/web/assets/CloudAccountPage-DjljrEI_.js +0 -1
- package/web/assets/CloudMessagingPage-CbfH2vPo.js +0 -2
- package/web/assets/DashboardPage-Cn3bUyhR.js +0 -1
- package/web/assets/DirectoryPickerDialog-BmsAi5gR.js +0 -1
- package/web/assets/EnvironmentForm-BfF9IFRB.js +0 -108
- package/web/assets/EnvironmentFormPage-CebWv3I_.js +0 -1
- package/web/assets/EnvironmentListPage-DDJGOHvR.js +0 -1
- package/web/assets/KanbanBoardPage-BMXyvHOl.js +0 -4
- package/web/assets/KanbanListPage-YMm_7vzg.js +0 -1
- package/web/assets/LaunchProjectPage--S6EXtGb.css +0 -1
- package/web/assets/LaunchProjectPage-Da21oFjw.js +0 -1
- package/web/assets/LaunchServicesPage-8YJT1stQ.js +0 -1
- package/web/assets/LaunchServicesPage-pWREsZTD.css +0 -1
- package/web/assets/LogViewer-BYNRWqlP.js +0 -3
- package/web/assets/OrgKeyPrompt-De8D0zzy.js +0 -1
- package/web/assets/ProcessDetailPage-CVwMbU6x.js +0 -1
- package/web/assets/ProjectDetailPage-BjBN3hnN.js +0 -1
- package/web/assets/ProjectListPage-BRXKT6op.js +0 -1
- package/web/assets/RandomJobTestPage-dhDNam5v.js +0 -2
- package/web/assets/ScenarioEditorPage-yOp4ZF14.js +0 -14
- package/web/assets/SendToChatDialog-o4y1Q-OD.js +0 -1
- package/web/assets/ServiceControlsBar-BH1ZEFkK.js +0 -1
- package/web/assets/ServiceDetailPage-CFb0blqq.js +0 -2
- package/web/assets/ServiceFormPage-DzFQ_M1-.js +0 -1
- package/web/assets/SettingsPage-Bcs3tnUy.js +0 -2063
- package/web/assets/UnlockPage-BAxKs_K9.js +0 -1
- package/web/assets/UnlockPage-DE_HJy8h.css +0 -1
- package/web/assets/VariablesTable-CSuAPeF-.js +0 -1
- package/web/assets/VaultMigrationPage-BGJ2PP-7.css +0 -1
- package/web/assets/VaultMigrationPage-BJX9kunL.js +0 -1
- package/web/assets/VersionBadge-B9Wvyvf6.js +0 -1
- package/web/assets/WikiPage-CBZFOPL_.js +0 -1
- package/web/assets/WikiView-DxPrGyFy.js +0 -1
- package/web/assets/add-scalar-classes-vtTXFTZ6.js +0 -387
- package/web/assets/auth-errors-DpUvxKid.js +0 -1
- package/web/assets/autocomplete-BakcEoGP.js +0 -308
- package/web/assets/card-DcpoBJHQ.js +0 -32
- package/web/assets/client-CKBKBNVm.js +0 -24
- package/web/assets/cloud-chat.store-Ci1DBP5j.js +0 -1
- package/web/assets/cloud-session-CzYQ65k8.js +0 -1
- package/web/assets/column-CVuKYYbZ.js +0 -907
- package/web/assets/interface-content-folder.svg-BikaY449.js +0 -1
- package/web/assets/modal-CGT4d1lM.js +0 -5
- package/web/assets/modal-D_N6NaGL.js +0 -1
- package/web/assets/multiselect-C6uayHqj.js +0 -251
- package/web/assets/process.store-CMxuFjFg.js +0 -1
- package/web/assets/router-QZ5Z8Lh7.js +0 -1
- package/web/assets/settings-scope-D7umae8c.js +0 -1
- package/web/assets/settings.store-Dte8TdJb.js +0 -1
- package/web/assets/src-DWvNj-EG.js +0 -1
- package/web/assets/tabpanel-Bkt-f7d6.js +0 -150
- package/web/assets/trpc-Dtgb4BMw.js +0 -1
- package/web/assets/useAiChatDrawer-fzyQ-fyM.js +0 -1
- package/web/assets/useCloudOrg-Bg7-icbW.js +0 -97
- /package/{agent-manager-UUSQK6S2.js.map → agent-manager-YDLSYZE3.js.map} +0 -0
- /package/web/assets/{uuid-CXjA27vZ.js → uuid-FpfcaBnR.js} +0 -0
|
@@ -85,8 +85,10 @@ import {
|
|
|
85
85
|
registerProjectLoader,
|
|
86
86
|
rememberFile,
|
|
87
87
|
rememberOrgName,
|
|
88
|
+
restartInstance,
|
|
88
89
|
rootOfProjectAmong,
|
|
89
90
|
rootOfProjectRef,
|
|
91
|
+
scheduleSelfRestart,
|
|
90
92
|
serviceStore,
|
|
91
93
|
setEncryptionKey,
|
|
92
94
|
setEncryptionKeyInMemory,
|
|
@@ -101,7 +103,7 @@ import {
|
|
|
101
103
|
vaultIdOfRoot,
|
|
102
104
|
wasRead,
|
|
103
105
|
writeEntity
|
|
104
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-HPYBAUAH.js";
|
|
105
107
|
|
|
106
108
|
// ../server/src/create-server.ts
|
|
107
109
|
import express from "express";
|
|
@@ -4376,7 +4378,7 @@ var environmentRouter = router({
|
|
|
4376
4378
|
|
|
4377
4379
|
// ../server/src/trpc/routers/settings.ts
|
|
4378
4380
|
import { promises as dns } from "dns";
|
|
4379
|
-
import { z as
|
|
4381
|
+
import { z as z11 } from "zod";
|
|
4380
4382
|
import { TRPCError as TRPCError8 } from "@trpc/server";
|
|
4381
4383
|
|
|
4382
4384
|
// ../server/src/services/settings-scope.ts
|
|
@@ -4388,6 +4390,122 @@ async function vaultOfProject(projectId) {
|
|
|
4388
4390
|
return refs[0]?.orgId ?? void 0;
|
|
4389
4391
|
}
|
|
4390
4392
|
|
|
4393
|
+
// ../server/src/services/lan-mode.ts
|
|
4394
|
+
import { networkInterfaces } from "os";
|
|
4395
|
+
import { readFile as readFile10, writeFile as writeFile10, rename as rename10, mkdir as mkdir10 } from "fs/promises";
|
|
4396
|
+
import { join as join11 } from "path";
|
|
4397
|
+
import { z as z10 } from "zod";
|
|
4398
|
+
var LOOPBACK = "127.0.0.1";
|
|
4399
|
+
var ANY = "0.0.0.0";
|
|
4400
|
+
var NETWORK_FILE = "network.json";
|
|
4401
|
+
var NetworkFileSchema = z10.object({
|
|
4402
|
+
instances: z10.record(z10.string(), z10.object({ lanEnabled: z10.boolean().default(false) })).default({})
|
|
4403
|
+
});
|
|
4404
|
+
var httpServer = null;
|
|
4405
|
+
function instanceKey() {
|
|
4406
|
+
return env.DATA_DIR;
|
|
4407
|
+
}
|
|
4408
|
+
function networkFilePath() {
|
|
4409
|
+
return join11(machineRoot(), NETWORK_FILE);
|
|
4410
|
+
}
|
|
4411
|
+
async function readFileState() {
|
|
4412
|
+
try {
|
|
4413
|
+
return NetworkFileSchema.parse(JSON.parse(await readFile10(networkFilePath(), "utf-8")));
|
|
4414
|
+
} catch {
|
|
4415
|
+
return { instances: {} };
|
|
4416
|
+
}
|
|
4417
|
+
}
|
|
4418
|
+
async function readPersisted() {
|
|
4419
|
+
const state = await readFileState();
|
|
4420
|
+
return state.instances[instanceKey()]?.lanEnabled ?? false;
|
|
4421
|
+
}
|
|
4422
|
+
async function writePersisted(lanEnabled) {
|
|
4423
|
+
const root = machineRoot();
|
|
4424
|
+
await mkdir10(root, { recursive: true });
|
|
4425
|
+
const state = await readFileState();
|
|
4426
|
+
state.instances[instanceKey()] = { lanEnabled };
|
|
4427
|
+
const filePath = networkFilePath();
|
|
4428
|
+
const tmpPath = filePath + ".tmp";
|
|
4429
|
+
await writeFile10(tmpPath, JSON.stringify(state, null, 2), "utf-8");
|
|
4430
|
+
await rename10(tmpPath, filePath);
|
|
4431
|
+
}
|
|
4432
|
+
function registerHttpServer(server) {
|
|
4433
|
+
httpServer = server;
|
|
4434
|
+
}
|
|
4435
|
+
function lanIps() {
|
|
4436
|
+
const found = [];
|
|
4437
|
+
for (const nets of Object.values(networkInterfaces())) {
|
|
4438
|
+
for (const net of nets ?? []) {
|
|
4439
|
+
if (net.family === "IPv4" && !net.internal) found.push(net.address);
|
|
4440
|
+
}
|
|
4441
|
+
}
|
|
4442
|
+
return found;
|
|
4443
|
+
}
|
|
4444
|
+
function currentPort() {
|
|
4445
|
+
const address = httpServer?.address();
|
|
4446
|
+
return typeof address === "object" && address ? address.port : env.PORT;
|
|
4447
|
+
}
|
|
4448
|
+
function networkInfo() {
|
|
4449
|
+
const port = currentPort();
|
|
4450
|
+
return {
|
|
4451
|
+
host: env.HOST,
|
|
4452
|
+
port,
|
|
4453
|
+
lanEnabled: env.RUNEYA_LAN_PROXY,
|
|
4454
|
+
lanUrls: env.RUNEYA_LAN_PROXY ? lanIps().map((ip) => `http://${ip}:${port}`) : []
|
|
4455
|
+
};
|
|
4456
|
+
}
|
|
4457
|
+
function setHost(host, enabled) {
|
|
4458
|
+
env.HOST = host;
|
|
4459
|
+
env.RUNEYA_HOST = host;
|
|
4460
|
+
env.RUNEYA_LAN_PROXY = enabled;
|
|
4461
|
+
process.env.RUNEYA_HOST = host;
|
|
4462
|
+
process.env.RUNEYA_LAN_PROXY = enabled ? "true" : "false";
|
|
4463
|
+
}
|
|
4464
|
+
async function rebind(host, previousHost) {
|
|
4465
|
+
const server = httpServer;
|
|
4466
|
+
if (!server?.listening) return;
|
|
4467
|
+
const port = currentPort();
|
|
4468
|
+
const listenOn = (target) => new Promise((resolve7, reject) => {
|
|
4469
|
+
const onError = (err) => {
|
|
4470
|
+
server.removeListener("listening", onListening);
|
|
4471
|
+
reject(err);
|
|
4472
|
+
};
|
|
4473
|
+
const onListening = () => {
|
|
4474
|
+
server.removeListener("error", onError);
|
|
4475
|
+
resolve7();
|
|
4476
|
+
};
|
|
4477
|
+
server.once("error", onError);
|
|
4478
|
+
server.once("listening", onListening);
|
|
4479
|
+
server.listen(port, target);
|
|
4480
|
+
});
|
|
4481
|
+
server.close(() => {
|
|
4482
|
+
});
|
|
4483
|
+
try {
|
|
4484
|
+
await listenOn(host);
|
|
4485
|
+
} catch (err) {
|
|
4486
|
+
setHost(previousHost, previousHost === ANY);
|
|
4487
|
+
await listenOn(previousHost).catch(() => {
|
|
4488
|
+
});
|
|
4489
|
+
throw err;
|
|
4490
|
+
}
|
|
4491
|
+
}
|
|
4492
|
+
async function applyPersistedLanMode() {
|
|
4493
|
+
if (env.RUNEYA_LAN_PROXY) return;
|
|
4494
|
+
if (env.HOST !== LOOPBACK && env.HOST !== "localhost") return;
|
|
4495
|
+
if (!await readPersisted()) return;
|
|
4496
|
+
setHost(ANY, true);
|
|
4497
|
+
console.log("[server] LAN mode: activ\xE9 par les r\xE9glages \u2014 \xE9coute sur 0.0.0.0");
|
|
4498
|
+
}
|
|
4499
|
+
async function setLanMode(enabled) {
|
|
4500
|
+
await writePersisted(enabled);
|
|
4501
|
+
const previousHost = env.HOST;
|
|
4502
|
+
const host = enabled ? ANY : LOOPBACK;
|
|
4503
|
+
setHost(host, enabled);
|
|
4504
|
+
if (host !== previousHost) await rebind(host, previousHost);
|
|
4505
|
+
console.log(`[server] LAN mode: ${enabled ? "activ\xE9" : "d\xE9sactiv\xE9"} \u2014 \xE9coute sur ${host}`);
|
|
4506
|
+
return networkInfo();
|
|
4507
|
+
}
|
|
4508
|
+
|
|
4391
4509
|
// ../server/src/trpc/routers/settings.ts
|
|
4392
4510
|
var NotificationPreferencesPatchSchema = NotificationPreferencesSchema.partial().strict();
|
|
4393
4511
|
function maskApiKey2(plaintext) {
|
|
@@ -4395,8 +4513,8 @@ function maskApiKey2(plaintext) {
|
|
|
4395
4513
|
return plaintext.slice(0, 4) + "****" + plaintext.slice(-4);
|
|
4396
4514
|
}
|
|
4397
4515
|
var ScopeShape = {
|
|
4398
|
-
orgId:
|
|
4399
|
-
projectId:
|
|
4516
|
+
orgId: z11.string().max(128).nullable().optional(),
|
|
4517
|
+
projectId: z11.string().max(128).optional()
|
|
4400
4518
|
};
|
|
4401
4519
|
async function scopeOf(input) {
|
|
4402
4520
|
return input?.orgId ?? await vaultOfProject(input?.projectId);
|
|
@@ -4423,6 +4541,27 @@ var settingsRouter = router({
|
|
|
4423
4541
|
// whichever directory the server happened to be started in.
|
|
4424
4542
|
machineDir: machineRoot()
|
|
4425
4543
|
})),
|
|
4544
|
+
/**
|
|
4545
|
+
* Où le serveur écoute, et s'il est joignable depuis le réseau local.
|
|
4546
|
+
*/
|
|
4547
|
+
getNetwork: protectedProcedure.query(() => networkInfo()),
|
|
4548
|
+
/**
|
|
4549
|
+
* Exposer — ou retirer — Runeya du réseau local, sans redémarrage.
|
|
4550
|
+
*
|
|
4551
|
+
* La socket d'écoute est rouverte sur place : les connexions en cours, dont
|
|
4552
|
+
* celle de l'onglet qui bascule, ne sont pas coupées. Le choix est mémorisé
|
|
4553
|
+
* dans les réglages, donc conservé au prochain démarrage.
|
|
4554
|
+
*/
|
|
4555
|
+
setLanMode: protectedProcedure.input(z11.object({ enabled: z11.boolean() })).mutation(async ({ input }) => {
|
|
4556
|
+
try {
|
|
4557
|
+
return await setLanMode(input.enabled);
|
|
4558
|
+
} catch (err) {
|
|
4559
|
+
throw new TRPCError8({
|
|
4560
|
+
code: "INTERNAL_SERVER_ERROR",
|
|
4561
|
+
message: `Impossible de changer l'adresse d'\xE9coute : ${err.message}`
|
|
4562
|
+
});
|
|
4563
|
+
}
|
|
4564
|
+
}),
|
|
4426
4565
|
/**
|
|
4427
4566
|
* Update settings (mode, cloudUrl)
|
|
4428
4567
|
*/
|
|
@@ -4438,7 +4577,7 @@ var settingsRouter = router({
|
|
|
4438
4577
|
/**
|
|
4439
4578
|
* Get notification preferences
|
|
4440
4579
|
*/
|
|
4441
|
-
getNotificationPreferences: protectedProcedure.input(
|
|
4580
|
+
getNotificationPreferences: protectedProcedure.input(z11.object(ScopeShape).optional()).query(async ({ input }) => {
|
|
4442
4581
|
const priv = await settingsManager.getPrivateSettings(await scopeOf(input));
|
|
4443
4582
|
return NotificationPreferencesSchema.parse(priv.notifications ?? {});
|
|
4444
4583
|
}),
|
|
@@ -4469,7 +4608,7 @@ var settingsRouter = router({
|
|
|
4469
4608
|
/**
|
|
4470
4609
|
* Get single parser by ID
|
|
4471
4610
|
*/
|
|
4472
|
-
getParser: protectedProcedure.input(
|
|
4611
|
+
getParser: protectedProcedure.input(z11.object({ id: z11.string().max(128) })).query(async ({ input }) => {
|
|
4473
4612
|
const settings = await settingsManager.getSettings();
|
|
4474
4613
|
const parser = (settings.logParsers || []).find((p) => p.id === input.id);
|
|
4475
4614
|
if (!parser) {
|
|
@@ -4544,7 +4683,7 @@ var settingsRouter = router({
|
|
|
4544
4683
|
/**
|
|
4545
4684
|
* Delete parser by ID
|
|
4546
4685
|
*/
|
|
4547
|
-
deleteParser: protectedProcedure.input(
|
|
4686
|
+
deleteParser: protectedProcedure.input(z11.object({ id: z11.string().max(128) })).mutation(async ({ input }) => {
|
|
4548
4687
|
const settings = await settingsManager.getSettings();
|
|
4549
4688
|
const newParsers = (settings.logParsers || []).filter(
|
|
4550
4689
|
(p) => p.id !== input.id
|
|
@@ -4567,7 +4706,7 @@ var settingsRouter = router({
|
|
|
4567
4706
|
/**
|
|
4568
4707
|
* List AI providers (API keys are masked)
|
|
4569
4708
|
*/
|
|
4570
|
-
listAIProviders: protectedProcedure.input(
|
|
4709
|
+
listAIProviders: protectedProcedure.input(z11.object(ScopeShape).optional()).query(async ({ input }) => {
|
|
4571
4710
|
const vault = await scopeOf(input);
|
|
4572
4711
|
const priv = await settingsManager.getPrivateSettings(vault);
|
|
4573
4712
|
return (priv.aiProviders ?? []).map((p) => {
|
|
@@ -4585,12 +4724,12 @@ var settingsRouter = router({
|
|
|
4585
4724
|
/**
|
|
4586
4725
|
* Create AI provider
|
|
4587
4726
|
*/
|
|
4588
|
-
createAIProvider: protectedProcedure.input(
|
|
4589
|
-
name:
|
|
4727
|
+
createAIProvider: protectedProcedure.input(z11.object({
|
|
4728
|
+
name: z11.string().min(1).max(200),
|
|
4590
4729
|
provider: AIProviderSchema.shape.provider,
|
|
4591
|
-
apiKey:
|
|
4730
|
+
apiKey: z11.string().max(500).optional(),
|
|
4592
4731
|
// optional for providers like Ollama
|
|
4593
|
-
model:
|
|
4732
|
+
model: z11.string().max(200).optional(),
|
|
4594
4733
|
...ScopeShape
|
|
4595
4734
|
})).mutation(async ({ input }) => {
|
|
4596
4735
|
if (input.provider !== "ollama" && !input.apiKey?.trim()) {
|
|
@@ -4623,12 +4762,12 @@ var settingsRouter = router({
|
|
|
4623
4762
|
/**
|
|
4624
4763
|
* Update AI provider (apiKey optional — omit to keep existing)
|
|
4625
4764
|
*/
|
|
4626
|
-
updateAIProvider: protectedProcedure.input(
|
|
4627
|
-
id:
|
|
4628
|
-
name:
|
|
4765
|
+
updateAIProvider: protectedProcedure.input(z11.object({
|
|
4766
|
+
id: z11.string().min(1).max(128),
|
|
4767
|
+
name: z11.string().min(1).max(200).optional(),
|
|
4629
4768
|
provider: AIProviderSchema.shape.provider.optional(),
|
|
4630
|
-
apiKey:
|
|
4631
|
-
model:
|
|
4769
|
+
apiKey: z11.string().min(1).max(500).optional(),
|
|
4770
|
+
model: z11.string().max(200).optional(),
|
|
4632
4771
|
...ScopeShape
|
|
4633
4772
|
})).mutation(async ({ input }) => {
|
|
4634
4773
|
const vault = await scopeOf(input);
|
|
@@ -4661,7 +4800,7 @@ var settingsRouter = router({
|
|
|
4661
4800
|
/**
|
|
4662
4801
|
* Delete AI provider
|
|
4663
4802
|
*/
|
|
4664
|
-
deleteAIProvider: protectedProcedure.input(
|
|
4803
|
+
deleteAIProvider: protectedProcedure.input(z11.object({ id: z11.string().min(1).max(128), ...ScopeShape })).mutation(async ({ input }) => {
|
|
4665
4804
|
const vault = await scopeOf(input);
|
|
4666
4805
|
const priv = await settingsManager.getPrivateSettings(vault);
|
|
4667
4806
|
const providers = priv.aiProviders ?? [];
|
|
@@ -4675,7 +4814,7 @@ var settingsRouter = router({
|
|
|
4675
4814
|
/**
|
|
4676
4815
|
* Set one provider as active (clears active flag on all others)
|
|
4677
4816
|
*/
|
|
4678
|
-
setActiveAIProvider: protectedProcedure.input(
|
|
4817
|
+
setActiveAIProvider: protectedProcedure.input(z11.object({ id: z11.string().min(1).max(128), ...ScopeShape })).mutation(async ({ input }) => {
|
|
4679
4818
|
const vault = await scopeOf(input);
|
|
4680
4819
|
const priv = await settingsManager.getPrivateSettings(vault);
|
|
4681
4820
|
const providers = priv.aiProviders ?? [];
|
|
@@ -4691,7 +4830,7 @@ var settingsRouter = router({
|
|
|
4691
4830
|
/**
|
|
4692
4831
|
* Get Traefik config for a specific agent (never returns credentials or cert key in plain text)
|
|
4693
4832
|
*/
|
|
4694
|
-
getAgentTraefikConfig: protectedProcedure.input(
|
|
4833
|
+
getAgentTraefikConfig: protectedProcedure.input(z11.object({ agentId: z11.string().max(128) })).query(async ({ input }) => {
|
|
4695
4834
|
const raw = agentStore.getTraefikConfig(input.agentId);
|
|
4696
4835
|
const parsed = raw ? TraefikConfigSchema.safeParse(raw) : null;
|
|
4697
4836
|
const config = parsed?.success ? parsed.data : null;
|
|
@@ -4711,16 +4850,16 @@ var settingsRouter = router({
|
|
|
4711
4850
|
/**
|
|
4712
4851
|
* Update Traefik config for a specific agent (credentials are encrypted before saving)
|
|
4713
4852
|
*/
|
|
4714
|
-
updateAgentTraefikConfig: protectedProcedure.input(
|
|
4715
|
-
agentId:
|
|
4716
|
-
enabled:
|
|
4717
|
-
acmeEmail:
|
|
4718
|
-
wildcardDomain:
|
|
4719
|
-
httpPort:
|
|
4720
|
-
httpsPort:
|
|
4721
|
-
dnsProvider:
|
|
4722
|
-
dnsCredentials:
|
|
4723
|
-
acmeStaging:
|
|
4853
|
+
updateAgentTraefikConfig: protectedProcedure.input(z11.object({
|
|
4854
|
+
agentId: z11.string().max(128),
|
|
4855
|
+
enabled: z11.boolean().optional(),
|
|
4856
|
+
acmeEmail: z11.string().email().max(256).optional(),
|
|
4857
|
+
wildcardDomain: z11.string().max(253).optional(),
|
|
4858
|
+
httpPort: z11.number().int().min(1).max(65535).optional(),
|
|
4859
|
+
httpsPort: z11.number().int().min(1).max(65535).optional(),
|
|
4860
|
+
dnsProvider: z11.string().max(64).optional(),
|
|
4861
|
+
dnsCredentials: z11.record(z11.string().max(64), z11.string().max(2048)).optional(),
|
|
4862
|
+
acmeStaging: z11.boolean().optional()
|
|
4724
4863
|
})).mutation(async ({ input }) => {
|
|
4725
4864
|
const { agentId, ...fields } = input;
|
|
4726
4865
|
const raw = agentStore.getTraefikConfig(agentId);
|
|
@@ -4749,13 +4888,13 @@ var settingsRouter = router({
|
|
|
4749
4888
|
/**
|
|
4750
4889
|
* Get Traefik config files content for a specific agent
|
|
4751
4890
|
*/
|
|
4752
|
-
getAgentTraefikConfigFiles: protectedProcedure.input(
|
|
4891
|
+
getAgentTraefikConfigFiles: protectedProcedure.input(z11.object({ agentId: z11.string().max(128) })).query(async ({ input }) => {
|
|
4753
4892
|
return agentManager.agentQuery(
|
|
4754
4893
|
input.agentId,
|
|
4755
4894
|
"config.getTraefikConfigFiles"
|
|
4756
4895
|
);
|
|
4757
4896
|
}),
|
|
4758
|
-
getAgentTraefikFileTree: protectedProcedure.input(
|
|
4897
|
+
getAgentTraefikFileTree: protectedProcedure.input(z11.object({ agentId: z11.string().max(128) })).query(async ({ input }) => {
|
|
4759
4898
|
return agentManager.agentQuery(
|
|
4760
4899
|
input.agentId,
|
|
4761
4900
|
"config.getTraefikFileTree"
|
|
@@ -4764,7 +4903,7 @@ var settingsRouter = router({
|
|
|
4764
4903
|
/**
|
|
4765
4904
|
* Get Traefik container logs for a specific agent (snapshot)
|
|
4766
4905
|
*/
|
|
4767
|
-
getAgentTraefikLogs: protectedProcedure.input(
|
|
4906
|
+
getAgentTraefikLogs: protectedProcedure.input(z11.object({ agentId: z11.string().max(128), lines: z11.number().int().min(1).max(500).default(100) })).query(async ({ input }) => {
|
|
4768
4907
|
const result = await agentManager.agentQuery(
|
|
4769
4908
|
input.agentId,
|
|
4770
4909
|
"config.getTraefikLogs",
|
|
@@ -4775,7 +4914,7 @@ var settingsRouter = router({
|
|
|
4775
4914
|
/**
|
|
4776
4915
|
* Stream Traefik logs in real-time (subscription, yields new lines every 500ms)
|
|
4777
4916
|
*/
|
|
4778
|
-
streamAgentTraefikLogs: protectedProcedure.input(
|
|
4917
|
+
streamAgentTraefikLogs: protectedProcedure.input(z11.object({ agentId: z11.string().max(128) })).subscription(async function* ({ input, signal }) {
|
|
4779
4918
|
let seen = 0;
|
|
4780
4919
|
while (!signal?.aborted) {
|
|
4781
4920
|
try {
|
|
@@ -4798,7 +4937,7 @@ var settingsRouter = router({
|
|
|
4798
4937
|
/**
|
|
4799
4938
|
* Restart Traefik container on a specific agent (re-pushes config first to handle agent restarts)
|
|
4800
4939
|
*/
|
|
4801
|
-
restartAgentTraefik: protectedProcedure.input(
|
|
4940
|
+
restartAgentTraefik: protectedProcedure.input(z11.object({ agentId: z11.string().max(128) })).mutation(async ({ input }) => {
|
|
4802
4941
|
const raw = agentStore.getTraefikConfig(input.agentId);
|
|
4803
4942
|
const parsed = raw ? TraefikConfigSchema.safeParse(raw) : null;
|
|
4804
4943
|
const config = parsed?.success ? parsed.data : null;
|
|
@@ -4811,7 +4950,7 @@ var settingsRouter = router({
|
|
|
4811
4950
|
/**
|
|
4812
4951
|
* Force certificate renewal for a specific agent (wipes acme.json + restarts container)
|
|
4813
4952
|
*/
|
|
4814
|
-
renewAgentTraefikCert: protectedProcedure.input(
|
|
4953
|
+
renewAgentTraefikCert: protectedProcedure.input(z11.object({ agentId: z11.string().max(128) })).mutation(async ({ input }) => {
|
|
4815
4954
|
const raw = agentStore.getTraefikConfig(input.agentId);
|
|
4816
4955
|
const parsed = raw ? TraefikConfigSchema.safeParse(raw) : null;
|
|
4817
4956
|
const config = parsed?.success ? parsed.data : null;
|
|
@@ -4824,7 +4963,7 @@ var settingsRouter = router({
|
|
|
4824
4963
|
/**
|
|
4825
4964
|
* Validate Traefik configuration for a specific agent
|
|
4826
4965
|
*/
|
|
4827
|
-
validateAgentTraefikConfig: protectedProcedure.input(
|
|
4966
|
+
validateAgentTraefikConfig: protectedProcedure.input(z11.object({ agentId: z11.string().max(128) })).query(async ({ input }) => {
|
|
4828
4967
|
const raw = agentStore.getTraefikConfig(input.agentId);
|
|
4829
4968
|
const parsed = raw ? TraefikConfigSchema.safeParse(raw) : null;
|
|
4830
4969
|
const config = parsed?.success ? parsed.data : null;
|
|
@@ -4926,12 +5065,12 @@ var settingsRouter = router({
|
|
|
4926
5065
|
* Test parser code: compile and run it against sample logs, return per-line results
|
|
4927
5066
|
*/
|
|
4928
5067
|
testParser: protectedProcedure.input(
|
|
4929
|
-
|
|
4930
|
-
code:
|
|
4931
|
-
sampleLogs:
|
|
4932
|
-
|
|
4933
|
-
raw:
|
|
4934
|
-
stream:
|
|
5068
|
+
z11.object({
|
|
5069
|
+
code: z11.string().max(5e4),
|
|
5070
|
+
sampleLogs: z11.array(
|
|
5071
|
+
z11.object({
|
|
5072
|
+
raw: z11.string().max(16384),
|
|
5073
|
+
stream: z11.enum(["stdout", "stderr"])
|
|
4935
5074
|
})
|
|
4936
5075
|
).max(100).default([])
|
|
4937
5076
|
})
|
|
@@ -4975,30 +5114,30 @@ var settingsRouter = router({
|
|
|
4975
5114
|
});
|
|
4976
5115
|
|
|
4977
5116
|
// ../server/src/trpc/routers/editor.ts
|
|
4978
|
-
import { z as
|
|
5117
|
+
import { z as z13 } from "zod";
|
|
4979
5118
|
import { TRPCError as TRPCError9 } from "@trpc/server";
|
|
4980
5119
|
import { execFile as execFile3, spawn as spawn2 } from "child_process";
|
|
4981
5120
|
import { stat as stat4 } from "fs/promises";
|
|
4982
|
-
import { resolve as resolve2, join as
|
|
5121
|
+
import { resolve as resolve2, join as join13 } from "path";
|
|
4983
5122
|
import { homedir as homedir2 } from "os";
|
|
4984
5123
|
|
|
4985
5124
|
// ../server/src/services/user-config-manager.ts
|
|
4986
|
-
import { readFile as
|
|
4987
|
-
import { join as
|
|
5125
|
+
import { readFile as readFile11, writeFile as writeFile11, rename as rename11, mkdir as mkdir11, chmod as chmod9 } from "fs/promises";
|
|
5126
|
+
import { join as join12 } from "path";
|
|
4988
5127
|
import { homedir } from "os";
|
|
4989
|
-
import { z as
|
|
4990
|
-
var CONFIG_DIR =
|
|
5128
|
+
import { z as z12 } from "zod";
|
|
5129
|
+
var CONFIG_DIR = join12(homedir(), ".runeya");
|
|
4991
5130
|
var CONFIG_FILE = "runeya.conf";
|
|
4992
|
-
var EditorPreferencesSchema =
|
|
4993
|
-
default:
|
|
4994
|
-
}).catchall(
|
|
4995
|
-
var ProjectSettingsSchema =
|
|
4996
|
-
settings:
|
|
5131
|
+
var EditorPreferencesSchema = z12.object({
|
|
5132
|
+
default: z12.string().max(64).optional()
|
|
5133
|
+
}).catchall(z12.string().max(64)).refine((obj) => Object.keys(obj).length <= 500, "Too many editor preferences");
|
|
5134
|
+
var ProjectSettingsSchema = z12.object({
|
|
5135
|
+
settings: z12.object({
|
|
4997
5136
|
editors: EditorPreferencesSchema.optional()
|
|
4998
5137
|
}).optional()
|
|
4999
5138
|
});
|
|
5000
|
-
var UserConfigSchema =
|
|
5001
|
-
|
|
5139
|
+
var UserConfigSchema = z12.record(
|
|
5140
|
+
z12.string().max(128),
|
|
5002
5141
|
ProjectSettingsSchema
|
|
5003
5142
|
).refine((obj) => Object.keys(obj).length <= 100, "Too many projects in config");
|
|
5004
5143
|
function configKey(ref) {
|
|
@@ -5007,20 +5146,20 @@ function configKey(ref) {
|
|
|
5007
5146
|
var UserConfigManager = class {
|
|
5008
5147
|
config = null;
|
|
5009
5148
|
async ensureDir() {
|
|
5010
|
-
await
|
|
5149
|
+
await mkdir11(CONFIG_DIR, { recursive: true });
|
|
5011
5150
|
}
|
|
5012
5151
|
async atomicWrite(data) {
|
|
5013
5152
|
await this.ensureDir();
|
|
5014
|
-
const filePath =
|
|
5153
|
+
const filePath = join12(CONFIG_DIR, CONFIG_FILE);
|
|
5015
5154
|
const tmpPath = filePath + ".tmp";
|
|
5016
|
-
await
|
|
5017
|
-
await
|
|
5155
|
+
await writeFile11(tmpPath, JSON.stringify(data, null, 2), "utf-8");
|
|
5156
|
+
await rename11(tmpPath, filePath);
|
|
5018
5157
|
await chmod9(filePath, 384);
|
|
5019
5158
|
}
|
|
5020
5159
|
async getConfig() {
|
|
5021
5160
|
if (!this.config) {
|
|
5022
5161
|
try {
|
|
5023
|
-
const raw = await
|
|
5162
|
+
const raw = await readFile11(join12(CONFIG_DIR, CONFIG_FILE), "utf-8");
|
|
5024
5163
|
const parsed = UserConfigSchema.safeParse(JSON.parse(raw));
|
|
5025
5164
|
this.config = parsed.success ? parsed.data : {};
|
|
5026
5165
|
} catch {
|
|
@@ -5090,16 +5229,16 @@ var editorRouter = router({
|
|
|
5090
5229
|
);
|
|
5091
5230
|
return results;
|
|
5092
5231
|
}),
|
|
5093
|
-
getPreferences: protectedProcedure.input(
|
|
5094
|
-
projectId:
|
|
5095
|
-
orgId:
|
|
5232
|
+
getPreferences: protectedProcedure.input(z13.object({
|
|
5233
|
+
projectId: z13.string().max(128),
|
|
5234
|
+
orgId: z13.string().max(128).nullable().optional()
|
|
5096
5235
|
})).query(async ({ input }) => {
|
|
5097
5236
|
return userConfigManager.getEditorPreferences({ id: input.projectId, orgId: input.orgId });
|
|
5098
5237
|
}),
|
|
5099
|
-
setDefault: protectedProcedure.input(
|
|
5100
|
-
projectId:
|
|
5101
|
-
orgId:
|
|
5102
|
-
editorKey:
|
|
5238
|
+
setDefault: protectedProcedure.input(z13.object({
|
|
5239
|
+
projectId: z13.string().max(128),
|
|
5240
|
+
orgId: z13.string().max(128).nullable().optional(),
|
|
5241
|
+
editorKey: z13.string().max(64)
|
|
5103
5242
|
})).mutation(async ({ input }) => {
|
|
5104
5243
|
if (!EDITOR_BY_KEY.has(input.editorKey)) {
|
|
5105
5244
|
throw new TRPCError9({ code: "BAD_REQUEST", message: `Unknown editor: ${input.editorKey}` });
|
|
@@ -5111,11 +5250,11 @@ var editorRouter = router({
|
|
|
5111
5250
|
);
|
|
5112
5251
|
return { success: true };
|
|
5113
5252
|
}),
|
|
5114
|
-
setServiceEditor: protectedProcedure.input(
|
|
5115
|
-
projectId:
|
|
5116
|
-
orgId:
|
|
5117
|
-
serviceId:
|
|
5118
|
-
editorKey:
|
|
5253
|
+
setServiceEditor: protectedProcedure.input(z13.object({
|
|
5254
|
+
projectId: z13.string().max(128),
|
|
5255
|
+
orgId: z13.string().max(128).nullable().optional(),
|
|
5256
|
+
serviceId: z13.string().max(128),
|
|
5257
|
+
editorKey: z13.string().max(64)
|
|
5119
5258
|
})).mutation(async ({ input }) => {
|
|
5120
5259
|
if (!EDITOR_BY_KEY.has(input.editorKey)) {
|
|
5121
5260
|
throw new TRPCError9({ code: "BAD_REQUEST", message: `Unknown editor: ${input.editorKey}` });
|
|
@@ -5127,10 +5266,10 @@ var editorRouter = router({
|
|
|
5127
5266
|
);
|
|
5128
5267
|
return { success: true };
|
|
5129
5268
|
}),
|
|
5130
|
-
removeServiceEditor: protectedProcedure.input(
|
|
5131
|
-
projectId:
|
|
5132
|
-
orgId:
|
|
5133
|
-
serviceId:
|
|
5269
|
+
removeServiceEditor: protectedProcedure.input(z13.object({
|
|
5270
|
+
projectId: z13.string().max(128),
|
|
5271
|
+
orgId: z13.string().max(128).nullable().optional(),
|
|
5272
|
+
serviceId: z13.string().max(128)
|
|
5134
5273
|
})).mutation(async ({ input }) => {
|
|
5135
5274
|
await userConfigManager.removeEditorPreference(
|
|
5136
5275
|
{ id: input.projectId, orgId: input.orgId },
|
|
@@ -5138,9 +5277,9 @@ var editorRouter = router({
|
|
|
5138
5277
|
);
|
|
5139
5278
|
return { success: true };
|
|
5140
5279
|
}),
|
|
5141
|
-
open: protectedProcedure.input(
|
|
5142
|
-
editorKey:
|
|
5143
|
-
path:
|
|
5280
|
+
open: protectedProcedure.input(z13.object({
|
|
5281
|
+
editorKey: z13.string().max(64),
|
|
5282
|
+
path: z13.string().max(4096)
|
|
5144
5283
|
})).mutation(async ({ input }) => {
|
|
5145
5284
|
const editor = EDITOR_BY_KEY.get(input.editorKey);
|
|
5146
5285
|
if (!editor) {
|
|
@@ -5163,17 +5302,17 @@ var editorRouter = router({
|
|
|
5163
5302
|
child.unref();
|
|
5164
5303
|
return { success: true };
|
|
5165
5304
|
}),
|
|
5166
|
-
openFile: protectedProcedure.input(
|
|
5167
|
-
editorKey:
|
|
5168
|
-
serviceId:
|
|
5169
|
-
relativePath:
|
|
5305
|
+
openFile: protectedProcedure.input(z13.object({
|
|
5306
|
+
editorKey: z13.string().max(64),
|
|
5307
|
+
serviceId: z13.string().max(128),
|
|
5308
|
+
relativePath: z13.string().max(4096)
|
|
5170
5309
|
})).mutation(async ({ input }) => {
|
|
5171
5310
|
const editor = EDITOR_BY_KEY.get(input.editorKey);
|
|
5172
5311
|
if (!editor) {
|
|
5173
5312
|
throw new TRPCError9({ code: "BAD_REQUEST", message: `Unknown editor: ${input.editorKey}` });
|
|
5174
5313
|
}
|
|
5175
5314
|
const cwd = await getServiceCwd(input.serviceId);
|
|
5176
|
-
const filePath =
|
|
5315
|
+
const filePath = join13(cwd, input.relativePath);
|
|
5177
5316
|
if (!filePath.startsWith(cwd)) {
|
|
5178
5317
|
throw new TRPCError9({ code: "BAD_REQUEST", message: "Path traversal not allowed" });
|
|
5179
5318
|
}
|
|
@@ -5194,65 +5333,65 @@ var editorRouter = router({
|
|
|
5194
5333
|
});
|
|
5195
5334
|
|
|
5196
5335
|
// ../server/src/trpc/routers/api-keys.ts
|
|
5197
|
-
import { z as
|
|
5336
|
+
import { z as z14 } from "zod";
|
|
5198
5337
|
import { TRPCError as TRPCError10 } from "@trpc/server";
|
|
5199
|
-
import { mkdir as
|
|
5200
|
-
import { join as
|
|
5338
|
+
import { mkdir as mkdir12, writeFile as writeFile12 } from "fs/promises";
|
|
5339
|
+
import { join as join14, dirname as dirname7 } from "path";
|
|
5201
5340
|
var ALLOWED_SKILL_PATHS = /* @__PURE__ */ new Set([
|
|
5202
5341
|
".claude/skills/runeya/SKILL.md",
|
|
5203
5342
|
".cursor/rules/runeya.mdc",
|
|
5204
5343
|
".windsurf/rules/runeya.md"
|
|
5205
5344
|
]);
|
|
5206
|
-
var KeyInputSchema =
|
|
5207
|
-
name:
|
|
5345
|
+
var KeyInputSchema = z14.object({
|
|
5346
|
+
name: z14.string().min(1).max(200),
|
|
5208
5347
|
scopes: ApiKeyScopeSchema,
|
|
5209
|
-
isPublic:
|
|
5348
|
+
isPublic: z14.boolean().default(false)
|
|
5210
5349
|
});
|
|
5211
5350
|
var apiKeysRouter = router({
|
|
5212
5351
|
list: protectedProcedure.query(() => apiKeyStore.list()),
|
|
5213
|
-
create: protectedProcedure.input(KeyInputSchema.extend({ orgId:
|
|
5352
|
+
create: protectedProcedure.input(KeyInputSchema.extend({ orgId: z14.string().min(1).max(128).nullable().optional() })).mutation(
|
|
5214
5353
|
({ input }) => apiKeyStore.create(input.name, input.scopes, input.isPublic, input.orgId ?? null)
|
|
5215
5354
|
),
|
|
5216
5355
|
/**
|
|
5217
5356
|
* Renvoie le secret d'une seule clé, sur demande explicite. `list` ne le
|
|
5218
5357
|
* contient pas : une clé ne doit jamais être re-servie en masse.
|
|
5219
5358
|
*/
|
|
5220
|
-
reveal: protectedProcedure.input(
|
|
5359
|
+
reveal: protectedProcedure.input(z14.object({ id: z14.string().max(128) })).query(async ({ input }) => {
|
|
5221
5360
|
const key = await apiKeyStore.reveal(input.id);
|
|
5222
5361
|
if (!key) throw new TRPCError10({ code: "NOT_FOUND", message: "API key not found" });
|
|
5223
5362
|
return { key };
|
|
5224
5363
|
}),
|
|
5225
|
-
update: protectedProcedure.input(KeyInputSchema.extend({ id:
|
|
5364
|
+
update: protectedProcedure.input(KeyInputSchema.extend({ id: z14.string().max(128) })).mutation(async ({ input }) => {
|
|
5226
5365
|
const updated = await apiKeyStore.update(input.id, input.name, input.scopes, input.isPublic);
|
|
5227
5366
|
if (!updated) throw new TRPCError10({ code: "NOT_FOUND", message: "API key not found" });
|
|
5228
5367
|
return maskApiKey(updated);
|
|
5229
5368
|
}),
|
|
5230
|
-
remove: protectedProcedure.input(
|
|
5369
|
+
remove: protectedProcedure.input(z14.object({ id: z14.string().max(128) })).mutation(async ({ input }) => {
|
|
5231
5370
|
const removed = await apiKeyStore.remove(input.id);
|
|
5232
5371
|
if (!removed) throw new TRPCError10({ code: "NOT_FOUND", message: "API key not found" });
|
|
5233
5372
|
return { success: true };
|
|
5234
5373
|
}),
|
|
5235
|
-
renewKey: protectedProcedure.input(
|
|
5374
|
+
renewKey: protectedProcedure.input(z14.object({ id: z14.string().max(128) })).mutation(async ({ input }) => {
|
|
5236
5375
|
const renewed = await apiKeyStore.renewKey(input.id);
|
|
5237
5376
|
if (!renewed) throw new TRPCError10({ code: "NOT_FOUND", message: "API key not found" });
|
|
5238
5377
|
return renewed;
|
|
5239
5378
|
}),
|
|
5240
|
-
writeSkillFile: protectedProcedure.input(
|
|
5241
|
-
relativePath:
|
|
5242
|
-
content:
|
|
5379
|
+
writeSkillFile: protectedProcedure.input(z14.object({
|
|
5380
|
+
relativePath: z14.string().max(256),
|
|
5381
|
+
content: z14.string().max(32768)
|
|
5243
5382
|
})).mutation(async ({ input }) => {
|
|
5244
5383
|
if (!ALLOWED_SKILL_PATHS.has(input.relativePath)) {
|
|
5245
5384
|
throw new TRPCError10({ code: "BAD_REQUEST", message: "Chemin non autoris\xE9" });
|
|
5246
5385
|
}
|
|
5247
|
-
const abs =
|
|
5248
|
-
await
|
|
5249
|
-
await
|
|
5386
|
+
const abs = join14(await resolveWorkspaceCwd({}), input.relativePath);
|
|
5387
|
+
await mkdir12(dirname7(abs), { recursive: true });
|
|
5388
|
+
await writeFile12(abs, input.content, { encoding: "utf-8", mode: 420 });
|
|
5250
5389
|
return { path: input.relativePath };
|
|
5251
5390
|
})
|
|
5252
5391
|
});
|
|
5253
5392
|
|
|
5254
5393
|
// ../server/src/trpc/routers/chat.ts
|
|
5255
|
-
import { z as
|
|
5394
|
+
import { z as z17 } from "zod";
|
|
5256
5395
|
import Anthropic2 from "@anthropic-ai/sdk";
|
|
5257
5396
|
import OpenAI2 from "openai";
|
|
5258
5397
|
import { execFile as execFile4 } from "child_process";
|
|
@@ -5606,11 +5745,11 @@ function buildApiDocs(apiBaseUrl, apiToken) {
|
|
|
5606
5745
|
}
|
|
5607
5746
|
|
|
5608
5747
|
// ../server/src/services/claude-transcript-sync.ts
|
|
5609
|
-
import { readdir as readdir2, access, readFile as
|
|
5748
|
+
import { readdir as readdir2, access, readFile as readFile12 } from "fs/promises";
|
|
5610
5749
|
import { watch } from "fs";
|
|
5611
5750
|
import { homedir as homedir3 } from "os";
|
|
5612
|
-
import { join as
|
|
5613
|
-
var PROJECTS_DIR =
|
|
5751
|
+
import { join as join15 } from "path";
|
|
5752
|
+
var PROJECTS_DIR = join15(homedir3(), ".claude", "projects");
|
|
5614
5753
|
var DEFAULT_TITLES = /* @__PURE__ */ new Set(["", "New conversation", "Nouvelle conversation"]);
|
|
5615
5754
|
async function findClaudeSessionFile(sessionId) {
|
|
5616
5755
|
let entries2;
|
|
@@ -5621,7 +5760,7 @@ async function findClaudeSessionFile(sessionId) {
|
|
|
5621
5760
|
}
|
|
5622
5761
|
const filename = `${sessionId}.jsonl`;
|
|
5623
5762
|
for (const dir of entries2) {
|
|
5624
|
-
const candidate =
|
|
5763
|
+
const candidate = join15(PROJECTS_DIR, dir, filename);
|
|
5625
5764
|
try {
|
|
5626
5765
|
await access(candidate);
|
|
5627
5766
|
return candidate;
|
|
@@ -5636,7 +5775,7 @@ async function claudeSessionExists(sessionId) {
|
|
|
5636
5775
|
async function readClaudeTranscript(sessionId) {
|
|
5637
5776
|
const path = await findClaudeSessionFile(sessionId);
|
|
5638
5777
|
if (!path) return { found: false, path: null, entries: [] };
|
|
5639
|
-
const raw = await
|
|
5778
|
+
const raw = await readFile12(path, "utf-8");
|
|
5640
5779
|
const entries2 = [];
|
|
5641
5780
|
for (const line of raw.split("\n")) {
|
|
5642
5781
|
if (!line.trim()) continue;
|
|
@@ -5784,7 +5923,7 @@ async function startClaudeTranscriptWatcher() {
|
|
|
5784
5923
|
}
|
|
5785
5924
|
for (const dir of topLevel) {
|
|
5786
5925
|
try {
|
|
5787
|
-
const w = watch(
|
|
5926
|
+
const w = watch(join15(PROJECTS_DIR, dir), (_event, filename) => {
|
|
5788
5927
|
handleFsEvent(filename ? filename.toString() : null);
|
|
5789
5928
|
});
|
|
5790
5929
|
w.on("error", () => {
|
|
@@ -5810,8 +5949,8 @@ function stopClaudeTranscriptWatcher() {
|
|
|
5810
5949
|
// ../server/src/services/codex-sessions.ts
|
|
5811
5950
|
import { readdir as readdir3 } from "fs/promises";
|
|
5812
5951
|
import { homedir as homedir4 } from "os";
|
|
5813
|
-
import { join as
|
|
5814
|
-
var SESSIONS_DIR =
|
|
5952
|
+
import { join as join16 } from "path";
|
|
5953
|
+
var SESSIONS_DIR = join16(homedir4(), ".codex", "sessions");
|
|
5815
5954
|
async function findCodexSessionFile(sessionId) {
|
|
5816
5955
|
const suffix = `-${sessionId}.jsonl`;
|
|
5817
5956
|
async function walk(dir) {
|
|
@@ -5822,7 +5961,7 @@ async function findCodexSessionFile(sessionId) {
|
|
|
5822
5961
|
return null;
|
|
5823
5962
|
}
|
|
5824
5963
|
for (const entry of entries2) {
|
|
5825
|
-
const full =
|
|
5964
|
+
const full = join16(dir, entry.name);
|
|
5826
5965
|
if (entry.isDirectory()) {
|
|
5827
5966
|
const found = await walk(full);
|
|
5828
5967
|
if (found) return found;
|
|
@@ -5842,12 +5981,12 @@ async function codexSessionExists(sessionId) {
|
|
|
5842
5981
|
import { TRPCError as TRPCError12 } from "@trpc/server";
|
|
5843
5982
|
|
|
5844
5983
|
// ../server/src/trpc/shared-schemas.ts
|
|
5845
|
-
import { z as
|
|
5846
|
-
var Id128Schema =
|
|
5847
|
-
var ConversationIdSchema =
|
|
5848
|
-
var NameSchema =
|
|
5849
|
-
var ShortString200Schema =
|
|
5850
|
-
var DescriptionSchema =
|
|
5984
|
+
import { z as z15 } from "zod";
|
|
5985
|
+
var Id128Schema = z15.string().max(128);
|
|
5986
|
+
var ConversationIdSchema = z15.string().max(128);
|
|
5987
|
+
var NameSchema = z15.string().min(1).max(200);
|
|
5988
|
+
var ShortString200Schema = z15.string().max(200);
|
|
5989
|
+
var DescriptionSchema = z15.string().max(2e3);
|
|
5851
5990
|
var OptionalProviderIdSchema = Id128Schema.optional();
|
|
5852
5991
|
|
|
5853
5992
|
// ../server/src/services/llms-txt-generator.ts
|
|
@@ -6782,11 +6921,11 @@ var ScenarioStore = class {
|
|
|
6782
6921
|
var scenarioStore = new ScenarioStore();
|
|
6783
6922
|
|
|
6784
6923
|
// ../server/src/services/scenario-run-store.ts
|
|
6785
|
-
import { mkdir as
|
|
6786
|
-
import { join as
|
|
6924
|
+
import { mkdir as mkdir14, rm as rm2, readFile as readFile14 } from "fs/promises";
|
|
6925
|
+
import { join as join17 } from "path";
|
|
6787
6926
|
|
|
6788
6927
|
// ../server/src/services/run-store-utils.ts
|
|
6789
|
-
import { chmod as chmod10, mkdir as
|
|
6928
|
+
import { chmod as chmod10, mkdir as mkdir13, rename as rename12, writeFile as writeFile13, readFile as readFile13 } from "fs/promises";
|
|
6790
6929
|
import { dirname as dirname8, resolve as resolve3, sep } from "path";
|
|
6791
6930
|
var SAFE_PATH_SEGMENT_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/;
|
|
6792
6931
|
function resolveConversationRunDir(rootDirName, conversationId) {
|
|
@@ -6801,10 +6940,10 @@ function resolveConversationRunDir(rootDirName, conversationId) {
|
|
|
6801
6940
|
return dir;
|
|
6802
6941
|
}
|
|
6803
6942
|
async function atomicWriteSecure(filePath, content) {
|
|
6804
|
-
await
|
|
6943
|
+
await mkdir13(dirname8(filePath), { recursive: true });
|
|
6805
6944
|
const tmpPath = `${filePath}.tmp`;
|
|
6806
|
-
await
|
|
6807
|
-
await
|
|
6945
|
+
await writeFile13(tmpPath, content, "utf-8");
|
|
6946
|
+
await rename12(tmpPath, filePath);
|
|
6808
6947
|
await chmod10(filePath, 384);
|
|
6809
6948
|
}
|
|
6810
6949
|
async function atomicWriteJsonSecure(filePath, data, pretty = false) {
|
|
@@ -6812,7 +6951,7 @@ async function atomicWriteJsonSecure(filePath, data, pretty = false) {
|
|
|
6812
6951
|
}
|
|
6813
6952
|
async function readJsonFileSafe(filePath) {
|
|
6814
6953
|
try {
|
|
6815
|
-
const raw = await
|
|
6954
|
+
const raw = await readFile13(filePath, "utf-8");
|
|
6816
6955
|
return JSON.parse(raw);
|
|
6817
6956
|
} catch {
|
|
6818
6957
|
return null;
|
|
@@ -6835,7 +6974,7 @@ var ScenarioRunStore = class _ScenarioRunStore {
|
|
|
6835
6974
|
}
|
|
6836
6975
|
async initializeConversationWorkspace(conversationId, scenario, userInput) {
|
|
6837
6976
|
const dir = this.getRunDir(conversationId);
|
|
6838
|
-
await
|
|
6977
|
+
await mkdir14(dir, { recursive: true });
|
|
6839
6978
|
await this.saveScenarioSnapshot(conversationId, scenario);
|
|
6840
6979
|
const nodesById = new Map(scenario.nodes.map((p) => [p.id, p]));
|
|
6841
6980
|
const teamMap = new Map(scenario.groups.map((t2) => [t2.id, t2.name]));
|
|
@@ -6860,8 +6999,8 @@ var ScenarioRunStore = class _ScenarioRunStore {
|
|
|
6860
6999
|
"- Use read-only references from linked upstream files as context.",
|
|
6861
7000
|
""
|
|
6862
7001
|
].join("\n");
|
|
6863
|
-
await atomicWriteSecure(
|
|
6864
|
-
await atomicWriteSecure(
|
|
7002
|
+
await atomicWriteSecure(join17(dir, "README.md"), overview);
|
|
7003
|
+
await atomicWriteSecure(join17(dir, "USER_REQUEST.md"), `# User request
|
|
6865
7004
|
|
|
6866
7005
|
${userInput.trim() || "(empty)"}
|
|
6867
7006
|
`);
|
|
@@ -6887,7 +7026,7 @@ ${userInput.trim() || "(empty)"}
|
|
|
6887
7026
|
"- Waiting for assignment.",
|
|
6888
7027
|
""
|
|
6889
7028
|
].join("\n");
|
|
6890
|
-
await atomicWriteSecure(
|
|
7029
|
+
await atomicWriteSecure(join17(dir, fileName), content);
|
|
6891
7030
|
}
|
|
6892
7031
|
}
|
|
6893
7032
|
async deleteRunDir(conversationId) {
|
|
@@ -6947,7 +7086,7 @@ ${userInput.trim() || "(empty)"}
|
|
|
6947
7086
|
if (!runState) return;
|
|
6948
7087
|
try {
|
|
6949
7088
|
const dir = this.getRunDir(conversationId);
|
|
6950
|
-
await
|
|
7089
|
+
await mkdir14(dir, { recursive: true });
|
|
6951
7090
|
const data = {
|
|
6952
7091
|
nodeStates: { ...runState.nodeStates },
|
|
6953
7092
|
nodeOutputs: { ...runState.nodeOutputs },
|
|
@@ -6955,18 +7094,18 @@ ${userInput.trim() || "(empty)"}
|
|
|
6955
7094
|
...Object.keys(runState.nodeAgentIds).length > 0 ? { nodeAgentIds: { ...runState.nodeAgentIds } } : {},
|
|
6956
7095
|
...Object.keys(runState.waitingInputs).length > 0 ? { waitingInputs: { ...runState.waitingInputs } } : {}
|
|
6957
7096
|
};
|
|
6958
|
-
await atomicWriteJsonSecure(
|
|
7097
|
+
await atomicWriteJsonSecure(join17(dir, "run-state.json"), data);
|
|
6959
7098
|
} catch {
|
|
6960
7099
|
}
|
|
6961
7100
|
}
|
|
6962
7101
|
async loadPersistedRunState(conversationId) {
|
|
6963
7102
|
const dir = this.getRunDir(conversationId);
|
|
6964
|
-
return readJsonFileSafe(
|
|
7103
|
+
return readJsonFileSafe(join17(dir, "run-state.json"));
|
|
6965
7104
|
}
|
|
6966
7105
|
async readUserRequest(conversationId) {
|
|
6967
7106
|
try {
|
|
6968
7107
|
const dir = this.getRunDir(conversationId);
|
|
6969
|
-
const content = await
|
|
7108
|
+
const content = await readFile14(join17(dir, "USER_REQUEST.md"), "utf-8");
|
|
6970
7109
|
return content.replace(/^#\s*User request\s*\n+/, "").trim() || null;
|
|
6971
7110
|
} catch {
|
|
6972
7111
|
return null;
|
|
@@ -6975,23 +7114,23 @@ ${userInput.trim() || "(empty)"}
|
|
|
6975
7114
|
async readReadme(conversationId) {
|
|
6976
7115
|
try {
|
|
6977
7116
|
const dir = this.getRunDir(conversationId);
|
|
6978
|
-
return await
|
|
7117
|
+
return await readFile14(join17(dir, "README.md"), "utf-8");
|
|
6979
7118
|
} catch {
|
|
6980
7119
|
return null;
|
|
6981
7120
|
}
|
|
6982
7121
|
}
|
|
6983
7122
|
async saveScenarioSnapshot(conversationId, scenario) {
|
|
6984
7123
|
const dir = this.getRunDir(conversationId);
|
|
6985
|
-
await
|
|
7124
|
+
await mkdir14(dir, { recursive: true });
|
|
6986
7125
|
await atomicWriteJsonSecure(
|
|
6987
|
-
|
|
7126
|
+
join17(dir, _ScenarioRunStore.SCENARIO_SNAPSHOT_FILE),
|
|
6988
7127
|
scenario,
|
|
6989
7128
|
true
|
|
6990
7129
|
);
|
|
6991
7130
|
}
|
|
6992
7131
|
async loadScenarioSnapshot(conversationId) {
|
|
6993
7132
|
const dir = this.getRunDir(conversationId);
|
|
6994
|
-
return readJsonFileSafe(
|
|
7133
|
+
return readJsonFileSafe(join17(dir, _ScenarioRunStore.SCENARIO_SNAPSHOT_FILE));
|
|
6995
7134
|
}
|
|
6996
7135
|
};
|
|
6997
7136
|
var scenarioRunStore = new ScenarioRunStore();
|
|
@@ -7037,9 +7176,9 @@ async function fetchProviderModels(provider, plaintextKey) {
|
|
|
7037
7176
|
|
|
7038
7177
|
// ../server/src/services/image-storage.service.ts
|
|
7039
7178
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
7040
|
-
import { mkdir as
|
|
7179
|
+
import { mkdir as mkdir15, writeFile as writeFile14, readFile as readFile15, unlink as unlink3, readdir as readdir4 } from "fs/promises";
|
|
7041
7180
|
import { existsSync as existsSync2 } from "fs";
|
|
7042
|
-
import { join as
|
|
7181
|
+
import { join as join18, extname, resolve as resolve4, sep as sep2 } from "path";
|
|
7043
7182
|
var ALLOWED_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
7044
7183
|
"image/png",
|
|
7045
7184
|
"image/jpeg",
|
|
@@ -7056,7 +7195,7 @@ var ImageStorageService = class {
|
|
|
7056
7195
|
this.dir = dir;
|
|
7057
7196
|
}
|
|
7058
7197
|
async ensureTmpDir() {
|
|
7059
|
-
await
|
|
7198
|
+
await mkdir15(this.dir, { recursive: true, mode: 448 });
|
|
7060
7199
|
}
|
|
7061
7200
|
async saveImage(buffer, originalName, mimeType, contextId) {
|
|
7062
7201
|
if (!ALLOWED_MIME_TYPES.has(mimeType)) {
|
|
@@ -7076,15 +7215,15 @@ var ImageStorageService = class {
|
|
|
7076
7215
|
const imageId = randomUUID4();
|
|
7077
7216
|
const safeExt = ext.replace(/[^a-z.]/g, "");
|
|
7078
7217
|
const fileName = `${imageId}${safeExt}`;
|
|
7079
|
-
const filePath =
|
|
7218
|
+
const filePath = join18(this.dir, fileName);
|
|
7080
7219
|
const resolvedPath = resolve4(filePath);
|
|
7081
7220
|
const resolvedDir = resolve4(this.dir);
|
|
7082
7221
|
if (resolvedPath !== resolvedDir && !resolvedPath.startsWith(resolvedDir + sep2)) {
|
|
7083
7222
|
throw new Error("Invalid file path");
|
|
7084
7223
|
}
|
|
7085
|
-
await
|
|
7224
|
+
await writeFile14(filePath, buffer, { mode: 384 });
|
|
7086
7225
|
const meta = { imageId, filePath, mimeType, originalName, createdAt: Date.now(), contextId };
|
|
7087
|
-
await
|
|
7226
|
+
await writeFile14(`${filePath}.meta.json`, JSON.stringify(meta), { encoding: "utf-8", mode: 384 });
|
|
7088
7227
|
return meta;
|
|
7089
7228
|
}
|
|
7090
7229
|
/**
|
|
@@ -7102,7 +7241,7 @@ var ImageStorageService = class {
|
|
|
7102
7241
|
const files = await readdir4(this.dir);
|
|
7103
7242
|
const metaFile = files.find((f) => f.startsWith(imageId) && f.endsWith(".meta.json"));
|
|
7104
7243
|
if (!metaFile) return null;
|
|
7105
|
-
const raw = JSON.parse(await
|
|
7244
|
+
const raw = JSON.parse(await readFile15(join18(this.dir, metaFile), "utf-8"));
|
|
7106
7245
|
if (expectedContextId !== void 0 && raw.contextId !== expectedContextId) return null;
|
|
7107
7246
|
if (!existsSync2(raw.filePath)) return null;
|
|
7108
7247
|
return { filePath: raw.filePath, mimeType: raw.mimeType, contextId: raw.contextId };
|
|
@@ -7128,7 +7267,7 @@ var ImageStorageService = class {
|
|
|
7128
7267
|
await Promise.all(
|
|
7129
7268
|
files.filter((f) => f.endsWith(".meta.json")).map(async (file) => {
|
|
7130
7269
|
try {
|
|
7131
|
-
const raw = JSON.parse(await
|
|
7270
|
+
const raw = JSON.parse(await readFile15(join18(this.dir, file), "utf-8"));
|
|
7132
7271
|
if (raw.contextId === contextId) {
|
|
7133
7272
|
await unlink3(raw.filePath).catch(() => {
|
|
7134
7273
|
});
|
|
@@ -7143,7 +7282,7 @@ var ImageStorageService = class {
|
|
|
7143
7282
|
async readImageAsBase64(imageId, expectedContextId) {
|
|
7144
7283
|
const result = await this.getImagePath(imageId, expectedContextId);
|
|
7145
7284
|
if (!result) return null;
|
|
7146
|
-
const buffer = await
|
|
7285
|
+
const buffer = await readFile15(result.filePath);
|
|
7147
7286
|
return { base64: buffer.toString("base64"), mimeType: result.mimeType };
|
|
7148
7287
|
}
|
|
7149
7288
|
async listExpiredImages(ttlMs = IMAGE_TTL_MS) {
|
|
@@ -7158,7 +7297,7 @@ var ImageStorageService = class {
|
|
|
7158
7297
|
for (const file of files) {
|
|
7159
7298
|
if (!file.endsWith(".meta.json")) continue;
|
|
7160
7299
|
try {
|
|
7161
|
-
const raw = JSON.parse(await
|
|
7300
|
+
const raw = JSON.parse(await readFile15(join18(this.dir, file), "utf-8"));
|
|
7162
7301
|
if (now - raw.createdAt > ttlMs) expired.push(raw);
|
|
7163
7302
|
} catch {
|
|
7164
7303
|
}
|
|
@@ -7220,11 +7359,8 @@ async function resolveImagesToBase64(images, contextId) {
|
|
|
7220
7359
|
return results.filter((r) => r !== null);
|
|
7221
7360
|
}
|
|
7222
7361
|
|
|
7223
|
-
// ../server/src/services/kanban-commands.ts
|
|
7224
|
-
import { randomUUID as randomUUID5 } from "crypto";
|
|
7225
|
-
|
|
7226
7362
|
// ../server/src/trpc/routers/cloud-auth.ts
|
|
7227
|
-
import { z as
|
|
7363
|
+
import { z as z16 } from "zod";
|
|
7228
7364
|
import { hostname } from "os";
|
|
7229
7365
|
import { basename } from "path";
|
|
7230
7366
|
import { TRPCError as TRPCError11 } from "@trpc/server";
|
|
@@ -7259,7 +7395,7 @@ function isAllowedProxyPath(path) {
|
|
|
7259
7395
|
}
|
|
7260
7396
|
var cloudAuthRouter = router({
|
|
7261
7397
|
/** Build the cloud authorization URL to open in the browser. */
|
|
7262
|
-
startLogin: protectedProcedure.input(
|
|
7398
|
+
startLogin: protectedProcedure.input(z16.object({ returnTo: z16.string().url().max(2048) })).mutation(async ({ input }) => {
|
|
7263
7399
|
if (!isLocalOrigin(input.returnTo)) {
|
|
7264
7400
|
throw new TRPCError11({ code: "BAD_REQUEST", message: "returnTo must be a local origin." });
|
|
7265
7401
|
}
|
|
@@ -7304,7 +7440,7 @@ var cloudAuthRouter = router({
|
|
|
7304
7440
|
* drops the session, and the local token is dropped here too, so nothing is
|
|
7305
7441
|
* left holding a dead credential.
|
|
7306
7442
|
*/
|
|
7307
|
-
revokeDevice: protectedProcedure.input(
|
|
7443
|
+
revokeDevice: protectedProcedure.input(z16.object({ id: z16.string().min(1).max(128) })).mutation(async ({ input }) => {
|
|
7308
7444
|
const res = await cloudFetch2("/api/auth/device/revoke", { method: "POST", body: { id: input.id } });
|
|
7309
7445
|
if (!res.ok) {
|
|
7310
7446
|
if (res.status === 401) await cloudSessionStore.clear();
|
|
@@ -7321,11 +7457,11 @@ var cloudAuthRouter = router({
|
|
|
7321
7457
|
* the cloud: the web UI asks its own server, which holds the credential.
|
|
7322
7458
|
*/
|
|
7323
7459
|
proxy: protectedProcedure.input(
|
|
7324
|
-
|
|
7325
|
-
path:
|
|
7326
|
-
method:
|
|
7327
|
-
query:
|
|
7328
|
-
body:
|
|
7460
|
+
z16.object({
|
|
7461
|
+
path: z16.string().min(1).max(512),
|
|
7462
|
+
method: z16.enum(["GET", "POST"]).default("GET"),
|
|
7463
|
+
query: z16.record(z16.string().max(128), z16.string().max(2048)).optional(),
|
|
7464
|
+
body: z16.unknown().optional()
|
|
7329
7465
|
})
|
|
7330
7466
|
).mutation(async ({ input }) => {
|
|
7331
7467
|
if (!isAllowedProxyPath(input.path)) {
|
|
@@ -7470,6 +7606,20 @@ var KanbanStore = class {
|
|
|
7470
7606
|
});
|
|
7471
7607
|
return res.ok;
|
|
7472
7608
|
}
|
|
7609
|
+
/**
|
|
7610
|
+
* Ajouter une carte, sans réécrire le tableau.
|
|
7611
|
+
*
|
|
7612
|
+
* La colonne se nomme par son titre : c'est ce que connaît une IA qui lit un
|
|
7613
|
+
* tableau, et le cloud le résout. Deux ajouts qui se croisent se rangent tous
|
|
7614
|
+
* les deux, ce qu'une sauvegarde de tableau entier ne garantissait pas.
|
|
7615
|
+
*/
|
|
7616
|
+
async addCard(boardId, input) {
|
|
7617
|
+
const res = await callCloud("/kanban/card/add", {
|
|
7618
|
+
method: "POST",
|
|
7619
|
+
body: { boardId, ...input }
|
|
7620
|
+
});
|
|
7621
|
+
return res.data?.card ?? null;
|
|
7622
|
+
}
|
|
7473
7623
|
/** Déplacer une carte, sans réécrire le tableau. */
|
|
7474
7624
|
async moveCard(boardId, cardId, toColumnId) {
|
|
7475
7625
|
const res = await callCloud("/kanban/card/move", {
|
|
@@ -7562,7 +7712,6 @@ async function executeKanbanCommands(boardId, cardId, commands, conversationId)
|
|
|
7562
7712
|
return;
|
|
7563
7713
|
}
|
|
7564
7714
|
}
|
|
7565
|
-
let pendingBoardWrite = false;
|
|
7566
7715
|
for (const cmd of commands) {
|
|
7567
7716
|
if (cmd.type === "move_card" && cmd.columnTitle) {
|
|
7568
7717
|
const target = board.columns.find(
|
|
@@ -7578,11 +7727,14 @@ async function executeKanbanCommands(boardId, cardId, commands, conversationId)
|
|
|
7578
7727
|
const ok = await kanbanStore.addComment(board.id, cardId, cmd.comment, conversationId);
|
|
7579
7728
|
if (!ok) console.warn(`[kanban-commands] add_comment failed: card=${cardId}`);
|
|
7580
7729
|
} else if (cmd.type === "add_card" && cmd.columnTitle && cmd.cardTitle) {
|
|
7581
|
-
|
|
7582
|
-
|
|
7730
|
+
const card = await kanbanStore.addCard(board.id, {
|
|
7731
|
+
column: cmd.columnTitle,
|
|
7732
|
+
title: cmd.cardTitle,
|
|
7733
|
+
markdown: cmd.cardContent
|
|
7734
|
+
});
|
|
7735
|
+
if (!card) console.warn(`[kanban-commands] add_card failed: column="${cmd.columnTitle}"`);
|
|
7583
7736
|
}
|
|
7584
7737
|
}
|
|
7585
|
-
if (pendingBoardWrite) await kanbanStore.update({ id: board.id, columns: board.columns });
|
|
7586
7738
|
}
|
|
7587
7739
|
async function executeKanbanBoardCommands(boardId, commands) {
|
|
7588
7740
|
if (commands.length === 0) return;
|
|
@@ -7590,30 +7742,14 @@ async function executeKanbanBoardCommands(boardId, commands) {
|
|
|
7590
7742
|
if (!board) return;
|
|
7591
7743
|
for (const cmd of commands) {
|
|
7592
7744
|
if (cmd.type === "add_card" && cmd.columnTitle && cmd.cardTitle) {
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
7597
|
-
}
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
7602
|
-
const card = {
|
|
7603
|
-
id: randomUUID5(),
|
|
7604
|
-
title: cardTitle,
|
|
7605
|
-
markdown: cardContent ?? "",
|
|
7606
|
-
images: [],
|
|
7607
|
-
// `.default([])` on the schema makes these optional on the wire but required
|
|
7608
|
-
// on the inferred type — a card built by hand has to supply them.
|
|
7609
|
-
attachments: [],
|
|
7610
|
-
assignees: [],
|
|
7611
|
-
order: col.cards.length,
|
|
7612
|
-
history: [{ type: "created", timestamp: now, detail: `AI \u2014 In column "${col.title}"` }],
|
|
7613
|
-
createdAt: now,
|
|
7614
|
-
updatedAt: now
|
|
7615
|
-
};
|
|
7616
|
-
col.cards.push(card);
|
|
7745
|
+
const card = await kanbanStore.addCard(board.id, {
|
|
7746
|
+
column: cmd.columnTitle,
|
|
7747
|
+
title: cmd.cardTitle,
|
|
7748
|
+
markdown: cmd.cardContent
|
|
7749
|
+
});
|
|
7750
|
+
if (!card) console.warn(`[kanban-commands] add_card failed: column="${cmd.columnTitle}"`);
|
|
7751
|
+
}
|
|
7752
|
+
}
|
|
7617
7753
|
}
|
|
7618
7754
|
function formatSize(bytes) {
|
|
7619
7755
|
if (bytes < 1024) return `${bytes} o`;
|
|
@@ -7839,7 +7975,7 @@ Ne jamais omettre ce tag. Il doit \xEAtre la toute derni\xE8re ligne de ta r\xE9
|
|
|
7839
7975
|
`.trim();
|
|
7840
7976
|
|
|
7841
7977
|
// ../server/src/services/ai-runners/claude-pty-runner.ts
|
|
7842
|
-
import { randomUUID as
|
|
7978
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
7843
7979
|
|
|
7844
7980
|
// ../server/src/services/ai-runners/claude-pty-tail.ts
|
|
7845
7981
|
import { open } from "fs/promises";
|
|
@@ -7963,7 +8099,7 @@ function tailTranscript(opts) {
|
|
|
7963
8099
|
|
|
7964
8100
|
// ../server/src/services/ai-runners/claude-pty-runner.ts
|
|
7965
8101
|
async function getAgentManager() {
|
|
7966
|
-
const { agentManager: agentManager2 } = await import("./agent-manager-
|
|
8102
|
+
const { agentManager: agentManager2 } = await import("./agent-manager-YDLSYZE3.js");
|
|
7967
8103
|
return agentManager2;
|
|
7968
8104
|
}
|
|
7969
8105
|
function buildPtyArgs(params, sessionId, opts) {
|
|
@@ -8033,7 +8169,7 @@ function dispatchEntry(entry, state, cbs) {
|
|
|
8033
8169
|
async function runClaudeViaPty(params) {
|
|
8034
8170
|
const { agentId, signal, skipTokenInstructions } = params;
|
|
8035
8171
|
if (!agentId) throw new Error("runClaudeViaPty requires an agentId");
|
|
8036
|
-
const sessionId = params.sessionId && params.sessionId.length > 0 ? params.sessionId :
|
|
8172
|
+
const sessionId = params.sessionId && params.sessionId.length > 0 ? params.sessionId : randomUUID5();
|
|
8037
8173
|
const args = buildPtyArgs(params, sessionId, { excludeMcp: true });
|
|
8038
8174
|
const agentMgr = await getAgentManager();
|
|
8039
8175
|
const displayArgs = args.map((a) => {
|
|
@@ -8704,7 +8840,7 @@ async function shutdownCodexAppServer() {
|
|
|
8704
8840
|
}
|
|
8705
8841
|
}
|
|
8706
8842
|
async function getAgentManager2() {
|
|
8707
|
-
const { agentManager: agentManager2 } = await import("./agent-manager-
|
|
8843
|
+
const { agentManager: agentManager2 } = await import("./agent-manager-YDLSYZE3.js");
|
|
8708
8844
|
return agentManager2;
|
|
8709
8845
|
}
|
|
8710
8846
|
function parseRuneyaCurlCommand(command) {
|
|
@@ -9145,18 +9281,18 @@ ${prompt}`;
|
|
|
9145
9281
|
|
|
9146
9282
|
// ../server/src/trpc/routers/chat.ts
|
|
9147
9283
|
var execFileAsync3 = promisify3(execFile4);
|
|
9148
|
-
var MessageSchema =
|
|
9149
|
-
role:
|
|
9150
|
-
content:
|
|
9284
|
+
var MessageSchema = z17.object({
|
|
9285
|
+
role: z17.enum(["user", "assistant"]),
|
|
9286
|
+
content: z17.string().max(1e5)
|
|
9151
9287
|
});
|
|
9152
|
-
var ImagePartSchema =
|
|
9153
|
-
type:
|
|
9154
|
-
imageId:
|
|
9155
|
-
url:
|
|
9156
|
-
mimeType:
|
|
9157
|
-
altText:
|
|
9288
|
+
var ImagePartSchema = z17.object({
|
|
9289
|
+
type: z17.literal("image"),
|
|
9290
|
+
imageId: z17.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),
|
|
9291
|
+
url: z17.string().max(500),
|
|
9292
|
+
mimeType: z17.string().max(100),
|
|
9293
|
+
altText: z17.string().max(500).optional()
|
|
9158
9294
|
});
|
|
9159
|
-
var ImagePartsSchema =
|
|
9295
|
+
var ImagePartsSchema = z17.array(ImagePartSchema).max(5).optional();
|
|
9160
9296
|
var LANGUAGE_INSTRUCTION = "Always respond in the same language the user writes in.";
|
|
9161
9297
|
async function buildSystemPrompt(apiKey) {
|
|
9162
9298
|
const allServices = await serviceStore.list();
|
|
@@ -9543,24 +9679,24 @@ async function startCodexSession(convId, prompt, opts = {}) {
|
|
|
9543
9679
|
});
|
|
9544
9680
|
return { session, done };
|
|
9545
9681
|
}
|
|
9546
|
-
var MessagePartSchema =
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
|
|
9550
|
-
type:
|
|
9682
|
+
var MessagePartSchema = z17.discriminatedUnion("type", [
|
|
9683
|
+
z17.object({ type: z17.literal("thinking"), text: z17.string().max(1e5) }),
|
|
9684
|
+
z17.object({ type: z17.literal("text"), text: z17.string().max(1e5) }),
|
|
9685
|
+
z17.object({
|
|
9686
|
+
type: z17.literal("tool"),
|
|
9551
9687
|
id: Id128Schema,
|
|
9552
9688
|
name: Id128Schema,
|
|
9553
|
-
input:
|
|
9554
|
-
rawInput:
|
|
9555
|
-
result:
|
|
9556
|
-
isError:
|
|
9557
|
-
pending:
|
|
9689
|
+
input: z17.record(z17.string(), z17.unknown()).optional(),
|
|
9690
|
+
rawInput: z17.string().max(1e4).optional(),
|
|
9691
|
+
result: z17.unknown().optional(),
|
|
9692
|
+
isError: z17.boolean().optional(),
|
|
9693
|
+
pending: z17.boolean()
|
|
9558
9694
|
})
|
|
9559
9695
|
]);
|
|
9560
|
-
var StoredMessageSchema =
|
|
9561
|
-
role:
|
|
9562
|
-
content:
|
|
9563
|
-
parts:
|
|
9696
|
+
var StoredMessageSchema = z17.object({
|
|
9697
|
+
role: z17.enum(["user", "assistant"]),
|
|
9698
|
+
content: z17.string().max(1e5),
|
|
9699
|
+
parts: z17.array(MessagePartSchema).max(200).optional()
|
|
9564
9700
|
});
|
|
9565
9701
|
async function conversationCwd(conv) {
|
|
9566
9702
|
return resolveConversationCwd(conv.id);
|
|
@@ -9574,7 +9710,7 @@ var chatRouter = router({
|
|
|
9574
9710
|
* et sans le même filtre il y reversait toutes les conversations de la
|
|
9575
9711
|
* machine, une seconde après un chargement pourtant filtré.
|
|
9576
9712
|
*/
|
|
9577
|
-
onChanged: protectedProcedure.input(
|
|
9713
|
+
onChanged: protectedProcedure.input(z17.object({
|
|
9578
9714
|
projectId: Id128Schema.optional(),
|
|
9579
9715
|
orgId: Id128Schema.nullable().optional()
|
|
9580
9716
|
}).optional()).subscription(async function* ({ input }) {
|
|
@@ -9622,7 +9758,7 @@ var chatRouter = router({
|
|
|
9622
9758
|
* reachable where they were written, without leaking into every other
|
|
9623
9759
|
* organization's projects.
|
|
9624
9760
|
*/
|
|
9625
|
-
list: protectedProcedure.input(
|
|
9761
|
+
list: protectedProcedure.input(z17.object({
|
|
9626
9762
|
projectId: Id128Schema.optional(),
|
|
9627
9763
|
orgId: Id128Schema.nullable().optional()
|
|
9628
9764
|
}).optional()).query(async ({ input }) => {
|
|
@@ -9630,24 +9766,24 @@ var chatRouter = router({
|
|
|
9630
9766
|
if (!projectId) return conversationStore.list();
|
|
9631
9767
|
return conversationStore.listForProject({ id: projectId, orgId: input?.orgId });
|
|
9632
9768
|
}),
|
|
9633
|
-
get: protectedProcedure.input(
|
|
9769
|
+
get: protectedProcedure.input(z17.object({ id: Id128Schema })).query(async ({ input }) => {
|
|
9634
9770
|
const conv = await conversationStore.get(input.id);
|
|
9635
9771
|
if (!conv) throw new TRPCError12({ code: "NOT_FOUND", message: "Conversation not found" });
|
|
9636
9772
|
return conv;
|
|
9637
9773
|
}),
|
|
9638
|
-
create: protectedProcedure.input(
|
|
9774
|
+
create: protectedProcedure.input(z17.object({
|
|
9639
9775
|
title: ShortString200Schema.optional(),
|
|
9640
|
-
isCli:
|
|
9641
|
-
runner:
|
|
9776
|
+
isCli: z17.boolean().optional(),
|
|
9777
|
+
runner: z17.enum(["claude-code", "codex"]).optional(),
|
|
9642
9778
|
providerId: Id128Schema.optional(),
|
|
9643
9779
|
scenarioId: Id128Schema.optional(),
|
|
9644
|
-
scenarioInput:
|
|
9780
|
+
scenarioInput: z17.string().max(1e5).optional(),
|
|
9645
9781
|
kanbanBoardId: Id128Schema.optional(),
|
|
9646
9782
|
kanbanCardId: Id128Schema.optional(),
|
|
9647
9783
|
// The project the conversation is about: only the caller knows which
|
|
9648
9784
|
// one it is looking at.
|
|
9649
9785
|
projectId: Id128Schema.optional(),
|
|
9650
|
-
orgId:
|
|
9786
|
+
orgId: z17.string().max(128).nullable().optional()
|
|
9651
9787
|
})).mutation(async ({ input }) => {
|
|
9652
9788
|
let scenario = null;
|
|
9653
9789
|
if (input.scenarioId) {
|
|
@@ -9678,20 +9814,20 @@ var chatRouter = router({
|
|
|
9678
9814
|
}
|
|
9679
9815
|
return conv;
|
|
9680
9816
|
}),
|
|
9681
|
-
update: protectedProcedure.input(
|
|
9817
|
+
update: protectedProcedure.input(z17.object({
|
|
9682
9818
|
id: Id128Schema,
|
|
9683
9819
|
title: ShortString200Schema.optional(),
|
|
9684
|
-
messages:
|
|
9685
|
-
contextUsage:
|
|
9686
|
-
inputTokens:
|
|
9687
|
-
contextWindow:
|
|
9820
|
+
messages: z17.array(StoredMessageSchema).max(500).optional(),
|
|
9821
|
+
contextUsage: z17.object({
|
|
9822
|
+
inputTokens: z17.number().int().nonnegative(),
|
|
9823
|
+
contextWindow: z17.number().int().positive()
|
|
9688
9824
|
}).optional()
|
|
9689
9825
|
})).mutation(async ({ input }) => {
|
|
9690
9826
|
const conv = await conversationStore.update(input.id, { title: input.title, messages: input.messages, contextUsage: input.contextUsage });
|
|
9691
9827
|
if (!conv) throw new TRPCError12({ code: "NOT_FOUND", message: "Conversation not found" });
|
|
9692
9828
|
return conv;
|
|
9693
9829
|
}),
|
|
9694
|
-
delete: protectedProcedure.input(
|
|
9830
|
+
delete: protectedProcedure.input(z17.object({ id: Id128Schema })).mutation(async ({ input }) => {
|
|
9695
9831
|
const existing = await conversationStore.get(input.id);
|
|
9696
9832
|
if (!existing) throw new TRPCError12({ code: "NOT_FOUND", message: "Conversation not found" });
|
|
9697
9833
|
for (const agent of agentManager.listAgents()) {
|
|
@@ -9713,18 +9849,18 @@ var chatRouter = router({
|
|
|
9713
9849
|
(err) => console.error("[chat.delete] Image cleanup error:", err)
|
|
9714
9850
|
);
|
|
9715
9851
|
}),
|
|
9716
|
-
archive: protectedProcedure.input(
|
|
9852
|
+
archive: protectedProcedure.input(z17.object({ id: Id128Schema, archived: z17.boolean() })).mutation(async ({ input }) => {
|
|
9717
9853
|
const conv = await conversationStore.update(input.id, { archived: input.archived });
|
|
9718
9854
|
if (!conv) throw new TRPCError12({ code: "NOT_FOUND", message: "Conversation not found" });
|
|
9719
9855
|
return conv;
|
|
9720
9856
|
})
|
|
9721
9857
|
}),
|
|
9722
|
-
listModels: protectedProcedure.input(
|
|
9858
|
+
listModels: protectedProcedure.input(z17.object({
|
|
9723
9859
|
providerId: Id128Schema.optional(),
|
|
9724
9860
|
// Le projet dit de quelle organisation lire les fournisseurs ; absent,
|
|
9725
9861
|
// ce sont ceux du poste.
|
|
9726
9862
|
projectId: Id128Schema.optional(),
|
|
9727
|
-
orgId:
|
|
9863
|
+
orgId: z17.string().max(128).nullable().optional()
|
|
9728
9864
|
}).optional()).query(async ({ input }) => {
|
|
9729
9865
|
const active = await getActiveProvider(
|
|
9730
9866
|
input?.providerId,
|
|
@@ -9737,7 +9873,7 @@ var chatRouter = router({
|
|
|
9737
9873
|
return [];
|
|
9738
9874
|
}
|
|
9739
9875
|
}),
|
|
9740
|
-
checkCliAvailability: protectedProcedure.input(
|
|
9876
|
+
checkCliAvailability: protectedProcedure.input(z17.object({ agentId: Id128Schema.optional() }).optional()).query(async ({ input }) => {
|
|
9741
9877
|
if (input?.agentId) {
|
|
9742
9878
|
try {
|
|
9743
9879
|
const res = await agentManager.agentQuery(
|
|
@@ -9755,12 +9891,12 @@ var chatRouter = router({
|
|
|
9755
9891
|
]);
|
|
9756
9892
|
return { available: claudeOk, codexAvailable: codexOk };
|
|
9757
9893
|
}),
|
|
9758
|
-
enhanceScenarioPrompt: protectedProcedure.input(
|
|
9759
|
-
text:
|
|
9894
|
+
enhanceScenarioPrompt: protectedProcedure.input(z17.object({
|
|
9895
|
+
text: z17.string().max(1e4),
|
|
9760
9896
|
providerId: Id128Schema.optional(),
|
|
9761
|
-
model:
|
|
9897
|
+
model: z17.string().max(200).optional(),
|
|
9762
9898
|
projectId: Id128Schema.optional(),
|
|
9763
|
-
orgId:
|
|
9899
|
+
orgId: z17.string().max(128).nullable().optional()
|
|
9764
9900
|
})).mutation(async ({ input }) => {
|
|
9765
9901
|
const active = await getActiveProvider(
|
|
9766
9902
|
input.providerId,
|
|
@@ -9817,22 +9953,22 @@ Return ONLY the improved text, no explanation, no preamble.`;
|
|
|
9817
9953
|
}
|
|
9818
9954
|
}),
|
|
9819
9955
|
getStreamingStatus: protectedProcedure.query(() => activeSessionRegistry.listActive()),
|
|
9820
|
-
stopSession: protectedProcedure.input(
|
|
9956
|
+
stopSession: protectedProcedure.input(z17.object({ conversationId: ConversationIdSchema })).mutation(({ input }) => {
|
|
9821
9957
|
if (process.env.RUNEYA_DEBUG) console.log("[chat]: stopSession");
|
|
9822
9958
|
const killed = activeSessionRegistry.kill(input.conversationId);
|
|
9823
9959
|
if (!killed) throw new TRPCError12({ code: "NOT_FOUND", message: "No active session for this conversation" });
|
|
9824
9960
|
return { ok: true };
|
|
9825
9961
|
}),
|
|
9826
|
-
streamViaClaudeCode: protectedProcedure.input(
|
|
9962
|
+
streamViaClaudeCode: protectedProcedure.input(z17.object({
|
|
9827
9963
|
conversationId: ConversationIdSchema,
|
|
9828
|
-
prompt:
|
|
9829
|
-
contextNote:
|
|
9964
|
+
prompt: z17.string().max(1e5),
|
|
9965
|
+
contextNote: z17.string().max(2e5).optional(),
|
|
9830
9966
|
model: ShortString200Schema.optional(),
|
|
9831
|
-
effort:
|
|
9832
|
-
reconnect:
|
|
9967
|
+
effort: z17.enum(["low", "medium", "high"]).optional(),
|
|
9968
|
+
reconnect: z17.boolean().optional(),
|
|
9833
9969
|
agentId: Id128Schema.optional(),
|
|
9834
|
-
environmentId:
|
|
9835
|
-
imageIds:
|
|
9970
|
+
environmentId: z17.string().max(128).optional(),
|
|
9971
|
+
imageIds: z17.array(z17.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)).max(5).optional(),
|
|
9836
9972
|
imageParts: ImagePartsSchema
|
|
9837
9973
|
})).subscription(async function* ({ input, ctx, signal }) {
|
|
9838
9974
|
if (process.env.RUNEYA_DEBUG) console.log("[chat]: Reconnect");
|
|
@@ -9943,15 +10079,15 @@ ${imagePaths.map((p) => `Image: ${p}`).join("\n")}` : cliPrompt;
|
|
|
9943
10079
|
if (process.env.RUNEYA_DEBUG) console.log("[chat]: drainSession...");
|
|
9944
10080
|
yield* drainSession(session, signal, false);
|
|
9945
10081
|
}),
|
|
9946
|
-
streamViaCodex: protectedProcedure.input(
|
|
10082
|
+
streamViaCodex: protectedProcedure.input(z17.object({
|
|
9947
10083
|
conversationId: ConversationIdSchema,
|
|
9948
|
-
prompt:
|
|
9949
|
-
contextNote:
|
|
10084
|
+
prompt: z17.string().max(1e5),
|
|
10085
|
+
contextNote: z17.string().max(2e5).optional(),
|
|
9950
10086
|
model: ShortString200Schema.optional(),
|
|
9951
|
-
reconnect:
|
|
10087
|
+
reconnect: z17.boolean().optional(),
|
|
9952
10088
|
agentId: Id128Schema.optional(),
|
|
9953
|
-
environmentId:
|
|
9954
|
-
imageIds:
|
|
10089
|
+
environmentId: z17.string().max(128).optional(),
|
|
10090
|
+
imageIds: z17.array(z17.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)).max(5).optional(),
|
|
9955
10091
|
imageParts: ImagePartsSchema
|
|
9956
10092
|
})).subscription(async function* ({ input, ctx, signal }) {
|
|
9957
10093
|
const existingSession = activeSessionRegistry.get(input.conversationId);
|
|
@@ -10029,13 +10165,13 @@ ${input.prompt}` : input.prompt;
|
|
|
10029
10165
|
});
|
|
10030
10166
|
yield* drainSession(session, signal, false);
|
|
10031
10167
|
}),
|
|
10032
|
-
send: protectedProcedure.input(
|
|
10168
|
+
send: protectedProcedure.input(z17.object({
|
|
10033
10169
|
conversationId: ConversationIdSchema,
|
|
10034
|
-
messages:
|
|
10170
|
+
messages: z17.array(MessageSchema).min(0).max(100),
|
|
10035
10171
|
model: ShortString200Schema.optional(),
|
|
10036
|
-
contextNote:
|
|
10037
|
-
reconnect:
|
|
10038
|
-
imageIds:
|
|
10172
|
+
contextNote: z17.string().max(2e5).optional(),
|
|
10173
|
+
reconnect: z17.boolean().optional(),
|
|
10174
|
+
imageIds: z17.array(z17.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)).max(5).optional(),
|
|
10039
10175
|
imageParts: ImagePartsSchema
|
|
10040
10176
|
})).subscription(async function* ({ input, ctx, signal }) {
|
|
10041
10177
|
const existingSession = activeSessionRegistry.get(input.conversationId);
|
|
@@ -10153,25 +10289,25 @@ ${input.prompt}` : input.prompt;
|
|
|
10153
10289
|
// ── PTY passthrough (interactive Claude Code session) ────────────────────
|
|
10154
10290
|
pty: router({
|
|
10155
10291
|
/** Start a PTY session running `claude --resume <sessionId>` (or fresh). */
|
|
10156
|
-
start: protectedProcedure.input(
|
|
10157
|
-
agentId:
|
|
10158
|
-
sessionId:
|
|
10159
|
-
runner:
|
|
10160
|
-
resume:
|
|
10161
|
-
model:
|
|
10162
|
-
cwd:
|
|
10292
|
+
start: protectedProcedure.input(z17.object({
|
|
10293
|
+
agentId: z17.string().max(128).optional(),
|
|
10294
|
+
sessionId: z17.string().max(128).optional(),
|
|
10295
|
+
runner: z17.enum(["claude-code", "codex"]).default("claude-code"),
|
|
10296
|
+
resume: z17.boolean().default(false),
|
|
10297
|
+
model: z17.string().max(128).optional(),
|
|
10298
|
+
cwd: z17.string().max(4096).optional(),
|
|
10163
10299
|
/** Anchors the session when no explicit cwd is given. */
|
|
10164
|
-
serviceId:
|
|
10300
|
+
serviceId: z17.string().max(128).optional(),
|
|
10165
10301
|
projectId: Id128Schema.optional(),
|
|
10166
|
-
orgId:
|
|
10167
|
-
cols:
|
|
10168
|
-
rows:
|
|
10169
|
-
enableMcp:
|
|
10170
|
-
apiBaseUrl:
|
|
10171
|
-
environmentId:
|
|
10172
|
-
attachedContexts:
|
|
10173
|
-
label:
|
|
10174
|
-
text:
|
|
10302
|
+
orgId: z17.string().max(128).nullable().optional(),
|
|
10303
|
+
cols: z17.number().int().min(1).max(1e3).default(120),
|
|
10304
|
+
rows: z17.number().int().min(1).max(1e3).default(30),
|
|
10305
|
+
enableMcp: z17.boolean().default(false),
|
|
10306
|
+
apiBaseUrl: z17.string().max(512).optional(),
|
|
10307
|
+
environmentId: z17.string().max(128).optional(),
|
|
10308
|
+
attachedContexts: z17.array(z17.object({
|
|
10309
|
+
label: z17.string().max(200),
|
|
10310
|
+
text: z17.string().max(1e6)
|
|
10175
10311
|
})).max(20).optional()
|
|
10176
10312
|
})).mutation(async ({ input, ctx }) => {
|
|
10177
10313
|
const t0 = Date.now();
|
|
@@ -10330,10 +10466,10 @@ Context:
|
|
|
10330
10466
|
return { spawnId: res.spawnId, agentId, reattached: false };
|
|
10331
10467
|
}),
|
|
10332
10468
|
/** Subscribe to PTY output stream (raw text with ANSI). */
|
|
10333
|
-
stream: protectedProcedure.input(
|
|
10334
|
-
agentId:
|
|
10335
|
-
spawnId:
|
|
10336
|
-
fromOffset:
|
|
10469
|
+
stream: protectedProcedure.input(z17.object({
|
|
10470
|
+
agentId: z17.string().max(128).optional(),
|
|
10471
|
+
spawnId: z17.string().max(128),
|
|
10472
|
+
fromOffset: z17.number().int().min(0).default(0)
|
|
10337
10473
|
})).subscription(async function* ({ input, signal }) {
|
|
10338
10474
|
const agentId = input.agentId ?? agentManager.getDefaultAgentId();
|
|
10339
10475
|
if (!agentId) throw new TRPCError12({ code: "PRECONDITION_FAILED", message: "No agent available" });
|
|
@@ -10385,10 +10521,10 @@ Context:
|
|
|
10385
10521
|
}
|
|
10386
10522
|
}),
|
|
10387
10523
|
/** Write input to a PTY session (keystrokes from xterm). */
|
|
10388
|
-
write: protectedProcedure.input(
|
|
10389
|
-
agentId:
|
|
10390
|
-
spawnId:
|
|
10391
|
-
data:
|
|
10524
|
+
write: protectedProcedure.input(z17.object({
|
|
10525
|
+
agentId: z17.string().max(128).optional(),
|
|
10526
|
+
spawnId: z17.string().max(128),
|
|
10527
|
+
data: z17.string().max(1e6)
|
|
10392
10528
|
})).mutation(async ({ input }) => {
|
|
10393
10529
|
const agentId = input.agentId ?? agentManager.getDefaultAgentId();
|
|
10394
10530
|
if (!agentId) throw new TRPCError12({ code: "PRECONDITION_FAILED", message: "No agent available" });
|
|
@@ -10398,11 +10534,11 @@ Context:
|
|
|
10398
10534
|
});
|
|
10399
10535
|
}),
|
|
10400
10536
|
/** Resize a PTY session. */
|
|
10401
|
-
resize: protectedProcedure.input(
|
|
10402
|
-
agentId:
|
|
10403
|
-
spawnId:
|
|
10404
|
-
cols:
|
|
10405
|
-
rows:
|
|
10537
|
+
resize: protectedProcedure.input(z17.object({
|
|
10538
|
+
agentId: z17.string().max(128).optional(),
|
|
10539
|
+
spawnId: z17.string().max(128),
|
|
10540
|
+
cols: z17.number().int().min(1).max(1e3),
|
|
10541
|
+
rows: z17.number().int().min(1).max(1e3)
|
|
10406
10542
|
})).mutation(async ({ input }) => {
|
|
10407
10543
|
const agentId = input.agentId ?? agentManager.getDefaultAgentId();
|
|
10408
10544
|
if (!agentId) throw new TRPCError12({ code: "PRECONDITION_FAILED", message: "No agent available" });
|
|
@@ -10418,11 +10554,11 @@ Context:
|
|
|
10418
10554
|
* picks it up. Returns the tmp path and which clipboard method succeeded
|
|
10419
10555
|
* (null if none — caller should inject `@<path>` instead of Ctrl+V).
|
|
10420
10556
|
*/
|
|
10421
|
-
pasteImage: protectedProcedure.input(
|
|
10422
|
-
agentId:
|
|
10423
|
-
sessionId:
|
|
10424
|
-
mimeType:
|
|
10425
|
-
base64:
|
|
10557
|
+
pasteImage: protectedProcedure.input(z17.object({
|
|
10558
|
+
agentId: z17.string().max(128).optional(),
|
|
10559
|
+
sessionId: z17.string().max(128).optional(),
|
|
10560
|
+
mimeType: z17.string().max(64),
|
|
10561
|
+
base64: z17.string().max(15e6)
|
|
10426
10562
|
})).mutation(async ({ input }) => {
|
|
10427
10563
|
const agentId = input.agentId ?? agentManager.getDefaultAgentId();
|
|
10428
10564
|
if (!agentId) throw new TRPCError12({ code: "PRECONDITION_FAILED", message: "No agent available" });
|
|
@@ -10440,7 +10576,7 @@ Context:
|
|
|
10440
10576
|
* Read the transcript Claude Code stores on disk for a given session.
|
|
10441
10577
|
* Returns parsed JSONL entries (user / assistant messages, tool uses, etc.).
|
|
10442
10578
|
*/
|
|
10443
|
-
transcript: protectedProcedure.input(
|
|
10579
|
+
transcript: protectedProcedure.input(z17.object({ sessionId: z17.string().max(128) })).query(async ({ input }) => {
|
|
10444
10580
|
return readClaudeTranscript(input.sessionId);
|
|
10445
10581
|
}),
|
|
10446
10582
|
/**
|
|
@@ -10448,9 +10584,9 @@ Context:
|
|
|
10448
10584
|
* when was the transcript JSONL last touched? Used by the non-PTY view
|
|
10449
10585
|
* to show a "Claude is thinking…" indicator while output streams.
|
|
10450
10586
|
*/
|
|
10451
|
-
activity: protectedProcedure.input(
|
|
10452
|
-
agentId:
|
|
10453
|
-
sessionId:
|
|
10587
|
+
activity: protectedProcedure.input(z17.object({
|
|
10588
|
+
agentId: z17.string().max(128).optional(),
|
|
10589
|
+
sessionId: z17.string().max(128)
|
|
10454
10590
|
})).query(async ({ input }) => {
|
|
10455
10591
|
const agentId = input.agentId ?? agentManager.getDefaultAgentId();
|
|
10456
10592
|
let running = false;
|
|
@@ -10476,7 +10612,7 @@ Context:
|
|
|
10476
10612
|
* them on the conversation, so the non-PTY chat view stays in sync.
|
|
10477
10613
|
* Uses the conversation id as session id (PTY sessions are spawned that way).
|
|
10478
10614
|
*/
|
|
10479
|
-
syncTranscript: protectedProcedure.input(
|
|
10615
|
+
syncTranscript: protectedProcedure.input(z17.object({ conversationId: ConversationIdSchema })).mutation(async ({ input }) => {
|
|
10480
10616
|
const conv = await conversationStore.get(input.conversationId);
|
|
10481
10617
|
if (!conv) {
|
|
10482
10618
|
throw new TRPCError12({ code: "NOT_FOUND", message: `Conversation ${input.conversationId} not found` });
|
|
@@ -10490,14 +10626,14 @@ Context:
|
|
|
10490
10626
|
* with the given sessionId. Used to benchmark the PTY → tRPC → xterm.js
|
|
10491
10627
|
* pipeline. Open the conversation in PTY mode to attach to it.
|
|
10492
10628
|
*/
|
|
10493
|
-
debugStress: protectedProcedure.input(
|
|
10494
|
-
sessionId:
|
|
10495
|
-
agentId:
|
|
10496
|
-
bytesPerSec:
|
|
10497
|
-
chunkSize:
|
|
10498
|
-
durationMs:
|
|
10499
|
-
cols:
|
|
10500
|
-
rows:
|
|
10629
|
+
debugStress: protectedProcedure.input(z17.object({
|
|
10630
|
+
sessionId: z17.string().max(128),
|
|
10631
|
+
agentId: z17.string().max(128).optional(),
|
|
10632
|
+
bytesPerSec: z17.number().int().min(100).max(1e7).default(5e4),
|
|
10633
|
+
chunkSize: z17.number().int().min(1).max(65536).default(256),
|
|
10634
|
+
durationMs: z17.number().int().min(0).max(36e5).default(0),
|
|
10635
|
+
cols: z17.number().int().min(1).max(1e3).default(120),
|
|
10636
|
+
rows: z17.number().int().min(1).max(1e3).default(30)
|
|
10501
10637
|
})).mutation(async ({ input }) => {
|
|
10502
10638
|
const agentId = input.agentId ?? agentManager.getDefaultAgentId();
|
|
10503
10639
|
if (!agentId) throw new TRPCError12({ code: "PRECONDITION_FAILED", message: "No agent available" });
|
|
@@ -10544,9 +10680,9 @@ Context:
|
|
|
10544
10680
|
return { spawnId: res.spawnId, agentId, stressSessionId };
|
|
10545
10681
|
}),
|
|
10546
10682
|
/** Kill a PTY session. */
|
|
10547
|
-
kill: protectedProcedure.input(
|
|
10548
|
-
agentId:
|
|
10549
|
-
spawnId:
|
|
10683
|
+
kill: protectedProcedure.input(z17.object({
|
|
10684
|
+
agentId: z17.string().max(128).optional(),
|
|
10685
|
+
spawnId: z17.string().max(128)
|
|
10550
10686
|
})).mutation(async ({ input }) => {
|
|
10551
10687
|
const agentId = input.agentId ?? agentManager.getDefaultAgentId();
|
|
10552
10688
|
if (!agentId) throw new TRPCError12({ code: "PRECONDITION_FAILED", message: "No agent available" });
|
|
@@ -10558,16 +10694,16 @@ Context:
|
|
|
10558
10694
|
});
|
|
10559
10695
|
|
|
10560
10696
|
// ../server/src/trpc/routers/git.ts
|
|
10561
|
-
import { z as
|
|
10697
|
+
import { z as z18 } from "zod";
|
|
10562
10698
|
import { TRPCError as TRPCError13 } from "@trpc/server";
|
|
10563
10699
|
import Anthropic3 from "@anthropic-ai/sdk";
|
|
10564
10700
|
import OpenAI3 from "openai";
|
|
10565
|
-
var SERVICE_ID_SCHEMA =
|
|
10566
|
-
var SAFE_PATH_SCHEMA =
|
|
10701
|
+
var SERVICE_ID_SCHEMA = z18.string().max(128);
|
|
10702
|
+
var SAFE_PATH_SCHEMA = z18.string().min(1).max(4096).refine((p) => !p.startsWith("/") && !p.includes("../"), {
|
|
10567
10703
|
message: "Path must be relative and not traverse up"
|
|
10568
10704
|
});
|
|
10569
|
-
var REMOTE_SCHEMA =
|
|
10570
|
-
var BRANCH_SCHEMA =
|
|
10705
|
+
var REMOTE_SCHEMA = z18.string().min(1).max(128).regex(/^[a-zA-Z0-9_\-.]+$/);
|
|
10706
|
+
var BRANCH_SCHEMA = z18.string().min(1).max(256).regex(/^[a-zA-Z0-9._\-/]+$/);
|
|
10571
10707
|
async function resolveServiceContext(serviceId) {
|
|
10572
10708
|
const service = await serviceStore.get(serviceId);
|
|
10573
10709
|
if (!service) {
|
|
@@ -10581,11 +10717,11 @@ async function resolveServiceContext(serviceId) {
|
|
|
10581
10717
|
}
|
|
10582
10718
|
var gitTargetShape = {
|
|
10583
10719
|
serviceId: SERVICE_ID_SCHEMA.optional(),
|
|
10584
|
-
agentId:
|
|
10720
|
+
agentId: z18.string().max(128).optional(),
|
|
10585
10721
|
/** Anchors on a project when no service is targeted (e.g. from the AI chat). */
|
|
10586
|
-
projectId:
|
|
10722
|
+
projectId: z18.string().max(128).optional(),
|
|
10587
10723
|
/** Son organisation : un id de projet seul peut en nommer un par organisation. */
|
|
10588
|
-
orgId:
|
|
10724
|
+
orgId: z18.string().max(128).nullable().optional()
|
|
10589
10725
|
};
|
|
10590
10726
|
async function resolveGitContext(input) {
|
|
10591
10727
|
if (input.serviceId) return resolveServiceContext(input.serviceId);
|
|
@@ -10598,82 +10734,82 @@ async function resolveGitContext(input) {
|
|
|
10598
10734
|
}
|
|
10599
10735
|
var gitRouter = router({
|
|
10600
10736
|
/** Get full git status */
|
|
10601
|
-
status: protectedProcedure.input(
|
|
10737
|
+
status: protectedProcedure.input(z18.object({ ...gitTargetShape })).query(async ({ input }) => {
|
|
10602
10738
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10603
10739
|
return agentManager.agentQuery(agentId, "git.status", { cwd });
|
|
10604
10740
|
}),
|
|
10605
10741
|
/** Get commit log */
|
|
10606
|
-
log: protectedProcedure.input(
|
|
10742
|
+
log: protectedProcedure.input(z18.object({ ...gitTargetShape, limit: z18.number().int().min(1).max(200).default(50) })).query(async ({ input }) => {
|
|
10607
10743
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10608
10744
|
return agentManager.agentQuery(agentId, "git.log", { cwd, limit: input.limit });
|
|
10609
10745
|
}),
|
|
10610
10746
|
/** List local and remote branches */
|
|
10611
|
-
branches: protectedProcedure.input(
|
|
10747
|
+
branches: protectedProcedure.input(z18.object({ ...gitTargetShape })).query(async ({ input }) => {
|
|
10612
10748
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10613
10749
|
return agentManager.agentQuery(agentId, "git.branches", { cwd });
|
|
10614
10750
|
}),
|
|
10615
10751
|
/** Checkout a branch */
|
|
10616
|
-
checkout: protectedProcedure.input(
|
|
10752
|
+
checkout: protectedProcedure.input(z18.object({ ...gitTargetShape, branch: BRANCH_SCHEMA, create: z18.boolean().default(false) })).mutation(async ({ input }) => {
|
|
10617
10753
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10618
10754
|
return agentManager.agentMutation(agentId, "git.checkout", { cwd, branch: input.branch, create: input.create });
|
|
10619
10755
|
}),
|
|
10620
10756
|
/** Stage files */
|
|
10621
|
-
stage: protectedProcedure.input(
|
|
10757
|
+
stage: protectedProcedure.input(z18.object({ ...gitTargetShape, paths: z18.array(SAFE_PATH_SCHEMA).min(1).max(500) })).mutation(async ({ input }) => {
|
|
10622
10758
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10623
10759
|
return agentManager.agentMutation(agentId, "git.stage", { cwd, paths: input.paths });
|
|
10624
10760
|
}),
|
|
10625
10761
|
/** Stage all files */
|
|
10626
|
-
stageAll: protectedProcedure.input(
|
|
10762
|
+
stageAll: protectedProcedure.input(z18.object({ ...gitTargetShape })).mutation(async ({ input }) => {
|
|
10627
10763
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10628
10764
|
return agentManager.agentMutation(agentId, "git.stageAll", { cwd });
|
|
10629
10765
|
}),
|
|
10630
10766
|
/** Unstage files */
|
|
10631
|
-
unstage: protectedProcedure.input(
|
|
10767
|
+
unstage: protectedProcedure.input(z18.object({ ...gitTargetShape, paths: z18.array(SAFE_PATH_SCHEMA).min(1).max(500) })).mutation(async ({ input }) => {
|
|
10632
10768
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10633
10769
|
return agentManager.agentMutation(agentId, "git.unstage", { cwd, paths: input.paths });
|
|
10634
10770
|
}),
|
|
10635
10771
|
/** Unstage all files */
|
|
10636
|
-
unstageAll: protectedProcedure.input(
|
|
10772
|
+
unstageAll: protectedProcedure.input(z18.object({ ...gitTargetShape })).mutation(async ({ input }) => {
|
|
10637
10773
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10638
10774
|
return agentManager.agentMutation(agentId, "git.unstageAll", { cwd });
|
|
10639
10775
|
}),
|
|
10640
10776
|
/** Commit staged changes */
|
|
10641
|
-
commit: protectedProcedure.input(
|
|
10777
|
+
commit: protectedProcedure.input(z18.object({ ...gitTargetShape, message: z18.string().min(1).max(4096) })).mutation(async ({ input }) => {
|
|
10642
10778
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10643
10779
|
return agentManager.agentMutation(agentId, "git.commit", { cwd, message: input.message });
|
|
10644
10780
|
}),
|
|
10645
10781
|
/** Push to remote */
|
|
10646
|
-
push: protectedProcedure.input(
|
|
10782
|
+
push: protectedProcedure.input(z18.object({ ...gitTargetShape, remote: REMOTE_SCHEMA.default("origin"), setUpstream: z18.boolean().default(false) })).mutation(async ({ input }) => {
|
|
10647
10783
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10648
10784
|
return agentManager.agentMutation(agentId, "git.push", { cwd, remote: input.remote, setUpstream: input.setUpstream });
|
|
10649
10785
|
}),
|
|
10650
10786
|
/** Pull from remote */
|
|
10651
|
-
pull: protectedProcedure.input(
|
|
10787
|
+
pull: protectedProcedure.input(z18.object({ ...gitTargetShape, remote: REMOTE_SCHEMA.default("origin") })).mutation(async ({ input }) => {
|
|
10652
10788
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10653
10789
|
return agentManager.agentMutation(agentId, "git.pull", { cwd, remote: input.remote });
|
|
10654
10790
|
}),
|
|
10655
10791
|
/** Fetch from remote */
|
|
10656
|
-
fetch: protectedProcedure.input(
|
|
10792
|
+
fetch: protectedProcedure.input(z18.object({ ...gitTargetShape, remote: REMOTE_SCHEMA.default("origin") })).mutation(async ({ input }) => {
|
|
10657
10793
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10658
10794
|
return agentManager.agentMutation(agentId, "git.fetch", { cwd, remote: input.remote });
|
|
10659
10795
|
}),
|
|
10660
10796
|
/** Get diff for a file or the whole index */
|
|
10661
|
-
diff: protectedProcedure.input(
|
|
10797
|
+
diff: protectedProcedure.input(z18.object({
|
|
10662
10798
|
...gitTargetShape,
|
|
10663
|
-
path:
|
|
10664
|
-
staged:
|
|
10665
|
-
untracked:
|
|
10799
|
+
path: z18.string().max(4096).optional(),
|
|
10800
|
+
staged: z18.boolean().default(false),
|
|
10801
|
+
untracked: z18.boolean().default(false)
|
|
10666
10802
|
})).query(async ({ input }) => {
|
|
10667
10803
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10668
10804
|
return agentManager.agentQuery(agentId, "git.diff", { cwd, path: input.path, staged: input.staged, untracked: input.untracked });
|
|
10669
10805
|
}),
|
|
10670
10806
|
/** Discard changes to working tree files */
|
|
10671
|
-
discard: protectedProcedure.input(
|
|
10807
|
+
discard: protectedProcedure.input(z18.object({ ...gitTargetShape, paths: z18.array(SAFE_PATH_SCHEMA).min(1).max(500) })).mutation(async ({ input }) => {
|
|
10672
10808
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10673
10809
|
return agentManager.agentMutation(agentId, "git.discard", { cwd, paths: input.paths });
|
|
10674
10810
|
}),
|
|
10675
10811
|
/** Generate a commit message from staged diffs using AI (diff fetched from agent, AI runs on server) */
|
|
10676
|
-
generateCommitMessage: protectedProcedure.input(
|
|
10812
|
+
generateCommitMessage: protectedProcedure.input(z18.object({ ...gitTargetShape, providerId: OptionalProviderIdSchema, model: z18.string().max(200).optional() })).mutation(async ({ input }) => {
|
|
10677
10813
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10678
10814
|
const { diff } = await agentManager.agentQuery(agentId, "git.stagedDiff", { cwd });
|
|
10679
10815
|
if (!diff.trim()) {
|
|
@@ -10720,42 +10856,42 @@ Rules:
|
|
|
10720
10856
|
throw new TRPCError13({ code: "BAD_REQUEST", message: "Unsupported AI provider" });
|
|
10721
10857
|
}),
|
|
10722
10858
|
/** Merge a branch into the current branch */
|
|
10723
|
-
merge: protectedProcedure.input(
|
|
10859
|
+
merge: protectedProcedure.input(z18.object({ ...gitTargetShape, branch: BRANCH_SCHEMA, noFf: z18.boolean().default(false) })).mutation(async ({ input }) => {
|
|
10724
10860
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10725
10861
|
return agentManager.agentMutation(agentId, "git.merge", { cwd, branch: input.branch, noFf: input.noFf });
|
|
10726
10862
|
}),
|
|
10727
10863
|
/** Rebase current branch onto another branch */
|
|
10728
|
-
rebase: protectedProcedure.input(
|
|
10864
|
+
rebase: protectedProcedure.input(z18.object({ ...gitTargetShape, branch: BRANCH_SCHEMA })).mutation(async ({ input }) => {
|
|
10729
10865
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10730
10866
|
return agentManager.agentMutation(agentId, "git.rebase", { cwd, branch: input.branch });
|
|
10731
10867
|
}),
|
|
10732
10868
|
/** List stash entries */
|
|
10733
|
-
stashList: protectedProcedure.input(
|
|
10869
|
+
stashList: protectedProcedure.input(z18.object({ ...gitTargetShape })).query(async ({ input }) => {
|
|
10734
10870
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10735
10871
|
return agentManager.agentQuery(agentId, "git.stashList", { cwd });
|
|
10736
10872
|
}),
|
|
10737
10873
|
/** Stash current changes */
|
|
10738
|
-
stashPush: protectedProcedure.input(
|
|
10874
|
+
stashPush: protectedProcedure.input(z18.object({ ...gitTargetShape, message: z18.string().max(4096).optional(), includeUntracked: z18.boolean().default(true) })).mutation(async ({ input }) => {
|
|
10739
10875
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10740
10876
|
return agentManager.agentMutation(agentId, "git.stashPush", { cwd, message: input.message, includeUntracked: input.includeUntracked });
|
|
10741
10877
|
}),
|
|
10742
10878
|
/** Pop a stash entry */
|
|
10743
|
-
stashPop: protectedProcedure.input(
|
|
10879
|
+
stashPop: protectedProcedure.input(z18.object({ ...gitTargetShape, index: z18.number().int().min(0).max(1e3).default(0) })).mutation(async ({ input }) => {
|
|
10744
10880
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10745
10881
|
return agentManager.agentMutation(agentId, "git.stashPop", { cwd, index: input.index });
|
|
10746
10882
|
}),
|
|
10747
10883
|
/** Apply a stash entry without dropping it */
|
|
10748
|
-
stashApply: protectedProcedure.input(
|
|
10884
|
+
stashApply: protectedProcedure.input(z18.object({ ...gitTargetShape, index: z18.number().int().min(0).max(1e3).default(0) })).mutation(async ({ input }) => {
|
|
10749
10885
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10750
10886
|
return agentManager.agentMutation(agentId, "git.stashApply", { cwd, index: input.index });
|
|
10751
10887
|
}),
|
|
10752
10888
|
/** Drop a stash entry */
|
|
10753
|
-
stashDrop: protectedProcedure.input(
|
|
10889
|
+
stashDrop: protectedProcedure.input(z18.object({ ...gitTargetShape, index: z18.number().int().min(0).max(1e3).default(0) })).mutation(async ({ input }) => {
|
|
10754
10890
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10755
10891
|
return agentManager.agentMutation(agentId, "git.stashDrop", { cwd, index: input.index });
|
|
10756
10892
|
}),
|
|
10757
10893
|
/** Watch .git/ for changes and stream updated status */
|
|
10758
|
-
onStatusChange: protectedProcedure.input(
|
|
10894
|
+
onStatusChange: protectedProcedure.input(z18.object({ ...gitTargetShape })).subscription(async function* ({ input }) {
|
|
10759
10895
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10760
10896
|
const queue = [];
|
|
10761
10897
|
let resolve7 = null;
|
|
@@ -10802,16 +10938,16 @@ Rules:
|
|
|
10802
10938
|
}
|
|
10803
10939
|
}),
|
|
10804
10940
|
/** List remotes */
|
|
10805
|
-
remotes: protectedProcedure.input(
|
|
10941
|
+
remotes: protectedProcedure.input(z18.object({ ...gitTargetShape })).query(async ({ input }) => {
|
|
10806
10942
|
const { agentId, cwd } = await resolveGitContext(input);
|
|
10807
10943
|
return agentManager.agentQuery(agentId, "git.remotes", { cwd });
|
|
10808
10944
|
})
|
|
10809
10945
|
});
|
|
10810
10946
|
|
|
10811
10947
|
// ../server/src/trpc/routers/scenario.ts
|
|
10812
|
-
import { randomUUID as
|
|
10948
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
10813
10949
|
import { TRPCError as TRPCError16 } from "@trpc/server";
|
|
10814
|
-
import { z as
|
|
10950
|
+
import { z as z19 } from "zod";
|
|
10815
10951
|
|
|
10816
10952
|
// ../server/src/trpc/crud-procedure-utils.ts
|
|
10817
10953
|
import { TRPCError as TRPCError14 } from "@trpc/server";
|
|
@@ -10925,9 +11061,9 @@ async function* streamWithActiveProvider(opts) {
|
|
|
10925
11061
|
}
|
|
10926
11062
|
|
|
10927
11063
|
// ../server/src/services/scenario-runner.ts
|
|
10928
|
-
import { mkdir as
|
|
10929
|
-
import { randomUUID as
|
|
10930
|
-
import { join as
|
|
11064
|
+
import { mkdir as mkdir16 } from "fs/promises";
|
|
11065
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
11066
|
+
import { join as join19 } from "path";
|
|
10931
11067
|
|
|
10932
11068
|
// ../server/src/services/scenario-presets.ts
|
|
10933
11069
|
var BUILT_IN_PRESETS = [
|
|
@@ -11268,7 +11404,7 @@ function applyHireDirectivesFromOutput(manager, scenario, output) {
|
|
|
11268
11404
|
}
|
|
11269
11405
|
const hired = [];
|
|
11270
11406
|
for (const payload of hireDirectives) {
|
|
11271
|
-
const id = `hire-${
|
|
11407
|
+
const id = `hire-${randomUUID6().slice(0, 8)}`;
|
|
11272
11408
|
const position = computeHirePosition(manager, scenario.nodes);
|
|
11273
11409
|
ensureGroupCanContainNode(scenario, manager.groupId ?? null, position);
|
|
11274
11410
|
const node = {
|
|
@@ -11707,7 +11843,7 @@ async function appendNodeOutput(conversationId, node, output) {
|
|
|
11707
11843
|
if (!dir) return;
|
|
11708
11844
|
const slug = node.label.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 60) || "member";
|
|
11709
11845
|
const safeId = node.id.replace(/[^a-z0-9_-]/gi, "-").slice(0, 80);
|
|
11710
|
-
const filePath =
|
|
11846
|
+
const filePath = join19(dir, `${slug}_${safeId}.md`);
|
|
11711
11847
|
const content = `## Output
|
|
11712
11848
|
|
|
11713
11849
|
${output}
|
|
@@ -11720,9 +11856,9 @@ async function appendToReadme(conversationId, bus, text) {
|
|
|
11720
11856
|
const line = `${text}
|
|
11721
11857
|
`;
|
|
11722
11858
|
try {
|
|
11723
|
-
await
|
|
11859
|
+
await mkdir16(dir, { recursive: true });
|
|
11724
11860
|
const { appendFile: appendFile2 } = await import("fs/promises");
|
|
11725
|
-
await appendFile2(
|
|
11861
|
+
await appendFile2(join19(dir, "README.md"), line, "utf-8");
|
|
11726
11862
|
} catch {
|
|
11727
11863
|
}
|
|
11728
11864
|
publishToBus(bus, { type: "readme_append", text: line });
|
|
@@ -11742,7 +11878,7 @@ async function writeFinalMd(conversationId, bus, userRequest, content) {
|
|
|
11742
11878
|
|
|
11743
11879
|
${content}
|
|
11744
11880
|
`;
|
|
11745
|
-
const filePath =
|
|
11881
|
+
const filePath = join19(dir, "FINAL.md");
|
|
11746
11882
|
await atomicWriteSecure(filePath, fullContent);
|
|
11747
11883
|
await appendToReadme(
|
|
11748
11884
|
conversationId,
|
|
@@ -12410,33 +12546,33 @@ Modify the scenario. Keep existing ids when possible.`;
|
|
|
12410
12546
|
return `Generate an scenario org-chart based on: ${userPrompt}`;
|
|
12411
12547
|
}
|
|
12412
12548
|
var ScopeShape2 = {
|
|
12413
|
-
orgId:
|
|
12549
|
+
orgId: z19.string().max(128).nullable().optional(),
|
|
12414
12550
|
projectId: Id128Schema.optional()
|
|
12415
12551
|
};
|
|
12416
12552
|
async function scopeOf2(input) {
|
|
12417
12553
|
return input?.orgId ?? await vaultOfProject(input?.projectId);
|
|
12418
12554
|
}
|
|
12419
12555
|
var scenarioRouter = router({
|
|
12420
|
-
list: protectedProcedure.input(
|
|
12421
|
-
get: protectedProcedure.input(
|
|
12556
|
+
list: protectedProcedure.input(z19.object(ScopeShape2).optional()).query(async ({ input }) => scenarioStore.list(await scopeOf2(input))),
|
|
12557
|
+
get: protectedProcedure.input(z19.object({ id: Id128Schema, ...ScopeShape2 })).query(async ({ input }) => getOrNotFound(
|
|
12422
12558
|
async () => scenarioStore.get(input.id, await scopeOf2(input)),
|
|
12423
12559
|
"Scenario not found"
|
|
12424
12560
|
)),
|
|
12425
|
-
create: protectedProcedure.input(
|
|
12561
|
+
create: protectedProcedure.input(z19.object({
|
|
12426
12562
|
name: NameSchema,
|
|
12427
|
-
icon:
|
|
12563
|
+
icon: z19.string().max(64).optional(),
|
|
12428
12564
|
description: DescriptionSchema.optional(),
|
|
12429
12565
|
leaderId: Id128Schema,
|
|
12430
|
-
groups:
|
|
12431
|
-
nodes:
|
|
12432
|
-
traversalMode:
|
|
12433
|
-
presetId:
|
|
12434
|
-
isPublished:
|
|
12566
|
+
groups: z19.array(ScenarioGroupSchema).max(100).optional(),
|
|
12567
|
+
nodes: z19.array(ScenarioNodeSchema).min(1).max(500),
|
|
12568
|
+
traversalMode: z19.enum(["hierarchical", "topological"]).optional(),
|
|
12569
|
+
presetId: z19.string().max(128).optional(),
|
|
12570
|
+
isPublished: z19.boolean().optional(),
|
|
12435
12571
|
...ScopeShape2
|
|
12436
12572
|
})).mutation(({ input }) => {
|
|
12437
12573
|
const now = Date.now();
|
|
12438
12574
|
return createOrBadRequest(async () => scenarioStore.create({
|
|
12439
|
-
id:
|
|
12575
|
+
id: randomUUID7(),
|
|
12440
12576
|
name: input.name,
|
|
12441
12577
|
icon: input.icon,
|
|
12442
12578
|
description: input.description,
|
|
@@ -12450,17 +12586,17 @@ var scenarioRouter = router({
|
|
|
12450
12586
|
updatedAt: now
|
|
12451
12587
|
}));
|
|
12452
12588
|
}),
|
|
12453
|
-
update: protectedProcedure.input(
|
|
12589
|
+
update: protectedProcedure.input(z19.object({
|
|
12454
12590
|
id: Id128Schema,
|
|
12455
12591
|
name: NameSchema.optional(),
|
|
12456
|
-
icon:
|
|
12592
|
+
icon: z19.string().max(64).optional(),
|
|
12457
12593
|
description: DescriptionSchema.optional(),
|
|
12458
12594
|
leaderId: Id128Schema.optional(),
|
|
12459
|
-
groups:
|
|
12460
|
-
nodes:
|
|
12461
|
-
traversalMode:
|
|
12462
|
-
presetId:
|
|
12463
|
-
isPublished:
|
|
12595
|
+
groups: z19.array(ScenarioGroupSchema).max(100).optional(),
|
|
12596
|
+
nodes: z19.array(ScenarioNodeSchema).min(1).max(500).optional(),
|
|
12597
|
+
traversalMode: z19.enum(["hierarchical", "topological"]).optional(),
|
|
12598
|
+
presetId: z19.string().max(128).optional(),
|
|
12599
|
+
isPublished: z19.boolean().optional(),
|
|
12464
12600
|
...ScopeShape2
|
|
12465
12601
|
})).mutation(({ input }) => updateOrThrow(
|
|
12466
12602
|
async () => scenarioStore.update(input.id, {
|
|
@@ -12477,22 +12613,22 @@ var scenarioRouter = router({
|
|
|
12477
12613
|
}, await scopeOf2(input)),
|
|
12478
12614
|
"Scenario not found"
|
|
12479
12615
|
)),
|
|
12480
|
-
delete: protectedProcedure.input(
|
|
12616
|
+
delete: protectedProcedure.input(z19.object({ id: Id128Schema, ...ScopeShape2 })).mutation(({ input }) => deleteOrNotFound(
|
|
12481
12617
|
async () => scenarioStore.delete(input.id, await scopeOf2(input)),
|
|
12482
12618
|
"Scenario not found"
|
|
12483
12619
|
)),
|
|
12484
|
-
run: protectedProcedure.input(
|
|
12620
|
+
run: protectedProcedure.input(z19.object({
|
|
12485
12621
|
conversationId: ConversationIdSchema,
|
|
12486
12622
|
scenarioId: Id128Schema,
|
|
12487
|
-
userRequest:
|
|
12488
|
-
runnerOverride:
|
|
12623
|
+
userRequest: z19.string().max(1e5),
|
|
12624
|
+
runnerOverride: z19.enum(["claude-code", "codex"]).optional(),
|
|
12489
12625
|
modelOverride: Id128Schema.optional(),
|
|
12490
12626
|
agentId: Id128Schema.optional(),
|
|
12491
12627
|
/** Anchors the run's working directory on the project it belongs to. */
|
|
12492
12628
|
projectId: Id128Schema.optional(),
|
|
12493
12629
|
/** Son organisation : sans elle, un id partagé désignerait un projet au hasard. */
|
|
12494
|
-
orgId:
|
|
12495
|
-
resume:
|
|
12630
|
+
orgId: z19.string().max(128).nullable().optional(),
|
|
12631
|
+
resume: z19.boolean().optional()
|
|
12496
12632
|
})).subscription(async function* ({ input, signal }) {
|
|
12497
12633
|
const scenario = await scenarioStore.get(input.scenarioId, await scopeOf2(input));
|
|
12498
12634
|
if (!scenario) throw new TRPCError16({ code: "NOT_FOUND", message: "Scenario not found" });
|
|
@@ -12512,41 +12648,41 @@ var scenarioRouter = router({
|
|
|
12512
12648
|
}
|
|
12513
12649
|
yield* tapBus(input.conversationId, signal ?? new AbortController().signal);
|
|
12514
12650
|
}),
|
|
12515
|
-
stop: protectedProcedure.input(
|
|
12651
|
+
stop: protectedProcedure.input(z19.object({ conversationId: ConversationIdSchema })).mutation(({ input }) => {
|
|
12516
12652
|
abortScenario(input.conversationId);
|
|
12517
12653
|
return { ok: true };
|
|
12518
12654
|
}),
|
|
12519
|
-
sendNodeInput: protectedProcedure.input(
|
|
12655
|
+
sendNodeInput: protectedProcedure.input(z19.object({
|
|
12520
12656
|
conversationId: ConversationIdSchema,
|
|
12521
12657
|
nodeId: Id128Schema,
|
|
12522
|
-
text:
|
|
12658
|
+
text: z19.string().min(1).max(1e5)
|
|
12523
12659
|
})).mutation(({ input }) => {
|
|
12524
12660
|
const resolved = resolveNodeInput(input.conversationId, input.nodeId, input.text);
|
|
12525
12661
|
if (!resolved) throw new TRPCError16({ code: "NOT_FOUND", message: "No pending input request for this node" });
|
|
12526
12662
|
return { ok: true };
|
|
12527
12663
|
}),
|
|
12528
|
-
isRunning: protectedProcedure.input(
|
|
12529
|
-
runState: protectedProcedure.input(
|
|
12664
|
+
isRunning: protectedProcedure.input(z19.object({ conversationId: ConversationIdSchema })).query(({ input }) => ({ running: isScenarioRunning(input.conversationId) })),
|
|
12665
|
+
runState: protectedProcedure.input(z19.object({ conversationId: ConversationIdSchema })).query(({ input }) => {
|
|
12530
12666
|
const runState = scenarioRunStore.getRunState(input.conversationId);
|
|
12531
12667
|
return runState ?? { nodeStates: {}, nodeOutputs: {}, activeNodeId: void 0 };
|
|
12532
12668
|
}),
|
|
12533
|
-
getPersistedRunState: protectedProcedure.input(
|
|
12669
|
+
getPersistedRunState: protectedProcedure.input(z19.object({ conversationId: ConversationIdSchema })).query(async ({ input }) => {
|
|
12534
12670
|
return await scenarioRunStore.loadPersistedRunState(input.conversationId);
|
|
12535
12671
|
}),
|
|
12536
|
-
getReadme: protectedProcedure.input(
|
|
12672
|
+
getReadme: protectedProcedure.input(z19.object({ conversationId: ConversationIdSchema })).query(async ({ input }) => {
|
|
12537
12673
|
return await scenarioRunStore.readReadme(input.conversationId);
|
|
12538
12674
|
}),
|
|
12539
|
-
getSnapshot: protectedProcedure.input(
|
|
12675
|
+
getSnapshot: protectedProcedure.input(z19.object({ conversationId: ConversationIdSchema })).query(async ({ input }) => {
|
|
12540
12676
|
return await scenarioRunStore.loadScenarioSnapshot(input.conversationId);
|
|
12541
12677
|
}),
|
|
12542
|
-
streamGenerateWithAI: protectedProcedure.input(
|
|
12543
|
-
prompt:
|
|
12678
|
+
streamGenerateWithAI: protectedProcedure.input(z19.object({
|
|
12679
|
+
prompt: z19.string().min(1).max(1e4),
|
|
12544
12680
|
providerId: OptionalProviderIdSchema,
|
|
12545
|
-
model:
|
|
12546
|
-
current:
|
|
12681
|
+
model: z19.string().max(200).optional(),
|
|
12682
|
+
current: z19.object({
|
|
12547
12683
|
leaderId: Id128Schema,
|
|
12548
|
-
groups:
|
|
12549
|
-
nodes:
|
|
12684
|
+
groups: z19.array(ScenarioGroupSchema).max(100),
|
|
12685
|
+
nodes: z19.array(ScenarioNodeSchema).max(500)
|
|
12550
12686
|
}).optional()
|
|
12551
12687
|
})).subscription(async function* ({ input, signal }) {
|
|
12552
12688
|
const userMessage = buildScenarioUserMessage(input.prompt, input.current);
|
|
@@ -12559,7 +12695,7 @@ var scenarioRouter = router({
|
|
|
12559
12695
|
signal: signal ?? void 0
|
|
12560
12696
|
});
|
|
12561
12697
|
}),
|
|
12562
|
-
streamRunEvents: protectedProcedure.input(
|
|
12698
|
+
streamRunEvents: protectedProcedure.input(z19.object({ conversationId: ConversationIdSchema })).subscription(async function* ({ input }) {
|
|
12563
12699
|
const convId = input.conversationId;
|
|
12564
12700
|
const runState = scenarioRunStore.getRunState(convId);
|
|
12565
12701
|
if (runState) {
|
|
@@ -12573,14 +12709,14 @@ var scenarioRouter = router({
|
|
|
12573
12709
|
* open a debug PTY with `claude --resume <sessionId>` on the right agent.
|
|
12574
12710
|
* Falls back to the persisted run-state for past nodes.
|
|
12575
12711
|
*/
|
|
12576
|
-
getNodeSession: protectedProcedure.input(
|
|
12712
|
+
getNodeSession: protectedProcedure.input(z19.object({
|
|
12577
12713
|
conversationId: ConversationIdSchema,
|
|
12578
12714
|
nodeId: Id128Schema
|
|
12579
12715
|
})).query(async ({ input }) => {
|
|
12580
12716
|
return await scenarioRunStore.getNodeSessionPersistent(input.conversationId, input.nodeId);
|
|
12581
12717
|
}),
|
|
12582
12718
|
listPresets: protectedProcedure.query(() => listPresets()),
|
|
12583
|
-
getPreset: protectedProcedure.input(
|
|
12719
|
+
getPreset: protectedProcedure.input(z19.object({ id: Id128Schema })).query(({ input }) => {
|
|
12584
12720
|
const preset = getPreset(input.id);
|
|
12585
12721
|
if (!preset) throw new TRPCError16({ code: "NOT_FOUND", message: "Preset not found" });
|
|
12586
12722
|
return preset;
|
|
@@ -12588,9 +12724,9 @@ var scenarioRouter = router({
|
|
|
12588
12724
|
});
|
|
12589
12725
|
|
|
12590
12726
|
// ../server/src/trpc/routers/debug.ts
|
|
12591
|
-
import { randomUUID as
|
|
12727
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
12592
12728
|
import { TRPCError as TRPCError17 } from "@trpc/server";
|
|
12593
|
-
import { z as
|
|
12729
|
+
import { z as z20 } from "zod";
|
|
12594
12730
|
var MAX_BUFFER3 = 300;
|
|
12595
12731
|
var jobs = /* @__PURE__ */ new Map();
|
|
12596
12732
|
function publish(job, event) {
|
|
@@ -12647,11 +12783,11 @@ async function* tapJob(job, signal) {
|
|
|
12647
12783
|
}
|
|
12648
12784
|
}
|
|
12649
12785
|
var debugRouter = router({
|
|
12650
|
-
startRandomJob: protectedProcedure.input(
|
|
12651
|
-
intervalMs:
|
|
12652
|
-
maxTicks:
|
|
12786
|
+
startRandomJob: protectedProcedure.input(z20.object({
|
|
12787
|
+
intervalMs: z20.number().int().min(100).max(5e3).optional(),
|
|
12788
|
+
maxTicks: z20.number().int().min(1).max(1e4).optional()
|
|
12653
12789
|
}).optional()).mutation(({ input }) => {
|
|
12654
|
-
const jobId =
|
|
12790
|
+
const jobId = randomUUID8();
|
|
12655
12791
|
const intervalMs = input?.intervalMs ?? 400;
|
|
12656
12792
|
const maxTicks = input?.maxTicks ?? 500;
|
|
12657
12793
|
const job = {
|
|
@@ -12683,15 +12819,15 @@ var debugRouter = router({
|
|
|
12683
12819
|
jobs.set(jobId, job);
|
|
12684
12820
|
return { jobId, intervalMs, maxTicks, startedAt: job.startedAt };
|
|
12685
12821
|
}),
|
|
12686
|
-
streamRandomJob: protectedProcedure.input(
|
|
12822
|
+
streamRandomJob: protectedProcedure.input(z20.object({ jobId: z20.string().max(128) })).subscription(async function* ({ input, signal }) {
|
|
12687
12823
|
const job = jobs.get(input.jobId);
|
|
12688
12824
|
if (!job) {
|
|
12689
12825
|
throw new TRPCError17({ code: "NOT_FOUND", message: "Random job not found" });
|
|
12690
12826
|
}
|
|
12691
12827
|
yield* tapJob(job, signal ?? new AbortController().signal);
|
|
12692
12828
|
}),
|
|
12693
|
-
stopRandomJob: protectedProcedure.input(
|
|
12694
|
-
randomJobStatus: protectedProcedure.input(
|
|
12829
|
+
stopRandomJob: protectedProcedure.input(z20.object({ jobId: z20.string().max(128) })).mutation(({ input }) => ({ ok: stopJob(input.jobId, "stopped") })),
|
|
12830
|
+
randomJobStatus: protectedProcedure.input(z20.object({ jobId: z20.string().max(128) })).query(({ input }) => {
|
|
12695
12831
|
const job = jobs.get(input.jobId);
|
|
12696
12832
|
return {
|
|
12697
12833
|
running: !!job && !job.done,
|
|
@@ -12701,7 +12837,7 @@ var debugRouter = router({
|
|
|
12701
12837
|
});
|
|
12702
12838
|
|
|
12703
12839
|
// ../server/src/trpc/routers/diagnostics.ts
|
|
12704
|
-
import { z as
|
|
12840
|
+
import { z as z21 } from "zod";
|
|
12705
12841
|
import { TRPCError as TRPCError18 } from "@trpc/server";
|
|
12706
12842
|
|
|
12707
12843
|
// ../server/src/services/log-buffer.ts
|
|
@@ -12773,7 +12909,7 @@ function onEntry(listener) {
|
|
|
12773
12909
|
// ../server/src/trpc/routers/diagnostics.ts
|
|
12774
12910
|
var diagnosticsRouter = router({
|
|
12775
12911
|
/** Backlog for a client that just opened the panel. */
|
|
12776
|
-
recentLogs: protectedProcedure.input(
|
|
12912
|
+
recentLogs: protectedProcedure.input(z21.object({ limit: z21.number().int().min(1).max(2e3).default(500) }).optional()).query(({ input }) => recentEntries(input?.limit ?? 500)),
|
|
12777
12913
|
/**
|
|
12778
12914
|
* Live log stream.
|
|
12779
12915
|
*
|
|
@@ -12782,7 +12918,7 @@ var diagnosticsRouter = router({
|
|
|
12782
12918
|
* silently loses lines, which is precisely what someone watching a boot
|
|
12783
12919
|
* failure cannot afford.
|
|
12784
12920
|
*/
|
|
12785
|
-
streamLogs: protectedProcedure.input(
|
|
12921
|
+
streamLogs: protectedProcedure.input(z21.object({ afterSeq: z21.number().int().nonnegative().default(0) }).optional()).subscription(async function* ({ input, signal }) {
|
|
12786
12922
|
for (const entry of entriesSince(input?.afterSeq ?? 0)) yield entry;
|
|
12787
12923
|
const queue = [];
|
|
12788
12924
|
let wake = null;
|
|
@@ -12816,7 +12952,7 @@ var diagnosticsRouter = router({
|
|
|
12816
12952
|
* refused. That is what keeps this from being a way to signal arbitrary
|
|
12817
12953
|
* processes with the server's privileges.
|
|
12818
12954
|
*/
|
|
12819
|
-
killInstance: protectedProcedure.input(
|
|
12955
|
+
killInstance: protectedProcedure.input(z21.object({ pid: z21.number().int().positive() })).mutation(async ({ input }) => {
|
|
12820
12956
|
try {
|
|
12821
12957
|
return await killInstance(input.pid);
|
|
12822
12958
|
} catch (err) {
|
|
@@ -12829,14 +12965,49 @@ var diagnosticsRouter = router({
|
|
|
12829
12965
|
}
|
|
12830
12966
|
throw new TRPCError18({ code: "INTERNAL_SERVER_ERROR", message: reason });
|
|
12831
12967
|
}
|
|
12968
|
+
}),
|
|
12969
|
+
/**
|
|
12970
|
+
* Redémarrer une Runeya de cette machine : même exécutable, mêmes arguments,
|
|
12971
|
+
* même répertoire, mêmes `RUNEYA_*`.
|
|
12972
|
+
*
|
|
12973
|
+
* Deux chemins pour une même promesse. Une autre instance est arrêtée puis
|
|
12974
|
+
* relancée d'ici, et la réponse dit ce qui s'est passé. Celle-ci ne peut pas :
|
|
12975
|
+
* elle répond d'abord, pose un relanceur détaché, et part — d'où un résultat
|
|
12976
|
+
* qui annonce un redémarrage à venir plutôt qu'un redémarrage fait.
|
|
12977
|
+
*
|
|
12978
|
+
* Mêmes garde-fous que `killInstance` — le pid est un sélecteur cherché dans
|
|
12979
|
+
* la liste validée — plus un refus propre quand le lancement n'est pas
|
|
12980
|
+
* reproductible : instance trop ancienne pour avoir publié sa ligne de
|
|
12981
|
+
* commande, ou lancée avec un secret que le registre ne conserve pas.
|
|
12982
|
+
*/
|
|
12983
|
+
restartInstance: protectedProcedure.input(z21.object({ pid: z21.number().int().positive() })).mutation(async ({ input }) => {
|
|
12984
|
+
try {
|
|
12985
|
+
if (input.pid === process.pid) {
|
|
12986
|
+
const { relauncherPid, port } = await scheduleSelfRestart();
|
|
12987
|
+
return { self: true, relauncherPid, port };
|
|
12988
|
+
}
|
|
12989
|
+
return { self: false, ...await restartInstance(input.pid) };
|
|
12990
|
+
} catch (err) {
|
|
12991
|
+
const reason = err.message;
|
|
12992
|
+
if (reason === "instance-not-found") {
|
|
12993
|
+
throw new TRPCError18({ code: "NOT_FOUND", message: "No live Runeya instance with this pid." });
|
|
12994
|
+
}
|
|
12995
|
+
if (reason.startsWith("instance-not-restartable:")) {
|
|
12996
|
+
throw new TRPCError18({
|
|
12997
|
+
code: "BAD_REQUEST",
|
|
12998
|
+
message: `This instance cannot be restarted (${reason.split(":")[1]}).`
|
|
12999
|
+
});
|
|
13000
|
+
}
|
|
13001
|
+
throw new TRPCError18({ code: "INTERNAL_SERVER_ERROR", message: reason });
|
|
13002
|
+
}
|
|
12832
13003
|
})
|
|
12833
13004
|
});
|
|
12834
13005
|
|
|
12835
13006
|
// ../server/src/trpc/routers/kanban-queue.ts
|
|
12836
|
-
import { z as
|
|
13007
|
+
import { z as z22 } from "zod";
|
|
12837
13008
|
|
|
12838
13009
|
// ../server/src/services/kanban-queue.ts
|
|
12839
|
-
import { randomUUID as
|
|
13010
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
12840
13011
|
import { EventEmitter as EventEmitter5 } from "events";
|
|
12841
13012
|
var KanbanQueueService = class extends EventEmitter5 {
|
|
12842
13013
|
items = [];
|
|
@@ -12864,7 +13035,7 @@ var KanbanQueueService = class extends EventEmitter5 {
|
|
|
12864
13035
|
return { id: alreadyRunning.id, addedAt: alreadyRunning.startedAt, ...item };
|
|
12865
13036
|
}
|
|
12866
13037
|
const queueItem = {
|
|
12867
|
-
id:
|
|
13038
|
+
id: randomUUID9(),
|
|
12868
13039
|
...item,
|
|
12869
13040
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
12870
13041
|
};
|
|
@@ -13021,36 +13192,36 @@ var kanbanQueue = new KanbanQueueService();
|
|
|
13021
13192
|
// ../server/src/trpc/routers/kanban-queue.ts
|
|
13022
13193
|
var kanbanQueueRouter = router({
|
|
13023
13194
|
getState: protectedProcedure.query(() => kanbanQueue.getState()),
|
|
13024
|
-
add: protectedProcedure.input(
|
|
13025
|
-
boardId:
|
|
13026
|
-
cardId:
|
|
13027
|
-
runner:
|
|
13028
|
-
model:
|
|
13029
|
-
scenarioId:
|
|
13195
|
+
add: protectedProcedure.input(z22.object({
|
|
13196
|
+
boardId: z22.string().max(128),
|
|
13197
|
+
cardId: z22.string().max(128),
|
|
13198
|
+
runner: z22.enum(["claude-code", "codex"]).optional(),
|
|
13199
|
+
model: z22.string().max(128).optional(),
|
|
13200
|
+
scenarioId: z22.string().max(128).optional(),
|
|
13030
13201
|
// Le projet ouvert quand la carte a été mise en file : la conversation
|
|
13031
13202
|
// qui en naîtra lui appartient, plutôt que de rester orpheline et de
|
|
13032
13203
|
// s'afficher dans tous les projets.
|
|
13033
|
-
projectId:
|
|
13034
|
-
orgId:
|
|
13204
|
+
projectId: z22.string().max(128).optional(),
|
|
13205
|
+
orgId: z22.string().max(128).nullable().optional()
|
|
13035
13206
|
})).mutation(({ input }) => kanbanQueue.add(input)),
|
|
13036
|
-
addColumn: protectedProcedure.input(
|
|
13037
|
-
boardId:
|
|
13038
|
-
columnId:
|
|
13039
|
-
runner:
|
|
13040
|
-
model:
|
|
13041
|
-
scenarioId:
|
|
13042
|
-
projectId:
|
|
13043
|
-
orgId:
|
|
13207
|
+
addColumn: protectedProcedure.input(z22.object({
|
|
13208
|
+
boardId: z22.string().max(128),
|
|
13209
|
+
columnId: z22.string().max(128),
|
|
13210
|
+
runner: z22.enum(["claude-code", "codex"]).optional(),
|
|
13211
|
+
model: z22.string().max(128).optional(),
|
|
13212
|
+
scenarioId: z22.string().max(128).optional(),
|
|
13213
|
+
projectId: z22.string().max(128).optional(),
|
|
13214
|
+
orgId: z22.string().max(128).nullable().optional()
|
|
13044
13215
|
})).mutation(async ({ input }) => {
|
|
13045
13216
|
const { boardId, columnId, ...options } = input;
|
|
13046
13217
|
return kanbanQueue.addColumn(boardId, columnId, options);
|
|
13047
13218
|
}),
|
|
13048
|
-
remove: protectedProcedure.input(
|
|
13219
|
+
remove: protectedProcedure.input(z22.object({ itemId: z22.string().max(128) })).mutation(({ input }) => ({ removed: kanbanQueue.remove(input.itemId) })),
|
|
13049
13220
|
stopAll: protectedProcedure.mutation(() => {
|
|
13050
13221
|
kanbanQueue.stopAll();
|
|
13051
13222
|
return { ok: true };
|
|
13052
13223
|
}),
|
|
13053
|
-
setMaxConcurrent: protectedProcedure.input(
|
|
13224
|
+
setMaxConcurrent: protectedProcedure.input(z22.object({ max: z22.number().int().min(1).max(20) })).mutation(({ input }) => {
|
|
13054
13225
|
kanbanQueue.setMaxConcurrent(input.max);
|
|
13055
13226
|
return kanbanQueue.getState();
|
|
13056
13227
|
}),
|
|
@@ -13084,11 +13255,11 @@ var kanbanQueueRouter = router({
|
|
|
13084
13255
|
});
|
|
13085
13256
|
|
|
13086
13257
|
// ../server/src/trpc/routers/kanban.ts
|
|
13087
|
-
import { mkdir as
|
|
13258
|
+
import { mkdir as mkdir17, readdir as readdir5, rm as rm3, stat as stat5, writeFile as writeFile15 } from "fs/promises";
|
|
13088
13259
|
import { createHash } from "crypto";
|
|
13089
13260
|
import { tmpdir } from "os";
|
|
13090
|
-
import { join as
|
|
13091
|
-
import { z as
|
|
13261
|
+
import { join as join20 } from "path";
|
|
13262
|
+
import { z as z23 } from "zod";
|
|
13092
13263
|
import { TRPCError as TRPCError19 } from "@trpc/server";
|
|
13093
13264
|
function summarizeCard(card, boardId, columnTitle) {
|
|
13094
13265
|
return {
|
|
@@ -13138,14 +13309,14 @@ function safeDecode(value) {
|
|
|
13138
13309
|
}
|
|
13139
13310
|
var MAX_ATTACHMENT_BYTES = 55 * 1024 * 1024;
|
|
13140
13311
|
function attachmentCacheDir() {
|
|
13141
|
-
return
|
|
13312
|
+
return join20(tmpdir(), "runeya-kanban-attachments");
|
|
13142
13313
|
}
|
|
13143
13314
|
var ATTACHMENT_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
13144
13315
|
async function purgeStaleAttachments(dir, ttlMs = ATTACHMENT_CACHE_TTL_MS) {
|
|
13145
13316
|
try {
|
|
13146
13317
|
const cutoff = Date.now() - ttlMs;
|
|
13147
13318
|
for (const name of await readdir5(dir)) {
|
|
13148
|
-
const path =
|
|
13319
|
+
const path = join20(dir, name);
|
|
13149
13320
|
const info = await stat5(path).catch(() => null);
|
|
13150
13321
|
if (info && info.mtimeMs < cutoff) await rm3(path, { force: true });
|
|
13151
13322
|
}
|
|
@@ -13153,15 +13324,15 @@ async function purgeStaleAttachments(dir, ttlMs = ATTACHMENT_CACHE_TTL_MS) {
|
|
|
13153
13324
|
}
|
|
13154
13325
|
}
|
|
13155
13326
|
function attachmentCacheDirs() {
|
|
13156
|
-
return [attachmentCacheDir(),
|
|
13327
|
+
return [attachmentCacheDir(), join20(machineRoot(), "kanban-attachments")];
|
|
13157
13328
|
}
|
|
13158
13329
|
async function storeAttachment(id, name, body, dirs = attachmentCacheDirs()) {
|
|
13159
13330
|
const refusals = [];
|
|
13160
13331
|
for (const dir of dirs) {
|
|
13161
13332
|
try {
|
|
13162
|
-
await
|
|
13163
|
-
const path =
|
|
13164
|
-
await
|
|
13333
|
+
await mkdir17(dir, { recursive: true });
|
|
13334
|
+
const path = join20(dir, safeLocalName(id, name));
|
|
13335
|
+
await writeFile15(path, body);
|
|
13165
13336
|
void purgeStaleAttachments(dir);
|
|
13166
13337
|
return path;
|
|
13167
13338
|
} catch (err) {
|
|
@@ -13184,9 +13355,9 @@ var kanbanRouter = router({
|
|
|
13184
13355
|
* card graph, so listing them in full would be megabytes to answer "which
|
|
13185
13356
|
* boards exist?". Use `getBoard` for the cards of one.
|
|
13186
13357
|
*/
|
|
13187
|
-
listBoards: protectedProcedure.input(
|
|
13188
|
-
includeArchived:
|
|
13189
|
-
organizationId:
|
|
13358
|
+
listBoards: protectedProcedure.input(z23.object({
|
|
13359
|
+
includeArchived: z23.boolean().optional(),
|
|
13360
|
+
organizationId: z23.string().max(128).optional()
|
|
13190
13361
|
}).optional()).query(async ({ input }) => {
|
|
13191
13362
|
const { organizationId, boards } = await kanbanStore.list(
|
|
13192
13363
|
input?.includeArchived ?? false,
|
|
@@ -13212,7 +13383,7 @@ var kanbanRouter = router({
|
|
|
13212
13383
|
};
|
|
13213
13384
|
}),
|
|
13214
13385
|
/** One board: its columns, and the cards in each. */
|
|
13215
|
-
getBoard: protectedProcedure.input(
|
|
13386
|
+
getBoard: protectedProcedure.input(z23.object({ boardId: z23.string().max(128) })).query(async ({ input }) => {
|
|
13216
13387
|
const board = await kanbanStore.get(input.boardId);
|
|
13217
13388
|
if (!board) return { board: null };
|
|
13218
13389
|
const { links } = await kanbanStore.cardLinks(input.boardId);
|
|
@@ -13251,11 +13422,11 @@ var kanbanRouter = router({
|
|
|
13251
13422
|
* organization — or one board when `boardId` is given. Archived boards are
|
|
13252
13423
|
* left out: they are what the team decided to stop looking at.
|
|
13253
13424
|
*/
|
|
13254
|
-
searchCards: protectedProcedure.input(
|
|
13255
|
-
query:
|
|
13256
|
-
boardId:
|
|
13257
|
-
limit:
|
|
13258
|
-
organizationId:
|
|
13425
|
+
searchCards: protectedProcedure.input(z23.object({
|
|
13426
|
+
query: z23.string().min(1).max(256),
|
|
13427
|
+
boardId: z23.string().max(128).optional(),
|
|
13428
|
+
limit: z23.number().int().min(1).max(100).optional(),
|
|
13429
|
+
organizationId: z23.string().max(128).optional()
|
|
13259
13430
|
})).query(async ({ input }) => {
|
|
13260
13431
|
const needle = normalize(input.query);
|
|
13261
13432
|
const ids = input.boardId ? [input.boardId] : (await kanbanStore.list(false, input.organizationId)).boards.map((b) => b.id);
|
|
@@ -13274,10 +13445,10 @@ var kanbanRouter = router({
|
|
|
13274
13445
|
* qu'un `commentCount`, et rien n'en donnait le texte. Cette route est la
|
|
13275
13446
|
* relecture, pour une seule carte : c'est le journal qui pèse, pas le reste.
|
|
13276
13447
|
*/
|
|
13277
|
-
getCardComments: protectedProcedure.input(
|
|
13278
|
-
boardId:
|
|
13279
|
-
cardId:
|
|
13280
|
-
limit:
|
|
13448
|
+
getCardComments: protectedProcedure.input(z23.object({
|
|
13449
|
+
boardId: z23.string().max(128),
|
|
13450
|
+
cardId: z23.string().max(128),
|
|
13451
|
+
limit: z23.number().int().min(1).max(200).optional()
|
|
13281
13452
|
})).query(async ({ input }) => {
|
|
13282
13453
|
const history = await kanbanStore.cardHistory(input.boardId, input.cardId);
|
|
13283
13454
|
const comments = history.filter((e) => e.type === "comment");
|
|
@@ -13306,18 +13477,18 @@ var kanbanRouter = router({
|
|
|
13306
13477
|
* `getBoard` en donne déjà l'essentiel carte par carte ; cette route sert
|
|
13307
13478
|
* quand c'est l'arbre lui-même qu'on veut, dates et auteurs compris.
|
|
13308
13479
|
*/
|
|
13309
|
-
getCardLinks: protectedProcedure.input(
|
|
13480
|
+
getCardLinks: protectedProcedure.input(z23.object({ boardId: z23.string().max(128) })).query(async ({ input }) => kanbanStore.cardLinks(input.boardId)),
|
|
13310
13481
|
/**
|
|
13311
13482
|
* Rattacher une carte à une carte parente, ou l'en détacher.
|
|
13312
13483
|
*
|
|
13313
13484
|
* Sans `parentCardId`, le lien est retiré. Le parent peut vivre sur un autre
|
|
13314
13485
|
* tableau : `parentBoardId` le désigne alors, sinon c'est celui de la carte.
|
|
13315
13486
|
*/
|
|
13316
|
-
setCardParent: protectedProcedure.input(
|
|
13317
|
-
boardId:
|
|
13318
|
-
cardId:
|
|
13319
|
-
parentCardId:
|
|
13320
|
-
parentBoardId:
|
|
13487
|
+
setCardParent: protectedProcedure.input(z23.object({
|
|
13488
|
+
boardId: z23.string().max(128),
|
|
13489
|
+
cardId: z23.string().max(128),
|
|
13490
|
+
parentCardId: z23.string().max(128).optional(),
|
|
13491
|
+
parentBoardId: z23.string().max(128).optional()
|
|
13321
13492
|
})).mutation(async ({ input }) => {
|
|
13322
13493
|
const ok = await kanbanStore.setCardParent(
|
|
13323
13494
|
input.boardId,
|
|
@@ -13329,31 +13500,31 @@ var kanbanRouter = router({
|
|
|
13329
13500
|
}
|
|
13330
13501
|
return { ok: true };
|
|
13331
13502
|
}),
|
|
13332
|
-
moveCard: protectedProcedure.input(
|
|
13333
|
-
boardId:
|
|
13334
|
-
cardId:
|
|
13335
|
-
targetColumn:
|
|
13503
|
+
moveCard: protectedProcedure.input(z23.object({
|
|
13504
|
+
boardId: z23.string().max(128),
|
|
13505
|
+
cardId: z23.string().max(128),
|
|
13506
|
+
targetColumn: z23.string().max(256)
|
|
13336
13507
|
})).mutation(async ({ input }) => {
|
|
13337
13508
|
await executeKanbanCommands(input.boardId, input.cardId, [
|
|
13338
13509
|
{ type: "move_card", columnTitle: input.targetColumn }
|
|
13339
13510
|
]);
|
|
13340
13511
|
return { ok: true };
|
|
13341
13512
|
}),
|
|
13342
|
-
addComment: protectedProcedure.input(
|
|
13343
|
-
boardId:
|
|
13344
|
-
cardId:
|
|
13345
|
-
comment:
|
|
13513
|
+
addComment: protectedProcedure.input(z23.object({
|
|
13514
|
+
boardId: z23.string().max(128),
|
|
13515
|
+
cardId: z23.string().max(128),
|
|
13516
|
+
comment: z23.string().max(2e4)
|
|
13346
13517
|
})).mutation(async ({ input }) => {
|
|
13347
13518
|
await executeKanbanCommands(input.boardId, input.cardId, [
|
|
13348
13519
|
{ type: "add_comment", comment: input.comment }
|
|
13349
13520
|
]);
|
|
13350
13521
|
return { ok: true };
|
|
13351
13522
|
}),
|
|
13352
|
-
addCard: protectedProcedure.input(
|
|
13353
|
-
boardId:
|
|
13354
|
-
column:
|
|
13355
|
-
title:
|
|
13356
|
-
content:
|
|
13523
|
+
addCard: protectedProcedure.input(z23.object({
|
|
13524
|
+
boardId: z23.string().max(128),
|
|
13525
|
+
column: z23.string().max(256),
|
|
13526
|
+
title: z23.string().max(512),
|
|
13527
|
+
content: z23.string().max(2e4).optional()
|
|
13357
13528
|
})).mutation(async ({ input }) => {
|
|
13358
13529
|
await executeKanbanBoardCommands(input.boardId, [
|
|
13359
13530
|
{ type: "add_card", columnTitle: input.column, cardTitle: input.title, cardContent: input.content }
|
|
@@ -13365,7 +13536,7 @@ var kanbanRouter = router({
|
|
|
13365
13536
|
* agent can open it with its own file tools. The bytes never go through the
|
|
13366
13537
|
* prompt: the card context lists the attachments, this returns a path.
|
|
13367
13538
|
*/
|
|
13368
|
-
downloadAttachment: protectedProcedure.input(
|
|
13539
|
+
downloadAttachment: protectedProcedure.input(z23.object({ attachmentId: z23.string().max(128) })).mutation(async ({ input }) => {
|
|
13369
13540
|
const id = input.attachmentId;
|
|
13370
13541
|
if (!ATTACHMENT_ID_REGEX.test(id)) {
|
|
13371
13542
|
throw new TRPCError19({ code: "BAD_REQUEST", message: "Invalid attachment id" });
|
|
@@ -13398,21 +13569,21 @@ var kanbanRouter = router({
|
|
|
13398
13569
|
});
|
|
13399
13570
|
|
|
13400
13571
|
// ../server/src/trpc/routers/terminal.ts
|
|
13401
|
-
import { z as
|
|
13572
|
+
import { z as z24 } from "zod";
|
|
13402
13573
|
import { TRPCError as TRPCError20 } from "@trpc/server";
|
|
13403
13574
|
var terminalRouter = router({
|
|
13404
13575
|
/** Create a PTY shell session on the target agent */
|
|
13405
|
-
create: protectedProcedure.input(
|
|
13406
|
-
agentId:
|
|
13407
|
-
cwd:
|
|
13576
|
+
create: protectedProcedure.input(z24.object({
|
|
13577
|
+
agentId: z24.string().max(128),
|
|
13578
|
+
cwd: z24.string().max(512).optional(),
|
|
13408
13579
|
/** Anchors the terminal when no explicit cwd is given. */
|
|
13409
|
-
serviceId:
|
|
13410
|
-
projectId:
|
|
13580
|
+
serviceId: z24.string().max(128).optional(),
|
|
13581
|
+
projectId: z24.string().max(128).optional(),
|
|
13411
13582
|
/** L'organisation du projet : un id seul peut en nommer un par organisation. */
|
|
13412
|
-
orgId:
|
|
13413
|
-
cols:
|
|
13414
|
-
rows:
|
|
13415
|
-
title:
|
|
13583
|
+
orgId: z24.string().max(128).nullable().optional(),
|
|
13584
|
+
cols: z24.number().int().min(1).max(512).optional(),
|
|
13585
|
+
rows: z24.number().int().min(1).max(256).optional(),
|
|
13586
|
+
title: z24.string().max(128).optional()
|
|
13416
13587
|
})).mutation(async ({ input }) => {
|
|
13417
13588
|
const result = await agentManager.agentMutation(
|
|
13418
13589
|
input.agentId,
|
|
@@ -13433,17 +13604,17 @@ var terminalRouter = router({
|
|
|
13433
13604
|
return result;
|
|
13434
13605
|
}),
|
|
13435
13606
|
/** Les sessions PTY encore vivantes sur l'agent (onglets à retrouver) */
|
|
13436
|
-
list: protectedProcedure.input(
|
|
13607
|
+
list: protectedProcedure.input(z24.object({ agentId: z24.string().max(128) })).query(async ({ input }) => {
|
|
13437
13608
|
return agentManager.agentQuery(
|
|
13438
13609
|
input.agentId,
|
|
13439
13610
|
"terminal.list"
|
|
13440
13611
|
);
|
|
13441
13612
|
}),
|
|
13442
13613
|
/** Renommer un onglet */
|
|
13443
|
-
rename: protectedProcedure.input(
|
|
13444
|
-
agentId:
|
|
13445
|
-
sessionId:
|
|
13446
|
-
title:
|
|
13614
|
+
rename: protectedProcedure.input(z24.object({
|
|
13615
|
+
agentId: z24.string().max(128),
|
|
13616
|
+
sessionId: z24.string().max(128),
|
|
13617
|
+
title: z24.string().max(128)
|
|
13447
13618
|
})).mutation(async ({ input }) => {
|
|
13448
13619
|
await agentManager.agentMutation(
|
|
13449
13620
|
input.agentId,
|
|
@@ -13453,10 +13624,10 @@ var terminalRouter = router({
|
|
|
13453
13624
|
return { ok: true };
|
|
13454
13625
|
}),
|
|
13455
13626
|
/** Send keystrokes / data to a PTY session */
|
|
13456
|
-
write: protectedProcedure.input(
|
|
13457
|
-
agentId:
|
|
13458
|
-
sessionId:
|
|
13459
|
-
data:
|
|
13627
|
+
write: protectedProcedure.input(z24.object({
|
|
13628
|
+
agentId: z24.string().max(128),
|
|
13629
|
+
sessionId: z24.string().max(128),
|
|
13630
|
+
data: z24.string().max(65536)
|
|
13460
13631
|
})).mutation(async ({ input }) => {
|
|
13461
13632
|
await agentManager.agentMutation(
|
|
13462
13633
|
input.agentId,
|
|
@@ -13466,11 +13637,11 @@ var terminalRouter = router({
|
|
|
13466
13637
|
return { ok: true };
|
|
13467
13638
|
}),
|
|
13468
13639
|
/** Resize the PTY */
|
|
13469
|
-
resize: protectedProcedure.input(
|
|
13470
|
-
agentId:
|
|
13471
|
-
sessionId:
|
|
13472
|
-
cols:
|
|
13473
|
-
rows:
|
|
13640
|
+
resize: protectedProcedure.input(z24.object({
|
|
13641
|
+
agentId: z24.string().max(128),
|
|
13642
|
+
sessionId: z24.string().max(128),
|
|
13643
|
+
cols: z24.number().int().min(1).max(512),
|
|
13644
|
+
rows: z24.number().int().min(1).max(256)
|
|
13474
13645
|
})).mutation(async ({ input }) => {
|
|
13475
13646
|
await agentManager.agentMutation(
|
|
13476
13647
|
input.agentId,
|
|
@@ -13480,9 +13651,9 @@ var terminalRouter = router({
|
|
|
13480
13651
|
return { ok: true };
|
|
13481
13652
|
}),
|
|
13482
13653
|
/** Destroy a PTY session */
|
|
13483
|
-
destroy: protectedProcedure.input(
|
|
13484
|
-
agentId:
|
|
13485
|
-
sessionId:
|
|
13654
|
+
destroy: protectedProcedure.input(z24.object({
|
|
13655
|
+
agentId: z24.string().max(128),
|
|
13656
|
+
sessionId: z24.string().max(128)
|
|
13486
13657
|
})).mutation(async ({ input }) => {
|
|
13487
13658
|
await agentManager.agentMutation(
|
|
13488
13659
|
input.agentId,
|
|
@@ -13492,11 +13663,11 @@ var terminalRouter = router({
|
|
|
13492
13663
|
return { ok: true };
|
|
13493
13664
|
}),
|
|
13494
13665
|
/** Stream PTY output — proxied via AgentWSBridge dynamic subscription */
|
|
13495
|
-
onData: protectedProcedure.input(
|
|
13496
|
-
agentId:
|
|
13497
|
-
sessionId:
|
|
13666
|
+
onData: protectedProcedure.input(z24.object({
|
|
13667
|
+
agentId: z24.string().max(128),
|
|
13668
|
+
sessionId: z24.string().max(128),
|
|
13498
13669
|
/** Rejouer l'historique de la session avant le flux temps réel. */
|
|
13499
|
-
replay:
|
|
13670
|
+
replay: z24.boolean().optional()
|
|
13500
13671
|
})).subscription(async function* ({ input }) {
|
|
13501
13672
|
const queue = [];
|
|
13502
13673
|
let resolve7 = null;
|
|
@@ -13545,11 +13716,11 @@ var terminalRouter = router({
|
|
|
13545
13716
|
});
|
|
13546
13717
|
|
|
13547
13718
|
// ../server/src/trpc/routers/utility.ts
|
|
13548
|
-
import { z as
|
|
13719
|
+
import { z as z25 } from "zod";
|
|
13549
13720
|
var MAX_WAIT_MS = 5 * 60 * 1e3;
|
|
13550
13721
|
var utilityRouter = router({
|
|
13551
|
-
wait: protectedProcedure.input(
|
|
13552
|
-
ms:
|
|
13722
|
+
wait: protectedProcedure.input(z25.object({
|
|
13723
|
+
ms: z25.number().int().min(0).max(MAX_WAIT_MS)
|
|
13553
13724
|
})).mutation(async ({ input }) => {
|
|
13554
13725
|
await new Promise((resolve7) => setTimeout(resolve7, input.ms));
|
|
13555
13726
|
return { waited: input.ms };
|
|
@@ -13557,15 +13728,15 @@ var utilityRouter = router({
|
|
|
13557
13728
|
});
|
|
13558
13729
|
|
|
13559
13730
|
// ../server/src/trpc/routers/wiki.ts
|
|
13560
|
-
import { z as
|
|
13731
|
+
import { z as z26 } from "zod";
|
|
13561
13732
|
import { TRPCError as TRPCError21 } from "@trpc/server";
|
|
13562
|
-
import { readFile as
|
|
13563
|
-
import { resolve as resolvePath, join as
|
|
13564
|
-
var SCOPE_SCHEMA =
|
|
13565
|
-
|
|
13566
|
-
|
|
13733
|
+
import { readFile as readFile16, readdir as readdir6, stat as stat6, realpath, writeFile as writeFile16, mkdir as mkdir18, rename as rename13, rm as rm4 } from "fs/promises";
|
|
13734
|
+
import { resolve as resolvePath, join as join21, relative, sep as sep3, dirname as dirname9 } from "path";
|
|
13735
|
+
var SCOPE_SCHEMA = z26.union([
|
|
13736
|
+
z26.literal("global"),
|
|
13737
|
+
z26.string().regex(/^service:[A-Za-z0-9_-]{1,128}$/, "Invalid service scope")
|
|
13567
13738
|
]);
|
|
13568
|
-
var REL_PATH_SCHEMA =
|
|
13739
|
+
var REL_PATH_SCHEMA = z26.string().min(1).max(512).regex(/^[A-Za-z0-9_./-]+$/).refine((p) => !p.includes("..") && !p.startsWith("/"), {
|
|
13569
13740
|
message: "Path must be a relative path without traversal"
|
|
13570
13741
|
});
|
|
13571
13742
|
var MAX_FILES = 500;
|
|
@@ -13585,9 +13756,9 @@ var IGNORED_DIRS = /* @__PURE__ */ new Set([
|
|
|
13585
13756
|
"target",
|
|
13586
13757
|
"out"
|
|
13587
13758
|
]);
|
|
13588
|
-
var DocsEntrySchema =
|
|
13589
|
-
|
|
13590
|
-
|
|
13759
|
+
var DocsEntrySchema = z26.lazy(() => z26.union([
|
|
13760
|
+
z26.object({ type: z26.literal("file"), name: z26.string(), path: z26.string() }),
|
|
13761
|
+
z26.object({ type: z26.literal("dir"), name: z26.string(), path: z26.string(), children: z26.array(DocsEntrySchema) })
|
|
13591
13762
|
]));
|
|
13592
13763
|
async function resolveScope(scope) {
|
|
13593
13764
|
if (scope === "global") {
|
|
@@ -13597,13 +13768,13 @@ async function resolveScope(scope) {
|
|
|
13597
13768
|
throw new TRPCError21({ code: "BAD_REQUEST", message: "Sous-chemin invalide" });
|
|
13598
13769
|
}
|
|
13599
13770
|
const dataDirAbs = resolvePath(env.DATA_DIR);
|
|
13600
|
-
await
|
|
13771
|
+
await mkdir18(dataDirAbs, { recursive: true });
|
|
13601
13772
|
const base = dirname9(await realpath(dataDirAbs));
|
|
13602
13773
|
const target = resolvePath(base, sub);
|
|
13603
13774
|
if (target !== base && !(target + sep3).startsWith(base + sep3)) {
|
|
13604
13775
|
throw new TRPCError21({ code: "FORBIDDEN", message: "Hors du dossier de donn\xE9es du serveur" });
|
|
13605
13776
|
}
|
|
13606
|
-
await
|
|
13777
|
+
await mkdir18(target, { recursive: true });
|
|
13607
13778
|
const root = await realpath(target);
|
|
13608
13779
|
if (root !== base && !(root + sep3).startsWith(base + sep3)) {
|
|
13609
13780
|
throw new TRPCError21({ code: "FORBIDDEN", message: "Le dossier wiki r\xE9sout hors du dossier de donn\xE9es" });
|
|
@@ -13630,7 +13801,7 @@ async function walkLocal(root, dir, depth, counter) {
|
|
|
13630
13801
|
for (const e of entries2) {
|
|
13631
13802
|
if (counter.n >= MAX_FILES) break;
|
|
13632
13803
|
if (e.name.startsWith(".") && e.name !== ".") continue;
|
|
13633
|
-
const abs =
|
|
13804
|
+
const abs = join21(dir, e.name);
|
|
13634
13805
|
const rel = relative(root, abs).split(sep3).join("/");
|
|
13635
13806
|
if (e.isDirectory()) {
|
|
13636
13807
|
if (IGNORED_DIRS.has(e.name)) continue;
|
|
@@ -13677,7 +13848,7 @@ async function resolveSafeLocal(root, relPath, requireExist) {
|
|
|
13677
13848
|
return resolvePath(realParent, target.slice(parent.length).replace(/^[\\/]+/, ""));
|
|
13678
13849
|
}
|
|
13679
13850
|
var wikiRouter = router({
|
|
13680
|
-
list: protectedProcedure.input(
|
|
13851
|
+
list: protectedProcedure.input(z26.object({ scope: SCOPE_SCHEMA })).output(z26.object({ root: z26.string(), entries: z26.array(DocsEntrySchema), truncated: z26.boolean() })).query(async ({ input }) => {
|
|
13681
13852
|
const target = await resolveScope(input.scope);
|
|
13682
13853
|
if (target.mode === "agent") {
|
|
13683
13854
|
return agentManager.agentQuery(target.agentId, "wiki.listRepoMarkdown", { cwd: target.cwd });
|
|
@@ -13686,7 +13857,7 @@ var wikiRouter = router({
|
|
|
13686
13857
|
const entries2 = await walkLocal(target.root, target.root, 0, counter);
|
|
13687
13858
|
return { root: target.root, entries: entries2, truncated: counter.n >= MAX_FILES };
|
|
13688
13859
|
}),
|
|
13689
|
-
read: protectedProcedure.input(
|
|
13860
|
+
read: protectedProcedure.input(z26.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA })).output(z26.object({ path: z26.string(), content: z26.string() })).query(async ({ input }) => {
|
|
13690
13861
|
if (!/\.(md|markdown)$/i.test(input.path)) {
|
|
13691
13862
|
throw new TRPCError21({ code: "BAD_REQUEST", message: "Seuls les .md/.markdown sont autoris\xE9s" });
|
|
13692
13863
|
}
|
|
@@ -13698,10 +13869,10 @@ var wikiRouter = router({
|
|
|
13698
13869
|
const s = await stat6(file);
|
|
13699
13870
|
if (!s.isFile()) throw new TRPCError21({ code: "BAD_REQUEST", message: "Pas un fichier" });
|
|
13700
13871
|
if (s.size > MAX_FILE_BYTES) throw new TRPCError21({ code: "PAYLOAD_TOO_LARGE", message: "Fichier trop volumineux" });
|
|
13701
|
-
const content = await
|
|
13872
|
+
const content = await readFile16(file, "utf-8");
|
|
13702
13873
|
return { path: input.path, content };
|
|
13703
13874
|
}),
|
|
13704
|
-
write: protectedProcedure.input(
|
|
13875
|
+
write: protectedProcedure.input(z26.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA, content: z26.string().max(5e6) })).mutation(async ({ input }) => {
|
|
13705
13876
|
if (!/\.(md|markdown)$/i.test(input.path)) {
|
|
13706
13877
|
throw new TRPCError21({ code: "BAD_REQUEST", message: "Seuls les .md/.markdown sont autoris\xE9s" });
|
|
13707
13878
|
}
|
|
@@ -13710,11 +13881,11 @@ var wikiRouter = router({
|
|
|
13710
13881
|
return agentManager.agentMutation(target.agentId, "wiki.writeMarkdown", { cwd: target.cwd, path: input.path, content: input.content });
|
|
13711
13882
|
}
|
|
13712
13883
|
const file = await resolveSafeLocal(target.root, input.path, false);
|
|
13713
|
-
await
|
|
13714
|
-
await
|
|
13884
|
+
await mkdir18(dirname9(file), { recursive: true });
|
|
13885
|
+
await writeFile16(file, input.content, "utf-8");
|
|
13715
13886
|
return { path: input.path, ok: true };
|
|
13716
13887
|
}),
|
|
13717
|
-
createFile: protectedProcedure.input(
|
|
13888
|
+
createFile: protectedProcedure.input(z26.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
|
|
13718
13889
|
if (!/\.(md|markdown)$/i.test(input.path)) {
|
|
13719
13890
|
throw new TRPCError21({ code: "BAD_REQUEST", message: "Seuls les .md/.markdown sont autoris\xE9s" });
|
|
13720
13891
|
}
|
|
@@ -13729,20 +13900,20 @@ var wikiRouter = router({
|
|
|
13729
13900
|
} catch (err) {
|
|
13730
13901
|
if (err instanceof TRPCError21) throw err;
|
|
13731
13902
|
}
|
|
13732
|
-
await
|
|
13733
|
-
await
|
|
13903
|
+
await mkdir18(dirname9(file), { recursive: true });
|
|
13904
|
+
await writeFile16(file, "", "utf-8");
|
|
13734
13905
|
return { path: input.path, ok: true };
|
|
13735
13906
|
}),
|
|
13736
|
-
createDir: protectedProcedure.input(
|
|
13907
|
+
createDir: protectedProcedure.input(z26.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
|
|
13737
13908
|
const target = await resolveScope(input.scope);
|
|
13738
13909
|
if (target.mode === "agent") {
|
|
13739
13910
|
return agentManager.agentMutation(target.agentId, "wiki.createDir", { cwd: target.cwd, path: input.path });
|
|
13740
13911
|
}
|
|
13741
13912
|
const dir = await resolveSafeLocal(target.root, input.path, false);
|
|
13742
|
-
await
|
|
13913
|
+
await mkdir18(dir, { recursive: true });
|
|
13743
13914
|
return { path: input.path, ok: true };
|
|
13744
13915
|
}),
|
|
13745
|
-
rename: protectedProcedure.input(
|
|
13916
|
+
rename: protectedProcedure.input(z26.object({ scope: SCOPE_SCHEMA, fromPath: REL_PATH_SCHEMA, toPath: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
|
|
13746
13917
|
const target = await resolveScope(input.scope);
|
|
13747
13918
|
if (target.mode === "agent") {
|
|
13748
13919
|
return agentManager.agentMutation(target.agentId, "wiki.renamePath", { cwd: target.cwd, fromPath: input.fromPath, toPath: input.toPath });
|
|
@@ -13755,11 +13926,11 @@ var wikiRouter = router({
|
|
|
13755
13926
|
} catch (err) {
|
|
13756
13927
|
if (err instanceof TRPCError21) throw err;
|
|
13757
13928
|
}
|
|
13758
|
-
await
|
|
13759
|
-
await
|
|
13929
|
+
await mkdir18(dirname9(to), { recursive: true });
|
|
13930
|
+
await rename13(from, to);
|
|
13760
13931
|
return { fromPath: input.fromPath, toPath: input.toPath, ok: true };
|
|
13761
13932
|
}),
|
|
13762
|
-
ensureRoot: protectedProcedure.input(
|
|
13933
|
+
ensureRoot: protectedProcedure.input(z26.object({ scope: SCOPE_SCHEMA })).mutation(async ({ input }) => {
|
|
13763
13934
|
if (input.scope === "global") {
|
|
13764
13935
|
await resolveScope("global");
|
|
13765
13936
|
return { ok: true };
|
|
@@ -13772,7 +13943,7 @@ var wikiRouter = router({
|
|
|
13772
13943
|
const cwd = await resolveWorkspaceCwd({ serviceId, override: service.docsPath?.trim() || void 0 });
|
|
13773
13944
|
return agentManager.agentMutation(agentId, "wiki.ensureRoot", { cwd });
|
|
13774
13945
|
}),
|
|
13775
|
-
delete: protectedProcedure.input(
|
|
13946
|
+
delete: protectedProcedure.input(z26.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA })).mutation(async ({ input }) => {
|
|
13776
13947
|
const target = await resolveScope(input.scope);
|
|
13777
13948
|
if (target.mode === "agent") {
|
|
13778
13949
|
return agentManager.agentMutation(target.agentId, "wiki.deletePath", { cwd: target.cwd, path: input.path });
|
|
@@ -13798,14 +13969,14 @@ var configRouter = router({
|
|
|
13798
13969
|
});
|
|
13799
13970
|
|
|
13800
13971
|
// ../server/src/trpc/routers/cloud-sync.ts
|
|
13801
|
-
import { z as
|
|
13972
|
+
import { z as z27 } from "zod";
|
|
13802
13973
|
import { TRPCError as TRPCError22 } from "@trpc/server";
|
|
13803
13974
|
|
|
13804
13975
|
// ../server/src/services/org-sync-scope.ts
|
|
13805
13976
|
import { access as access2 } from "fs/promises";
|
|
13806
|
-
import { join as
|
|
13977
|
+
import { join as join22 } from "path";
|
|
13807
13978
|
async function isMaterialized(root) {
|
|
13808
|
-
return access2(
|
|
13979
|
+
return access2(join22(root, "project.json")).then(() => true, () => false);
|
|
13809
13980
|
}
|
|
13810
13981
|
async function orgsToSync() {
|
|
13811
13982
|
const cloudUrl = getCloudApiUrl();
|
|
@@ -13866,17 +14037,17 @@ async function reconcileOrgCanary(orgId) {
|
|
|
13866
14037
|
}
|
|
13867
14038
|
|
|
13868
14039
|
// ../server/src/services/cloud-sync-bridge.ts
|
|
13869
|
-
import { randomUUID as
|
|
13870
|
-
import { mkdir as
|
|
14040
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
14041
|
+
import { mkdir as mkdir20, rm as rm5 } from "fs/promises";
|
|
13871
14042
|
import * as Y from "yjs";
|
|
13872
14043
|
|
|
13873
14044
|
// ../server/src/services/org-lock.ts
|
|
13874
|
-
import { open as open2, readFile as
|
|
14045
|
+
import { open as open2, readFile as readFile17, unlink as unlink4, mkdir as mkdir19 } from "fs/promises";
|
|
13875
14046
|
import { readFileSync, unlinkSync } from "fs";
|
|
13876
|
-
import { join as
|
|
14047
|
+
import { join as join23 } from "path";
|
|
13877
14048
|
var held = /* @__PURE__ */ new Set();
|
|
13878
14049
|
function lockPath(orgId) {
|
|
13879
|
-
return
|
|
14050
|
+
return join23(orgVaultRoot(orgId), "org.lock");
|
|
13880
14051
|
}
|
|
13881
14052
|
function isRunning(pid) {
|
|
13882
14053
|
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
@@ -13889,7 +14060,7 @@ function isRunning(pid) {
|
|
|
13889
14060
|
}
|
|
13890
14061
|
async function readLock(path) {
|
|
13891
14062
|
try {
|
|
13892
|
-
const parsed = JSON.parse(await
|
|
14063
|
+
const parsed = JSON.parse(await readFile17(path, "utf-8"));
|
|
13893
14064
|
return typeof parsed?.pid === "number" ? parsed : null;
|
|
13894
14065
|
} catch {
|
|
13895
14066
|
return null;
|
|
@@ -13897,7 +14068,7 @@ async function readLock(path) {
|
|
|
13897
14068
|
}
|
|
13898
14069
|
async function acquireOrgLock(orgId) {
|
|
13899
14070
|
const path = lockPath(orgId);
|
|
13900
|
-
await
|
|
14071
|
+
await mkdir19(orgVaultRoot(orgId), { recursive: true });
|
|
13901
14072
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
13902
14073
|
try {
|
|
13903
14074
|
const handle = await open2(path, "wx");
|
|
@@ -13980,7 +14151,7 @@ var OrgSyncConnection = class {
|
|
|
13980
14151
|
projects = getCollection(this.doc, "projects");
|
|
13981
14152
|
services = getCollection(this.doc, "services");
|
|
13982
14153
|
environments = getCollection(this.doc, "environments");
|
|
13983
|
-
conn =
|
|
14154
|
+
conn = randomUUID10();
|
|
13984
14155
|
link;
|
|
13985
14156
|
stopped = false;
|
|
13986
14157
|
initializing = true;
|
|
@@ -14308,7 +14479,7 @@ var OrgSyncConnection = class {
|
|
|
14308
14479
|
}
|
|
14309
14480
|
const isLocal = existing?.orgId === this.link.orgId;
|
|
14310
14481
|
if (!inDoc && !isLocal) return false;
|
|
14311
|
-
await
|
|
14482
|
+
await mkdir20(projectVaultRoot(this.link.orgId, projectId), { recursive: true });
|
|
14312
14483
|
this.tracked.add(projectId);
|
|
14313
14484
|
if (inDoc) await this.pullFromDoc([projectId]);
|
|
14314
14485
|
else await this.reconcileLocalToDoc();
|
|
@@ -14684,8 +14855,8 @@ var CloudSyncBridge = class {
|
|
|
14684
14855
|
var cloudSyncBridge = new CloudSyncBridge();
|
|
14685
14856
|
|
|
14686
14857
|
// ../server/src/services/key-adoption.ts
|
|
14687
|
-
import { readdir as readdir7, readFile as
|
|
14688
|
-
import { join as
|
|
14858
|
+
import { readdir as readdir7, readFile as readFile18, writeFile as writeFile17, mkdir as mkdir21, copyFile, rename as rename14, stat as stat7 } from "fs/promises";
|
|
14859
|
+
import { join as join24 } from "path";
|
|
14689
14860
|
import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes5 } from "crypto";
|
|
14690
14861
|
var ALGORITHM = "aes-256-gcm";
|
|
14691
14862
|
function isAgentTriplet(value) {
|
|
@@ -14765,10 +14936,10 @@ async function adoptOrgKey(orgId, newKey, masterPassword, now) {
|
|
|
14765
14936
|
const touchedRoots = /* @__PURE__ */ new Set();
|
|
14766
14937
|
for (const vaultRoot of await rootsOfOrg(orgId)) {
|
|
14767
14938
|
for (const name of await jsonFilesIn(vaultRoot)) {
|
|
14768
|
-
const path =
|
|
14939
|
+
const path = join24(vaultRoot, name);
|
|
14769
14940
|
let parsed;
|
|
14770
14941
|
try {
|
|
14771
|
-
parsed = JSON.parse(await
|
|
14942
|
+
parsed = JSON.parse(await readFile18(path, "utf-8"));
|
|
14772
14943
|
} catch {
|
|
14773
14944
|
continue;
|
|
14774
14945
|
}
|
|
@@ -14782,22 +14953,22 @@ async function adoptOrgKey(orgId, newKey, masterPassword, now) {
|
|
|
14782
14953
|
const stamp = now.toISOString().replace(/[:.]/g, "-").substring(0, 19);
|
|
14783
14954
|
const backups = [];
|
|
14784
14955
|
for (const vaultRoot of touchedRoots) {
|
|
14785
|
-
const backupDir =
|
|
14786
|
-
await
|
|
14956
|
+
const backupDir = join24(vaultRoot, `backup-key-${stamp}`);
|
|
14957
|
+
await mkdir21(backupDir, { recursive: true });
|
|
14787
14958
|
for (const name of await jsonFilesIn(vaultRoot)) {
|
|
14788
|
-
await copyFile(
|
|
14959
|
+
await copyFile(join24(vaultRoot, name), join24(backupDir, name));
|
|
14789
14960
|
}
|
|
14790
14961
|
for (const name of [".encryption.key.enc", ".runeya-verify"]) {
|
|
14791
|
-
if (await exists(
|
|
14792
|
-
await copyFile(
|
|
14962
|
+
if (await exists(join24(vaultRoot, name))) {
|
|
14963
|
+
await copyFile(join24(vaultRoot, name), join24(backupDir, name));
|
|
14793
14964
|
}
|
|
14794
14965
|
}
|
|
14795
14966
|
backups.push(backupDir);
|
|
14796
14967
|
}
|
|
14797
14968
|
for (const item of pending) {
|
|
14798
14969
|
const tmp = item.path + ".tmp";
|
|
14799
|
-
await
|
|
14800
|
-
await
|
|
14970
|
+
await writeFile17(tmp, item.content, "utf-8");
|
|
14971
|
+
await rename14(tmp, item.path);
|
|
14801
14972
|
}
|
|
14802
14973
|
await installOrgKey(orgId, newKey, masterPassword);
|
|
14803
14974
|
clearVaultLock(orgId);
|
|
@@ -14858,10 +15029,10 @@ var cloudSyncRouter = router({
|
|
|
14858
15029
|
* "open this project" is the whole gesture.
|
|
14859
15030
|
*/
|
|
14860
15031
|
trackProject: protectedProcedure.input(
|
|
14861
|
-
|
|
14862
|
-
orgId:
|
|
14863
|
-
cloudUrl:
|
|
14864
|
-
projectId:
|
|
15032
|
+
z27.object({
|
|
15033
|
+
orgId: z27.string().min(1).max(128),
|
|
15034
|
+
cloudUrl: z27.string().url().max(2048),
|
|
15035
|
+
projectId: z27.string().min(1).max(128)
|
|
14865
15036
|
})
|
|
14866
15037
|
).mutation(async ({ input }) => {
|
|
14867
15038
|
await assertOrgReadable(input.orgId);
|
|
@@ -14895,10 +15066,10 @@ var cloudSyncRouter = router({
|
|
|
14895
15066
|
* fusionné.
|
|
14896
15067
|
*/
|
|
14897
15068
|
publishProject: protectedProcedure.input(
|
|
14898
|
-
|
|
14899
|
-
orgId:
|
|
14900
|
-
cloudUrl:
|
|
14901
|
-
projectId:
|
|
15069
|
+
z27.object({
|
|
15070
|
+
orgId: z27.string().min(1).max(128),
|
|
15071
|
+
cloudUrl: z27.string().url().max(2048),
|
|
15072
|
+
projectId: z27.string().min(1).max(128)
|
|
14902
15073
|
})
|
|
14903
15074
|
).mutation(async ({ input }) => {
|
|
14904
15075
|
const local = await projectStore.get({ id: input.projectId, orgId: null });
|
|
@@ -14939,9 +15110,9 @@ var cloudSyncRouter = router({
|
|
|
14939
15110
|
* publié. Le cloud, lui, ne peut pas répondre — il n'a que du chiffré sous
|
|
14940
15111
|
* les yeux — donc le canari est rapatrié et jugé ici.
|
|
14941
15112
|
*/
|
|
14942
|
-
checkOrgKey: protectedProcedure.input(
|
|
14943
|
-
orgId:
|
|
14944
|
-
keyHex:
|
|
15113
|
+
checkOrgKey: protectedProcedure.input(z27.object({
|
|
15114
|
+
orgId: z27.string().min(1).max(128),
|
|
15115
|
+
keyHex: z27.string().length(64).regex(/^[0-9a-f]+$/i)
|
|
14945
15116
|
})).query(async ({ input }) => {
|
|
14946
15117
|
const res = await cloudFetch2(
|
|
14947
15118
|
`/api/auth/organization/canary?organizationId=${encodeURIComponent(input.orgId)}`,
|
|
@@ -14964,10 +15135,10 @@ var cloudSyncRouter = router({
|
|
|
14964
15135
|
* Bornée au coffre de l'organisation et à ceux de ses projets : les autres
|
|
14965
15136
|
* organisations et la machine gardent leur clé.
|
|
14966
15137
|
*/
|
|
14967
|
-
adoptOrgKey: protectedProcedure.input(
|
|
14968
|
-
orgId:
|
|
14969
|
-
keyHex:
|
|
14970
|
-
masterPassword:
|
|
15138
|
+
adoptOrgKey: protectedProcedure.input(z27.object({
|
|
15139
|
+
orgId: z27.string().min(1).max(128),
|
|
15140
|
+
keyHex: z27.string().length(64).regex(/^[0-9a-f]+$/i),
|
|
15141
|
+
masterPassword: z27.string().min(1).max(1024)
|
|
14971
15142
|
})).mutation(async ({ input }) => {
|
|
14972
15143
|
const report = await adoptOrgKey(
|
|
14973
15144
|
input.orgId,
|
|
@@ -14991,7 +15162,7 @@ var cloudSyncRouter = router({
|
|
|
14991
15162
|
* Elle ne re-chiffre rien : ce qui a déjà été synchronisé sous l'ancienne clé
|
|
14992
15163
|
* reste illisible. L'interface le dit avant de la déclencher.
|
|
14993
15164
|
*/
|
|
14994
|
-
resetOrgKey: protectedProcedure.input(
|
|
15165
|
+
resetOrgKey: protectedProcedure.input(z27.object({ orgId: z27.string().min(1).max(128) })).mutation(async ({ input }) => {
|
|
14995
15166
|
const canary = await readVerifyFile(await keyRoot());
|
|
14996
15167
|
if (!canary) {
|
|
14997
15168
|
throw new TRPCError22({
|
|
@@ -15021,9 +15192,9 @@ var cloudSyncRouter = router({
|
|
|
15021
15192
|
* every other member and for this one on another machine.
|
|
15022
15193
|
*/
|
|
15023
15194
|
untrackProject: protectedProcedure.input(
|
|
15024
|
-
|
|
15025
|
-
orgId:
|
|
15026
|
-
projectId:
|
|
15195
|
+
z27.object({
|
|
15196
|
+
orgId: z27.string().min(1).max(128),
|
|
15197
|
+
projectId: z27.string().min(1).max(128)
|
|
15027
15198
|
})
|
|
15028
15199
|
).mutation(async ({ input }) => {
|
|
15029
15200
|
await cloudSyncBridge.unfollowProject(input.orgId, input.projectId);
|
|
@@ -15039,9 +15210,9 @@ var cloudSyncRouter = router({
|
|
|
15039
15210
|
* membre, ce qui évite d'effacer les fichiers si le cloud a refusé l'ordre.
|
|
15040
15211
|
*/
|
|
15041
15212
|
deleteProjectFromOrg: protectedProcedure.input(
|
|
15042
|
-
|
|
15043
|
-
orgId:
|
|
15044
|
-
projectId:
|
|
15213
|
+
z27.object({
|
|
15214
|
+
orgId: z27.string().min(1).max(128),
|
|
15215
|
+
projectId: z27.string().min(1).max(128)
|
|
15045
15216
|
})
|
|
15046
15217
|
).mutation(async ({ input }) => {
|
|
15047
15218
|
let res;
|
|
@@ -15085,10 +15256,10 @@ var cloudSyncRouter = router({
|
|
|
15085
15256
|
* afficher. Le nom est donc recopié dans le tampon du coffre au passage, là
|
|
15086
15257
|
* où il est déjà lu au démarrage suivant.
|
|
15087
15258
|
*/
|
|
15088
|
-
rememberOrgNames: protectedProcedure.input(
|
|
15089
|
-
orgs:
|
|
15090
|
-
orgId:
|
|
15091
|
-
name:
|
|
15259
|
+
rememberOrgNames: protectedProcedure.input(z27.object({
|
|
15260
|
+
orgs: z27.array(z27.object({
|
|
15261
|
+
orgId: z27.string().min(1).max(128),
|
|
15262
|
+
name: z27.string().min(1).max(100)
|
|
15092
15263
|
})).max(200)
|
|
15093
15264
|
})).mutation(async ({ input }) => {
|
|
15094
15265
|
for (const { orgId, name } of input.orgs) await rememberOrgName(orgId, name);
|
|
@@ -15124,13 +15295,13 @@ var cloudSyncRouter = router({
|
|
|
15124
15295
|
// ../server/src/trpc/routers/filesystem.ts
|
|
15125
15296
|
import { readdir as readdir8, stat as stat8 } from "fs/promises";
|
|
15126
15297
|
import { homedir as homedir5 } from "os";
|
|
15127
|
-
import { isAbsolute as isAbsolute4, join as
|
|
15128
|
-
import { z as
|
|
15298
|
+
import { isAbsolute as isAbsolute4, join as join25, resolve as resolve5, dirname as dirname10, basename as basename2 } from "path";
|
|
15299
|
+
import { z as z28 } from "zod";
|
|
15129
15300
|
var MAX_ENTRIES2 = 500;
|
|
15130
|
-
var PATH_SCHEMA =
|
|
15301
|
+
var PATH_SCHEMA = z28.string().min(1).max(4096);
|
|
15131
15302
|
function safeResolve(input) {
|
|
15132
15303
|
if (input.includes("\0")) throw new Error("Chemin invalide");
|
|
15133
|
-
const expanded = input.startsWith("~") ?
|
|
15304
|
+
const expanded = input.startsWith("~") ? join25(homedir5(), input.slice(1)) : input;
|
|
15134
15305
|
if (!isAbsolute4(expanded)) throw new Error("Le chemin doit \xEAtre absolu");
|
|
15135
15306
|
return resolve5(expanded);
|
|
15136
15307
|
}
|
|
@@ -15151,7 +15322,7 @@ var filesystemRouter = router({
|
|
|
15151
15322
|
* Hidden entries are skipped: they are noise for choosing a workspace, and
|
|
15152
15323
|
* `.runeya` itself would invite placing a project inside another's data.
|
|
15153
15324
|
*/
|
|
15154
|
-
listDirectories: protectedProcedure.input(
|
|
15325
|
+
listDirectories: protectedProcedure.input(z28.object({ path: PATH_SCHEMA })).query(async ({ input }) => {
|
|
15155
15326
|
const dir = safeResolve(input.path);
|
|
15156
15327
|
const info = await stat8(dir).catch(() => null);
|
|
15157
15328
|
if (!info?.isDirectory()) {
|
|
@@ -15166,7 +15337,7 @@ var filesystemRouter = router({
|
|
|
15166
15337
|
const truncated = names.length > MAX_ENTRIES2;
|
|
15167
15338
|
const entries2 = [];
|
|
15168
15339
|
for (const name of names.slice(0, MAX_ENTRIES2)) {
|
|
15169
|
-
const path =
|
|
15340
|
+
const path = join25(dir, name);
|
|
15170
15341
|
entries2.push({ name, path, hasRuneyaProject: await holdsRuneyaProject(path) });
|
|
15171
15342
|
}
|
|
15172
15343
|
return {
|
|
@@ -15185,10 +15356,10 @@ var filesystemRouter = router({
|
|
|
15185
15356
|
* Two projects in one directory is what makes services run against the wrong
|
|
15186
15357
|
* code, so a directory that already holds one is refused outright.
|
|
15187
15358
|
*/
|
|
15188
|
-
checkProjectTarget: protectedProcedure.input(
|
|
15359
|
+
checkProjectTarget: protectedProcedure.input(z28.object({
|
|
15189
15360
|
path: PATH_SCHEMA,
|
|
15190
|
-
projectId:
|
|
15191
|
-
orgId:
|
|
15361
|
+
projectId: z28.string().min(1).max(128),
|
|
15362
|
+
orgId: z28.string().max(128).nullable().optional()
|
|
15192
15363
|
})).query(async ({ input }) => {
|
|
15193
15364
|
const dir = safeResolve(input.path);
|
|
15194
15365
|
const info = await stat8(dir).catch(() => null);
|
|
@@ -15298,8 +15469,8 @@ async function ensureFilePermissions() {
|
|
|
15298
15469
|
}
|
|
15299
15470
|
|
|
15300
15471
|
// ../server/src/services/vault-migration.ts
|
|
15301
|
-
import { readdir as readdir9, readFile as
|
|
15302
|
-
import { join as
|
|
15472
|
+
import { readdir as readdir9, readFile as readFile19, writeFile as writeFile18, mkdir as mkdir22, copyFile as copyFile2, unlink as unlink5, rename as rename15, stat as stat10 } from "fs/promises";
|
|
15473
|
+
import { join as join26 } from "path";
|
|
15303
15474
|
var KEY_FILES = [".encryption.key.enc", ".runeya-verify"];
|
|
15304
15475
|
var MACHINE_FILES = [
|
|
15305
15476
|
"agents.json",
|
|
@@ -15329,17 +15500,17 @@ async function openLegacyVault(legacyRoot, masterPassword) {
|
|
|
15329
15500
|
}
|
|
15330
15501
|
async function migrateLegacyVault(legacyRoot, machineRootDir, legacyKey, machineKey, now) {
|
|
15331
15502
|
const stamp = now.toISOString().replace(/[:.]/g, "-").substring(0, 19);
|
|
15332
|
-
const backupDir =
|
|
15333
|
-
await
|
|
15503
|
+
const backupDir = join26(legacyRoot, `backup-${stamp}`);
|
|
15504
|
+
await mkdir22(backupDir, { recursive: true });
|
|
15334
15505
|
const jsonFiles = await vaultJsonFiles(legacyRoot);
|
|
15335
15506
|
for (const name of [...jsonFiles, ...KEY_FILES]) {
|
|
15336
|
-
if (await exists2(
|
|
15337
|
-
await copyFile2(
|
|
15507
|
+
if (await exists2(join26(legacyRoot, name))) {
|
|
15508
|
+
await copyFile2(join26(legacyRoot, name), join26(backupDir, name));
|
|
15338
15509
|
}
|
|
15339
15510
|
}
|
|
15340
15511
|
const rekeyed = [];
|
|
15341
15512
|
for (const name of jsonFiles) {
|
|
15342
|
-
const raw = await
|
|
15513
|
+
const raw = await readFile19(join26(legacyRoot, name), "utf-8");
|
|
15343
15514
|
let parsed;
|
|
15344
15515
|
try {
|
|
15345
15516
|
parsed = JSON.parse(raw);
|
|
@@ -15349,13 +15520,13 @@ async function migrateLegacyVault(legacyRoot, machineRootDir, legacyKey, machine
|
|
|
15349
15520
|
const counter = { n: 0 };
|
|
15350
15521
|
const converted = rekeyValue(parsed, legacyKey, machineKey, counter);
|
|
15351
15522
|
if (counter.n === 0) continue;
|
|
15352
|
-
const tmp =
|
|
15353
|
-
await
|
|
15354
|
-
await
|
|
15523
|
+
const tmp = join26(legacyRoot, `${name}.tmp`);
|
|
15524
|
+
await writeFile18(tmp, JSON.stringify(converted, null, 2), "utf-8");
|
|
15525
|
+
await rename15(tmp, join26(legacyRoot, name));
|
|
15355
15526
|
rekeyed.push({ file: name, values: counter.n });
|
|
15356
15527
|
}
|
|
15357
15528
|
for (const { file, values } of rekeyed) {
|
|
15358
|
-
const parsed = JSON.parse(await
|
|
15529
|
+
const parsed = JSON.parse(await readFile19(join26(legacyRoot, file), "utf-8"));
|
|
15359
15530
|
const check = { n: 0 };
|
|
15360
15531
|
rekeyValue(parsed, machineKey, machineKey, check);
|
|
15361
15532
|
if (check.n !== values) {
|
|
@@ -15364,13 +15535,13 @@ async function migrateLegacyVault(legacyRoot, machineRootDir, legacyKey, machine
|
|
|
15364
15535
|
);
|
|
15365
15536
|
}
|
|
15366
15537
|
}
|
|
15367
|
-
await
|
|
15538
|
+
await mkdir22(machineRootDir, { recursive: true });
|
|
15368
15539
|
const moved = [];
|
|
15369
15540
|
const skipped = [];
|
|
15370
15541
|
for (const name of MACHINE_FILES) {
|
|
15371
|
-
const from =
|
|
15542
|
+
const from = join26(legacyRoot, name);
|
|
15372
15543
|
if (!await exists2(from)) continue;
|
|
15373
|
-
const to =
|
|
15544
|
+
const to = join26(machineRootDir, name);
|
|
15374
15545
|
if (await exists2(to)) {
|
|
15375
15546
|
skipped.push(name);
|
|
15376
15547
|
continue;
|
|
@@ -15380,15 +15551,15 @@ async function migrateLegacyVault(legacyRoot, machineRootDir, legacyKey, machine
|
|
|
15380
15551
|
moved.push(name);
|
|
15381
15552
|
}
|
|
15382
15553
|
for (const name of KEY_FILES) {
|
|
15383
|
-
const path =
|
|
15554
|
+
const path = join26(legacyRoot, name);
|
|
15384
15555
|
if (await exists2(path)) await unlink5(path);
|
|
15385
15556
|
}
|
|
15386
15557
|
return { backupDir, rekeyed, moved, skipped };
|
|
15387
15558
|
}
|
|
15388
15559
|
|
|
15389
15560
|
// ../server/src/services/settings-migration.ts
|
|
15390
|
-
import { readFile as
|
|
15391
|
-
import { join as
|
|
15561
|
+
import { readFile as readFile20, writeFile as writeFile19, rename as rename16, unlink as unlink6, mkdir as mkdir23, chmod as chmod12, stat as stat11 } from "fs/promises";
|
|
15562
|
+
import { join as join27 } from "path";
|
|
15392
15563
|
var SETTINGS_FILE2 = "settings.json";
|
|
15393
15564
|
var SETTINGS_PRIVATE_FILE2 = "settings.private.json";
|
|
15394
15565
|
async function exists3(path) {
|
|
@@ -15401,12 +15572,12 @@ async function legacySource(filename) {
|
|
|
15401
15572
|
return null;
|
|
15402
15573
|
}
|
|
15403
15574
|
async function moveInto(root, filename, from) {
|
|
15404
|
-
await
|
|
15405
|
-
const to =
|
|
15406
|
-
const contents = await
|
|
15575
|
+
await mkdir23(root, { recursive: true });
|
|
15576
|
+
const to = join27(root, filename);
|
|
15577
|
+
const contents = await readFile20(from, "utf-8");
|
|
15407
15578
|
const tmp = to + ".tmp";
|
|
15408
|
-
await
|
|
15409
|
-
await
|
|
15579
|
+
await writeFile19(tmp, contents, "utf-8");
|
|
15580
|
+
await rename16(tmp, to);
|
|
15410
15581
|
await chmod12(to, 384);
|
|
15411
15582
|
await unlink6(from);
|
|
15412
15583
|
}
|
|
@@ -15427,7 +15598,7 @@ async function migrateSettingsIntoVaults() {
|
|
|
15427
15598
|
const orgId = orgs[0];
|
|
15428
15599
|
const root = orgVaultRoot(orgId);
|
|
15429
15600
|
for (const { filename, from } of sources) {
|
|
15430
|
-
if (await exists3(
|
|
15601
|
+
if (await exists3(join27(root, filename))) continue;
|
|
15431
15602
|
await moveInto(root, filename, from);
|
|
15432
15603
|
report.files.push(filename);
|
|
15433
15604
|
}
|
|
@@ -15441,16 +15612,16 @@ async function migrateSettingsIntoVaults() {
|
|
|
15441
15612
|
// ../server/src/migrations/migrate-from-legacy.ts
|
|
15442
15613
|
import { createRequire as createRequire2 } from "module";
|
|
15443
15614
|
import { randomBytes as randomBytes6, createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3 } from "crypto";
|
|
15444
|
-
import { randomUUID as
|
|
15615
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
15445
15616
|
import {
|
|
15446
|
-
readFile as
|
|
15447
|
-
writeFile as
|
|
15448
|
-
rename as
|
|
15449
|
-
mkdir as
|
|
15617
|
+
readFile as readFile21,
|
|
15618
|
+
writeFile as writeFile20,
|
|
15619
|
+
rename as rename17,
|
|
15620
|
+
mkdir as mkdir24,
|
|
15450
15621
|
access as access3,
|
|
15451
15622
|
readdir as readdir10
|
|
15452
15623
|
} from "fs/promises";
|
|
15453
|
-
import { join as
|
|
15624
|
+
import { join as join28, dirname as dirname11 } from "path";
|
|
15454
15625
|
var _require = createRequire2(import.meta.url);
|
|
15455
15626
|
var PARSER_ID_MAP = {
|
|
15456
15627
|
"stack-monitor-parser-jsons": "native:json",
|
|
@@ -15559,7 +15730,7 @@ async function getSodium() {
|
|
|
15559
15730
|
return _sodium;
|
|
15560
15731
|
}
|
|
15561
15732
|
async function decryptLegacyFile(filePath, key, sodium) {
|
|
15562
|
-
const raw = (await
|
|
15733
|
+
const raw = (await readFile21(filePath, "utf-8")).trim();
|
|
15563
15734
|
if (!raw || raw === "[]" || raw === "{}") {
|
|
15564
15735
|
try {
|
|
15565
15736
|
return JSON.parse(raw);
|
|
@@ -15579,12 +15750,12 @@ async function decryptLegacyFile(filePath, key, sodium) {
|
|
|
15579
15750
|
}
|
|
15580
15751
|
async function atomicWrite(path, data) {
|
|
15581
15752
|
const tmp = path + ".tmp";
|
|
15582
|
-
await
|
|
15583
|
-
await
|
|
15753
|
+
await writeFile20(tmp, JSON.stringify(data, null, 2), "utf-8");
|
|
15754
|
+
await rename17(tmp, path);
|
|
15584
15755
|
}
|
|
15585
15756
|
async function runLegacyMigration(dataDir) {
|
|
15586
15757
|
const legacyRoot = env.DATA_DIR;
|
|
15587
|
-
const legacyKeyPath =
|
|
15758
|
+
const legacyKeyPath = join28(legacyRoot, "dbs", "encryption-key.json");
|
|
15588
15759
|
try {
|
|
15589
15760
|
await access3(legacyKeyPath);
|
|
15590
15761
|
} catch {
|
|
@@ -15592,20 +15763,20 @@ async function runLegacyMigration(dataDir) {
|
|
|
15592
15763
|
}
|
|
15593
15764
|
console.log("[legacy-migration] Legacy Runeya data detected, starting migration\u2026");
|
|
15594
15765
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").substring(0, 19);
|
|
15595
|
-
const legacyTmp =
|
|
15596
|
-
await
|
|
15597
|
-
await
|
|
15598
|
-
const legacyOld =
|
|
15599
|
-
await
|
|
15766
|
+
const legacyTmp = join28(abCwd, ".runeya-tmp");
|
|
15767
|
+
await rename17(legacyRoot, legacyTmp);
|
|
15768
|
+
await mkdir24(dataDir, { recursive: true });
|
|
15769
|
+
const legacyOld = join28(dataDir, `backup-${timestamp}`);
|
|
15770
|
+
await rename17(legacyTmp, legacyOld);
|
|
15600
15771
|
console.log(`[legacy-migration] Legacy data backed up to ${legacyOld}`);
|
|
15601
|
-
const keyJson = JSON.parse(await
|
|
15772
|
+
const keyJson = JSON.parse(await readFile21(join28(legacyOld, "dbs", "encryption-key.json"), "utf-8"));
|
|
15602
15773
|
const sodium = await getSodium();
|
|
15603
15774
|
const sodiumKey = sodium.from_base64(keyJson.encryptionKey);
|
|
15604
15775
|
const keyBuffer = Buffer.from(sodiumKey);
|
|
15605
15776
|
const runyeaKeyHex = keyBuffer.toString("hex");
|
|
15606
15777
|
await setEncryptionKey(runyeaKeyHex);
|
|
15607
15778
|
console.log("[legacy-migration] Encryption key loaded in memory (temporary)");
|
|
15608
|
-
const dbsDir =
|
|
15779
|
+
const dbsDir = join28(legacyOld, "dbs");
|
|
15609
15780
|
async function readEncrypted(filePath) {
|
|
15610
15781
|
try {
|
|
15611
15782
|
return await decryptLegacyFile(filePath, sodiumKey, sodium);
|
|
@@ -15614,29 +15785,29 @@ async function runLegacyMigration(dataDir) {
|
|
|
15614
15785
|
return null;
|
|
15615
15786
|
}
|
|
15616
15787
|
}
|
|
15617
|
-
const envsDir =
|
|
15788
|
+
const envsDir = join28(dbsDir, "envs");
|
|
15618
15789
|
const envFiles = (await readdir10(envsDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
|
|
15619
15790
|
const legacyEnvs = {};
|
|
15620
15791
|
for (const file of envFiles) {
|
|
15621
15792
|
const name = file.replace(".encrypted.json", "");
|
|
15622
|
-
legacyEnvs[name] = await readEncrypted(
|
|
15793
|
+
legacyEnvs[name] = await readEncrypted(join28(envsDir, file));
|
|
15623
15794
|
}
|
|
15624
|
-
const servicesDir =
|
|
15795
|
+
const servicesDir = join28(dbsDir, "services");
|
|
15625
15796
|
const serviceFiles = (await readdir10(servicesDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
|
|
15626
15797
|
const legacyServices = {};
|
|
15627
15798
|
for (const file of serviceFiles) {
|
|
15628
15799
|
const name = file.replace(".encrypted.json", "");
|
|
15629
15800
|
if (!name) continue;
|
|
15630
|
-
const data = await readEncrypted(
|
|
15801
|
+
const data = await readEncrypted(join28(servicesDir, file));
|
|
15631
15802
|
if (data?.label) legacyServices[name] = data;
|
|
15632
15803
|
}
|
|
15633
|
-
const overridesDir =
|
|
15804
|
+
const overridesDir = join28(dbsDir, "overrides");
|
|
15634
15805
|
const overrideFiles = (await readdir10(overridesDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
|
|
15635
15806
|
const legacyServiceOverrides = {};
|
|
15636
15807
|
const legacyEnvOverrides = {};
|
|
15637
15808
|
for (const file of overrideFiles) {
|
|
15638
15809
|
const baseName = file.replace(".encrypted.json", "");
|
|
15639
|
-
const data = await readEncrypted(
|
|
15810
|
+
const data = await readEncrypted(join28(overridesDir, file));
|
|
15640
15811
|
if (!data) continue;
|
|
15641
15812
|
if (baseName.endsWith("-envs")) {
|
|
15642
15813
|
legacyServiceOverrides[baseName.slice(0, -5)] = data;
|
|
@@ -15644,18 +15815,18 @@ async function runLegacyMigration(dataDir) {
|
|
|
15644
15815
|
legacyEnvOverrides[baseName.slice(0, -12)] = data;
|
|
15645
15816
|
}
|
|
15646
15817
|
}
|
|
15647
|
-
const parsersDir =
|
|
15818
|
+
const parsersDir = join28(dbsDir, "parsers");
|
|
15648
15819
|
const parserFiles = (await readdir10(parsersDir).catch(() => [])).filter((f) => f.endsWith(".encrypted.json"));
|
|
15649
15820
|
const legacyParsers = [];
|
|
15650
15821
|
for (const file of parserFiles) {
|
|
15651
|
-
const data = await readEncrypted(
|
|
15822
|
+
const data = await readEncrypted(join28(parsersDir, file));
|
|
15652
15823
|
if (data?.id) legacyParsers.push(data);
|
|
15653
15824
|
}
|
|
15654
|
-
const projectMonoId =
|
|
15825
|
+
const projectMonoId = randomUUID11();
|
|
15655
15826
|
const envIdMap = {};
|
|
15656
15827
|
const labelToKey = {};
|
|
15657
15828
|
for (const [name, legacyEnv] of Object.entries(legacyEnvs)) {
|
|
15658
|
-
envIdMap[name] =
|
|
15829
|
+
envIdMap[name] = randomUUID11();
|
|
15659
15830
|
if (legacyEnv?.label) labelToKey[legacyEnv.label] = name;
|
|
15660
15831
|
}
|
|
15661
15832
|
const runeEnvs = [];
|
|
@@ -15680,7 +15851,7 @@ async function runLegacyMigration(dataDir) {
|
|
|
15680
15851
|
if (hasInvalidInterpolation(value)) continue;
|
|
15681
15852
|
const cleaned = cleanVarKey(key);
|
|
15682
15853
|
if (inheritedVars[cleaned] === value) continue;
|
|
15683
|
-
const varId =
|
|
15854
|
+
const varId = randomUUID11();
|
|
15684
15855
|
variables[varId] = makeVariable(cleaned, value);
|
|
15685
15856
|
varIdLookup.set(`${envIdMap[name]}:${cleaned}`, varId);
|
|
15686
15857
|
}
|
|
@@ -15701,7 +15872,7 @@ async function runLegacyMigration(dataDir) {
|
|
|
15701
15872
|
const serviceIdMap = {};
|
|
15702
15873
|
const runeServices = [];
|
|
15703
15874
|
for (const [name, legacy] of Object.entries(legacyServices)) {
|
|
15704
|
-
const id =
|
|
15875
|
+
const id = randomUUID11();
|
|
15705
15876
|
serviceIdMap[name] = id;
|
|
15706
15877
|
const rootPath = legacy.rootPath || "";
|
|
15707
15878
|
const rootPathCwd = rootPath && rootPath !== "." ? rootPath : "";
|
|
@@ -15710,7 +15881,7 @@ async function runLegacyMigration(dataDir) {
|
|
|
15710
15881
|
const parts = [cmd.spawnCmd, ...cmd.spawnArgs || []].filter(Boolean);
|
|
15711
15882
|
if (!parts.length) continue;
|
|
15712
15883
|
commands.push({
|
|
15713
|
-
id: cmd.id ||
|
|
15884
|
+
id: cmd.id || randomUUID11(),
|
|
15714
15885
|
label: "Launch",
|
|
15715
15886
|
command: parts.join(" "),
|
|
15716
15887
|
cwd: cmd.spawnOptions?.cwd || "",
|
|
@@ -15771,7 +15942,7 @@ async function runLegacyMigration(dataDir) {
|
|
|
15771
15942
|
const legacyBootstrapCmds = container.bootstrap?.commands || [];
|
|
15772
15943
|
if (legacyBootstrapCmds.length > 0) {
|
|
15773
15944
|
dockerConfig.bootstrapCommands = legacyBootstrapCmds.filter((bs) => bs.cmd || bs.entrypoint).map((bs, idx) => ({
|
|
15774
|
-
id: bs.id ||
|
|
15945
|
+
id: bs.id || randomUUID11(),
|
|
15775
15946
|
label: bs.label || `Bootstrap ${idx + 1}`,
|
|
15776
15947
|
command: bs.cmd || "",
|
|
15777
15948
|
...bs.entrypoint ? { entrypoint: bs.entrypoint } : {},
|
|
@@ -15819,7 +15990,7 @@ async function runLegacyMigration(dataDir) {
|
|
|
15819
15990
|
cwd: serviceCwd,
|
|
15820
15991
|
runner: dockerConfig ? "docker" : "native",
|
|
15821
15992
|
shortcuts: (legacy.shortcuts || []).filter((s) => s.spawnCmd || s.label).map((s) => ({
|
|
15822
|
-
id: s.id ||
|
|
15993
|
+
id: s.id || randomUUID11(),
|
|
15823
15994
|
label: s.label || s.spawnCmd || "",
|
|
15824
15995
|
command: [s.spawnCmd, ...s.spawnArgs || []].filter(Boolean).join(" "),
|
|
15825
15996
|
...s.spawnOptions?.cwd ? { cwd: s.spawnOptions.cwd } : {}
|
|
@@ -15859,7 +16030,7 @@ async function runLegacyMigration(dataDir) {
|
|
|
15859
16030
|
);
|
|
15860
16031
|
if (!svcScopedEnv) {
|
|
15861
16032
|
svcScopedEnv = {
|
|
15862
|
-
id:
|
|
16033
|
+
id: randomUUID11(),
|
|
15863
16034
|
projectId: projectMonoId,
|
|
15864
16035
|
name: `${service?.name || name} (${globalEnv.name})`,
|
|
15865
16036
|
scope: "service",
|
|
@@ -15883,7 +16054,7 @@ async function runLegacyMigration(dataDir) {
|
|
|
15883
16054
|
const varPost = typeof varData === "object" ? String(varData.suffix ?? "") : "";
|
|
15884
16055
|
if (!varKey || existingKeys.has(cleanVarKey(varKey))) continue;
|
|
15885
16056
|
const cleaned = cleanVarKey(varKey);
|
|
15886
|
-
const varId =
|
|
16057
|
+
const varId = randomUUID11();
|
|
15887
16058
|
svcScopedEnv.variables[varId] = makeVariable(cleaned, varValue, varPre, varPost);
|
|
15888
16059
|
existingKeys.add(cleaned);
|
|
15889
16060
|
}
|
|
@@ -15903,7 +16074,7 @@ async function runLegacyMigration(dataDir) {
|
|
|
15903
16074
|
);
|
|
15904
16075
|
if (!svcScopedEnv) {
|
|
15905
16076
|
svcScopedEnv = {
|
|
15906
|
-
id:
|
|
16077
|
+
id: randomUUID11(),
|
|
15907
16078
|
projectId: projectMonoId,
|
|
15908
16079
|
name: `${service?.name || serviceName} (${globalEnv.name})`,
|
|
15909
16080
|
scope: "service",
|
|
@@ -15924,7 +16095,7 @@ async function runLegacyMigration(dataDir) {
|
|
|
15924
16095
|
const baseEntry = Object.entries(svcScopedEnv.variables).find(([, v]) => v.key === cleaned);
|
|
15925
16096
|
let varId = baseEntry?.[0];
|
|
15926
16097
|
if (!varId) {
|
|
15927
|
-
varId =
|
|
16098
|
+
varId = randomUUID11();
|
|
15928
16099
|
svcScopedEnv.variables[varId] = {
|
|
15929
16100
|
key: cleaned,
|
|
15930
16101
|
value: { value: "", pre: "", post: "", isSecret: false, injectIntoAi: false }
|
|
@@ -15954,13 +16125,13 @@ async function runLegacyMigration(dataDir) {
|
|
|
15954
16125
|
flatOverrides[varId] = makeVariable(cleaned, value);
|
|
15955
16126
|
}
|
|
15956
16127
|
} else {
|
|
15957
|
-
flatOverrides[
|
|
16128
|
+
flatOverrides[randomUUID11()] = makeVariable(cleaned, value);
|
|
15958
16129
|
}
|
|
15959
16130
|
} else {
|
|
15960
16131
|
const cleaned = cleanVarKey(key);
|
|
15961
16132
|
const existingVarId = Object.entries(env2.variables).find(([, v]) => v.key === cleaned)?.[0];
|
|
15962
16133
|
if (!existingVarId) {
|
|
15963
|
-
const varId =
|
|
16134
|
+
const varId = randomUUID11();
|
|
15964
16135
|
env2.variables[varId] = makeVariable(cleaned, value);
|
|
15965
16136
|
varIdLookup.set(`${envId}:${cleaned}`, varId);
|
|
15966
16137
|
}
|
|
@@ -15989,7 +16160,7 @@ async function runLegacyMigration(dataDir) {
|
|
|
15989
16160
|
}
|
|
15990
16161
|
let existingSettings = {};
|
|
15991
16162
|
try {
|
|
15992
|
-
existingSettings = JSON.parse(await
|
|
16163
|
+
existingSettings = JSON.parse(await readFile21(join28(dataDir, "settings.json"), "utf-8"));
|
|
15993
16164
|
} catch {
|
|
15994
16165
|
}
|
|
15995
16166
|
const migratedParsers = legacyParsers.map((p) => ({
|
|
@@ -16010,11 +16181,11 @@ ${p.transform ?? ""}`,
|
|
|
16010
16181
|
...migratedParsers
|
|
16011
16182
|
]
|
|
16012
16183
|
};
|
|
16013
|
-
await atomicWrite(
|
|
16014
|
-
await atomicWrite(
|
|
16015
|
-
await atomicWrite(
|
|
16016
|
-
await atomicWrite(
|
|
16017
|
-
await atomicWrite(
|
|
16184
|
+
await atomicWrite(join28(dataDir, "projects.json"), runeProjects);
|
|
16185
|
+
await atomicWrite(join28(dataDir, "services.json"), runeServices);
|
|
16186
|
+
await atomicWrite(join28(dataDir, "environments.json"), runeEnvs);
|
|
16187
|
+
await atomicWrite(join28(dataDir, "environment-overrides.json"), flatOverrides);
|
|
16188
|
+
await atomicWrite(join28(dataDir, "settings.json"), newSettings);
|
|
16018
16189
|
const svcEnvCount = runeEnvs.filter((e) => e.scope === "service").length;
|
|
16019
16190
|
console.log(`[legacy-migration] Written: ${runeProjects.length} projects, ${runeServices.length} services, ${runeEnvs.length} environments (${svcEnvCount} service-scoped)`);
|
|
16020
16191
|
console.log(`[legacy-migration] Overrides: ${Object.keys(flatOverrides).length}, custom parsers: ${migratedParsers.length} (all disabled \u2014 rewrite required)`);
|
|
@@ -16028,9 +16199,9 @@ async function findLegacyKeyInBackup(dataDir) {
|
|
|
16028
16199
|
const entries2 = await readdir10(dataDir);
|
|
16029
16200
|
const backupDirs = entries2.filter((e) => e.startsWith("backup-")).sort((a, b) => a < b ? -1 : a > b ? 1 : 0).reverse();
|
|
16030
16201
|
for (const dir of backupDirs) {
|
|
16031
|
-
const keyJsonPath =
|
|
16202
|
+
const keyJsonPath = join28(dataDir, dir, "dbs", "encryption-key.json");
|
|
16032
16203
|
try {
|
|
16033
|
-
const raw = await
|
|
16204
|
+
const raw = await readFile21(keyJsonPath, "utf-8");
|
|
16034
16205
|
const parsed = JSON.parse(raw);
|
|
16035
16206
|
if (!parsed.encryptionKey) continue;
|
|
16036
16207
|
const sodium = await getSodium();
|
|
@@ -16051,8 +16222,8 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
16051
16222
|
const { resolve: resolve7 } = await import("path");
|
|
16052
16223
|
const abDataDir = resolve7(dataDir);
|
|
16053
16224
|
const candidateDirs = [
|
|
16054
|
-
|
|
16055
|
-
|
|
16225
|
+
join28(dirname11(env.DATA_DIR), ".runeya", "dbs", "overrides"),
|
|
16226
|
+
join28(abDataDir, "dbs", "overrides")
|
|
16056
16227
|
];
|
|
16057
16228
|
let overridesDir = null;
|
|
16058
16229
|
let overrideFiles = [];
|
|
@@ -16068,7 +16239,7 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
16068
16239
|
}
|
|
16069
16240
|
}
|
|
16070
16241
|
if (!overridesDir || overrideFiles.length === 0) return false;
|
|
16071
|
-
const legacyKeyPath =
|
|
16242
|
+
const legacyKeyPath = join28(overridesDir, "..", "encryption-key.json");
|
|
16072
16243
|
try {
|
|
16073
16244
|
await access3(legacyKeyPath);
|
|
16074
16245
|
return false;
|
|
@@ -16086,7 +16257,7 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
16086
16257
|
const envNameToId = {};
|
|
16087
16258
|
let envsRaw;
|
|
16088
16259
|
try {
|
|
16089
|
-
envsRaw = JSON.parse(await
|
|
16260
|
+
envsRaw = JSON.parse(await readFile21(join28(abDataDir, "environments.json"), "utf-8"));
|
|
16090
16261
|
for (const _env of envsRaw) {
|
|
16091
16262
|
const env2 = _env;
|
|
16092
16263
|
if (env2["name"] && env2["id"]) {
|
|
@@ -16105,7 +16276,7 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
16105
16276
|
let servicesRaw = [];
|
|
16106
16277
|
const serviceNameToId = {};
|
|
16107
16278
|
try {
|
|
16108
|
-
servicesRaw = JSON.parse(await
|
|
16279
|
+
servicesRaw = JSON.parse(await readFile21(join28(abDataDir, "services.json"), "utf-8"));
|
|
16109
16280
|
for (const _svc of servicesRaw) {
|
|
16110
16281
|
const svc = _svc;
|
|
16111
16282
|
if (svc["name"] && svc["id"]) serviceNameToId[svc["name"]] = svc["id"];
|
|
@@ -16122,7 +16293,7 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
16122
16293
|
const envName = baseName.slice(0, -"-environment".length);
|
|
16123
16294
|
let data;
|
|
16124
16295
|
try {
|
|
16125
|
-
data = await decryptLegacyFile(
|
|
16296
|
+
data = await decryptLegacyFile(join28(overridesDir, file), sodiumKey, sodium);
|
|
16126
16297
|
} catch (err) {
|
|
16127
16298
|
console.warn(`[override-migration] Failed to decrypt ${file}: ${err.message}`);
|
|
16128
16299
|
continue;
|
|
@@ -16144,12 +16315,12 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
16144
16315
|
if (isSameAsBase(value, baseVar)) continue;
|
|
16145
16316
|
flatOverrides[varId] = makeVariable(cleaned, value);
|
|
16146
16317
|
} else {
|
|
16147
|
-
flatOverrides[
|
|
16318
|
+
flatOverrides[randomUUID11()] = makeVariable(cleaned, value);
|
|
16148
16319
|
}
|
|
16149
16320
|
}
|
|
16150
16321
|
}
|
|
16151
16322
|
if (Object.keys(flatOverrides).length > 0) {
|
|
16152
|
-
await atomicWrite(
|
|
16323
|
+
await atomicWrite(join28(abDataDir, "environment-overrides.json"), flatOverrides);
|
|
16153
16324
|
console.log(`[override-migration] Written ${Object.keys(flatOverrides).length} override(s) to environment-overrides.json`);
|
|
16154
16325
|
}
|
|
16155
16326
|
let envsModified = false;
|
|
@@ -16159,7 +16330,7 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
16159
16330
|
const serviceName = baseName.slice(0, -"-envs".length);
|
|
16160
16331
|
let data;
|
|
16161
16332
|
try {
|
|
16162
|
-
data = await decryptLegacyFile(
|
|
16333
|
+
data = await decryptLegacyFile(join28(overridesDir, file), sodiumKey, sodium);
|
|
16163
16334
|
} catch (err) {
|
|
16164
16335
|
console.warn(`[override-migration] Failed to decrypt ${file}: ${err.message}`);
|
|
16165
16336
|
continue;
|
|
@@ -16181,7 +16352,7 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
16181
16352
|
);
|
|
16182
16353
|
if (!svcScopedEnv) {
|
|
16183
16354
|
svcScopedEnv = {
|
|
16184
|
-
id:
|
|
16355
|
+
id: randomUUID11(),
|
|
16185
16356
|
projectId: globalEnv["projectId"],
|
|
16186
16357
|
name: `${service?.["name"] || serviceName} (${globalEnv["name"]})`,
|
|
16187
16358
|
scope: "service",
|
|
@@ -16203,7 +16374,7 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
16203
16374
|
const baseEntry = Object.entries(svcScopedEnv["variables"]).find(([, v]) => v.key === cleaned);
|
|
16204
16375
|
let varId = baseEntry?.[0];
|
|
16205
16376
|
if (!varId) {
|
|
16206
|
-
varId =
|
|
16377
|
+
varId = randomUUID11();
|
|
16207
16378
|
svcScopedEnv["variables"][varId] = {
|
|
16208
16379
|
key: cleaned,
|
|
16209
16380
|
value: { value: "", pre: "", post: "", isSecret: false, injectIntoAi: false }
|
|
@@ -16218,12 +16389,12 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
16218
16389
|
}
|
|
16219
16390
|
}
|
|
16220
16391
|
if (envsModified) {
|
|
16221
|
-
await atomicWrite(
|
|
16392
|
+
await atomicWrite(join28(abDataDir, "environments.json"), envsRaw);
|
|
16222
16393
|
console.log("[override-migration] Merged service overrides into environments.json");
|
|
16223
16394
|
}
|
|
16224
16395
|
const migratedDir = overridesDir.replace(/overrides$/, "overrides-migrated");
|
|
16225
16396
|
try {
|
|
16226
|
-
await
|
|
16397
|
+
await rename17(overridesDir, migratedDir);
|
|
16227
16398
|
console.log(`[override-migration] Moved overrides/ \u2192 overrides-migrated/`);
|
|
16228
16399
|
} catch (err) {
|
|
16229
16400
|
console.warn(`[override-migration] Could not rename overrides dir: ${err.message}`);
|
|
@@ -16233,7 +16404,7 @@ async function runOverrideOnlyMigration(dataDir) {
|
|
|
16233
16404
|
}
|
|
16234
16405
|
|
|
16235
16406
|
// ../server/src/services/server-state.ts
|
|
16236
|
-
import { join as
|
|
16407
|
+
import { join as join29 } from "path";
|
|
16237
16408
|
import { stat as stat12 } from "fs/promises";
|
|
16238
16409
|
var ENCRYPTED_KEY_FILENAME2 = ".encryption.key.enc";
|
|
16239
16410
|
var VERIFY_FILENAME2 = ".runeya-verify";
|
|
@@ -16243,22 +16414,22 @@ async function getServerState() {
|
|
|
16243
16414
|
let hasVerify = false;
|
|
16244
16415
|
let hasData = false;
|
|
16245
16416
|
try {
|
|
16246
|
-
await stat12(
|
|
16417
|
+
await stat12(join29(dataDir, ENCRYPTED_KEY_FILENAME2));
|
|
16247
16418
|
hasEncFile = true;
|
|
16248
16419
|
} catch {
|
|
16249
16420
|
}
|
|
16250
16421
|
try {
|
|
16251
|
-
await stat12(
|
|
16422
|
+
await stat12(join29(dataDir, VERIFY_FILENAME2));
|
|
16252
16423
|
hasVerify = true;
|
|
16253
16424
|
} catch {
|
|
16254
16425
|
}
|
|
16255
16426
|
try {
|
|
16256
|
-
await stat12(
|
|
16427
|
+
await stat12(join29(dataDir, "projects.json"));
|
|
16257
16428
|
hasData = true;
|
|
16258
16429
|
} catch {
|
|
16259
16430
|
}
|
|
16260
16431
|
try {
|
|
16261
|
-
await stat12(
|
|
16432
|
+
await stat12(join29(dataDir, "project.json"));
|
|
16262
16433
|
hasData = true;
|
|
16263
16434
|
} catch {
|
|
16264
16435
|
}
|
|
@@ -16671,6 +16842,7 @@ async function createLocalServer() {
|
|
|
16671
16842
|
await ensureDataGitignore(env.DATA_DIR);
|
|
16672
16843
|
}
|
|
16673
16844
|
await settingsManager.getSettings();
|
|
16845
|
+
await applyPersistedLanMode();
|
|
16674
16846
|
await migrationEngine.run();
|
|
16675
16847
|
await ensureFilePermissions();
|
|
16676
16848
|
auditService.cleanup().catch((err) => console.error("[server] Audit cleanup failed:", err));
|
|
@@ -17267,6 +17439,7 @@ async function createLocalServer() {
|
|
|
17267
17439
|
}));
|
|
17268
17440
|
app.use(errorHandler);
|
|
17269
17441
|
const server = createServer(app);
|
|
17442
|
+
registerHttpServer(server);
|
|
17270
17443
|
const wss = new WebSocketServer({ noServer: true });
|
|
17271
17444
|
applyWSSHandler({
|
|
17272
17445
|
wss,
|
|
@@ -17518,4 +17691,4 @@ export {
|
|
|
17518
17691
|
pullEnv,
|
|
17519
17692
|
registerInstance
|
|
17520
17693
|
};
|
|
17521
|
-
//# sourceMappingURL=src-
|
|
17694
|
+
//# sourceMappingURL=src-53OQNM27.js.map
|