@runeya/runeya 2.0.21 → 2.0.24
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 +103 -9
- package/agent/index.js.map +1 -1
- package/agent-manager-2P4THUVA.js +7 -0
- package/{chunk-PUNE7P6S.js → chunk-Y2R42AXQ.js} +848 -561
- package/chunk-Y2R42AXQ.js.map +1 -0
- package/index.js +92 -43
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/{src-K32WI425.js → src-EGBDYHL5.js} +1540 -1119
- package/src-EGBDYHL5.js.map +1 -0
- package/web/assets/AgentScalarChatInterface.vue-Bk_cXx74.js +13 -0
- package/web/assets/AgentTerminalPage-DqXrABlh.js +1 -0
- package/web/assets/AiChatPage-B3P7qefE.js +1 -0
- package/web/assets/AppLayout-B2e7K0cZ.js +1 -0
- package/web/assets/{AuditPage-CUdrFc3C.js → AuditPage-B55qp9MV.js} +1 -1
- package/web/assets/{CloudAccountPage-am6AxJRB.js → CloudAccountPage-CGyW79m_.js} +1 -1
- package/web/assets/CloudAccountPage-DTity1N0.js +1 -0
- package/web/assets/CloudMessagingPage-7RQRbAOB.js +2 -0
- package/web/assets/CloudMessagingPage-BUnfNsBz.css +1 -0
- package/web/assets/{DashboardPage-pA2caWR9.js → DashboardPage-CwmCbP3t.js} +1 -1
- package/web/assets/{EditorIcon-C9E8hRyM.js → EditorIcon-BaldhaS8.js} +1 -1
- package/web/assets/{EnvironmentForm-XKpxQ-45.js → EnvironmentForm-Da52SUx4.js} +2 -2
- package/web/assets/EnvironmentFormPage-Bab5iOWS.js +1 -0
- package/web/assets/EnvironmentListPage-O1fIWq-g.js +1 -0
- package/web/assets/EnvironmentSelector-BWzLYssP.js +1 -0
- package/web/assets/KanbanBoardPage-BOMHKLHX.css +1 -0
- package/web/assets/KanbanBoardPage-BvtIaHqG.js +4 -0
- package/web/assets/KanbanListPage-BoNcgR3h.css +1 -0
- package/web/assets/KanbanListPage-Cv_QJF00.js +1 -0
- package/web/assets/LaunchProjectPage-uB7iIMG1.js +1 -0
- package/web/assets/{LaunchServicesPage-CViec72c.js → LaunchServicesPage-1ZN1JYqH.js} +1 -1
- package/web/assets/LogViewer-BJxpIK11.js +3 -0
- package/web/assets/{ProcessControls-D97-A3dI.js → ProcessControls-C2EYsD-P.js} +1 -1
- package/web/assets/ProcessDetailPage-DdOfegjU.js +1 -0
- package/web/assets/{ProcessMetrics-CNJ30_ef.js → ProcessMetrics-DpDxpUpO.js} +2 -2
- package/web/assets/ProjectDetailPage-DtwRjTew.js +1 -0
- package/web/assets/ProjectListPage-D9SUNEFu.js +1 -0
- package/web/assets/{RandomJobTestPage-CnY2f-qz.js → RandomJobTestPage-OoAk9WAJ.js} +1 -1
- package/web/assets/{ScenarioEditorPage-CBZp7Q34.css → ScenarioEditorPage-GmFIXPDj.css} +1 -1
- package/web/assets/ScenarioEditorPage-LhEs4hjS.js +14 -0
- package/web/assets/SendToChatDialog-CZWy1K4A.js +1 -0
- package/web/assets/ServiceControlsBar-CU6b2KBJ.js +1 -0
- package/web/assets/{ServiceDetailPage-DhE1LYrn.css → ServiceDetailPage-BvoD3SB6.css} +1 -1
- package/web/assets/ServiceDetailPage-CSaPyV_v.js +2 -0
- package/web/assets/ServiceFormPage-D9NFCmmW.js +1 -0
- package/web/assets/SettingsPage-BMclTDLy.css +1 -0
- package/web/assets/SettingsPage-DXlBFfBq.js +2062 -0
- package/web/assets/{SetupPage-CzabsTON.js → SetupPage-dqqf_M_p.js} +1 -1
- package/web/assets/UnlockPage-ClEawxOC.css +1 -0
- package/web/assets/UnlockPage-DjjpY02d.js +1 -0
- package/web/assets/VariablesTable-B4h9eNC_.css +1 -0
- package/web/assets/VariablesTable-BFgRnjza.js +1 -0
- package/web/assets/{VersionBadge-DUE17MrD.js → VersionBadge-ToW3NGSQ.js} +1 -1
- package/web/assets/WikiPage-Djisdsae.js +1 -0
- package/web/assets/{WikiView-CUBKfTT-.css → WikiView-CaUVD3f1.css} +1 -1
- package/web/assets/WikiView-CiATkY8l.js +1 -0
- package/web/assets/{add-scalar-classes-Cfh7_IWy.js → add-scalar-classes-DGwycuRW.js} +3 -3
- package/web/assets/auth-errors-DEObS1lG.js +1 -0
- package/web/assets/{autocomplete-CrWQ5zMj.js → autocomplete-DP0sGong.js} +1 -1
- package/web/assets/{basic-shape-diamond.svg-pjhwN4JT.js → basic-shape-diamond.svg-B0FzUXGN.js} +1 -1
- package/web/assets/{basic-shape-hexagon.svg-D0yEDOCC.js → basic-shape-hexagon.svg-BuI9rv44.js} +1 -1
- package/web/assets/{basic-shape-primary-circle-ellipse-round.svg-DvZ7CdgE.js → basic-shape-primary-circle-ellipse-round.svg-C0WlStV7.js} +1 -1
- package/web/assets/{basic-shape-primary-square-rectangle.svg-ChB1hiGR.js → basic-shape-primary-square-rectangle.svg-ByMGtNMn.js} +1 -1
- package/web/assets/{basic-shape-shield.svg-Bxrmr3jg.js → basic-shape-shield.svg-h6znjRmZ.js} +1 -1
- package/web/assets/{browser-C2YmKQw8.js → browser-DJeF2lho.js} +1 -1
- package/web/assets/{browser-CvQ_J2u9.js → browser-oekISqUb.js} +1 -1
- package/web/assets/{card-CpyeL2dI.js → card-B7-be48x.js} +1 -1
- package/web/assets/{checkbox-DWNV_RaS.js → checkbox-DDSZK_Pi.js} +1 -1
- package/web/assets/{chip-8cRcc2L3.js → chip-BVSQ-56q.js} +1 -1
- package/web/assets/{client-DNj6VDDb.js → client-DWfGqqLr.js} +1 -1
- package/web/assets/cloud-chat.store-BLFChRpl.js +1 -0
- package/web/assets/cloud-client-GmxBhiFl.js +1 -0
- package/web/assets/{column-DtLr_xcq.js → column-BHRqZfnh.js} +7 -7
- package/web/assets/{computer-device-desktop-monitor.svg-CLGySxTI.js → computer-device-desktop-monitor.svg-CL9XulYR.js} +1 -1
- package/web/assets/{computer-device-desktop.svg-DJ9n7_Sq.js → computer-device-desktop.svg-CKWeVTzO.js} +1 -1
- package/web/assets/{computer-device-laptop.svg-k6zcRWN4.js → computer-device-laptop.svg-wAkdRlEi.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-android-samsung-back.svg-pwKHMzIK.js → computer-device-mobile-phone-android-samsung-back.svg-DOahzxu1.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-android-samsung.svg-CR796QT_.js → computer-device-mobile-phone-android-samsung.svg-FBZO3WLS.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-iphone-x-back.svg-CY2r7WXK.js → computer-device-mobile-phone-iphone-x-back.svg-CCLknBWv.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-iphone-x.svg-BHISnTWX.js → computer-device-mobile-phone-iphone-x.svg-CWdT8wN4.js} +1 -1
- package/web/assets/{computer-device-mobile-tablet-touch.svg-DQqDUvnk.js → computer-device-mobile-tablet-touch.svg-Bx1A6qUQ.js} +1 -1
- package/web/assets/{computer-device-mobile-tablet.svg-4Ab5vdIo.js → computer-device-mobile-tablet.svg-JpmP6yqf.js} +1 -1
- package/web/assets/{computer-device-network-ethernet-cat6.svg-DJf04S68.js → computer-device-network-ethernet-cat6.svg-D6WFbLbI.js} +1 -1
- package/web/assets/{computer-device-network-lan-www.svg-CaETgcOJ.js → computer-device-network-lan-www.svg-U8NMAi5b.js} +1 -1
- package/web/assets/{computer-device-network-wifi-connection.svg-PndfmFuy.js → computer-device-network-wifi-connection.svg-FuRBLyH4.js} +1 -1
- package/web/assets/{computer-device-network-wifi-router.svg-CBLwEbOV.js → computer-device-network-wifi-router.svg-BMzCP2Aw.js} +1 -1
- package/web/assets/{cssMode-RVPpAuHz.js → cssMode--4DE_809.js} +1 -1
- package/web/assets/{divider-CYFRNVal.js → divider-hPOrl1Iy.js} +1 -1
- package/web/assets/{ecology-science-erlenmeyer-flask.svg-BYXK2uKa.js → ecology-science-erlenmeyer-flask.svg-Bnte5Nm-.js} +1 -1
- package/web/assets/{fieldset-BCXBPIiB.js → fieldset-BSwilV-Y.js} +1 -1
- package/web/assets/{freemarker2-B6guP0jO.js → freemarker2-DUNAk_0P.js} +1 -1
- package/web/assets/{handlebars-BxlL79LN.js → handlebars-CoM2DS_1.js} +1 -1
- package/web/assets/{html-Dr0M60O0.js → html-CgEDNZ_R.js} +1 -1
- package/web/assets/{htmlMode-B63yAhXq.js → htmlMode-QDDBWVzd.js} +1 -1
- package/web/assets/{image-flash-lightning.svg-DVtJFd09.js → image-flash-lightning.svg-ZIxta1IB.js} +1 -1
- package/web/assets/{image-picture-flower.svg-BaBdyWt-.js → image-picture-flower.svg-BXxhgW1Q.js} +1 -1
- package/web/assets/{index-BTYNCNK0.js → index-Dl-HyfHx.js} +244 -244
- package/web/assets/{index-DS4VL_1S.css → index-gKo3WNkm.css} +1 -1
- package/web/assets/{interface-alert-exclamation-diamond.svg-BQYncN9j.js → interface-alert-exclamation-diamond.svg-bVfL6jBy.js} +1 -1
- package/web/assets/{interface-alert-exclamation-triangle-warning.svg-BvQxARpD.js → interface-alert-exclamation-triangle-warning.svg-BrapXyrc.js} +1 -1
- package/web/assets/{interface-alert-information-circle.svg-BbiwUtTt.js → interface-alert-information-circle.svg--W3bUw5n.js} +1 -1
- package/web/assets/{interface-award-crown.svg-BJs2BJ9S.js → interface-award-crown.svg-CBbbHFIN.js} +1 -1
- package/web/assets/{interface-bookmark.svg-WUL572zM.js → interface-bookmark-tag.svg-C4_v-zTY.js} +1 -1
- package/web/assets/{interface-bookmark-tag.svg-huwK9o4X.js → interface-bookmark.svg-CIY69-iu.js} +1 -1
- package/web/assets/{interface-calendar-date-one.svg-CEkOALKM.js → interface-calendar-date-one.svg-CD7WxblA.js} +1 -1
- package/web/assets/{interface-content-book-open-pages.svg-CDxvdidz.js → interface-content-book-open-pages.svg-BamW-eNv.js} +1 -1
- package/web/assets/{interface-content-book-page.svg-ROxK9a-V.js → interface-content-book-page.svg-CpHhLWQE.js} +1 -1
- package/web/assets/{interface-content-file.svg-69XGQGxu.js → interface-content-file.svg-BmqLN3iR.js} +1 -1
- package/web/assets/interface-content-folder.svg-B2phMZXd.js +1 -0
- package/web/assets/{interface-content-folder.svg-BjXgivIz.js → interface-content-folder.svg-ffbcORbT.js} +1 -1
- package/web/assets/{interface-copy-clipboard.svg-BAAZ1QLS.js → interface-copy-clipboard.svg-MdbbmqXS.js} +1 -1
- package/web/assets/{interface-edit-attachment.svg-BCmyBBsd.js → interface-edit-attachment.svg-DtAVj6tp.js} +1 -1
- package/web/assets/{interface-edit-binocular.svg-BI3JPE3j.js → interface-edit-binocular.svg-DfT11Y7N.js} +1 -1
- package/web/assets/{interface-edit-magic-wand.svg-DhECH5yw.js → interface-edit-magic-wand.svg-D4mLRHJs.js} +1 -1
- package/web/assets/{interface-edit-tool-paint-roller.svg-0-Os9Flg.js → interface-edit-tool-paint-roller.svg-Cxa7Ct4C.js} +1 -1
- package/web/assets/{interface-edit-tool-pencil.svg-CM5UI5Rv.js → interface-edit-tool-pencil.svg-IRM3BHKY.js} +1 -1
- package/web/assets/{interface-favorite-award.svg-BZNkuFiE.js → interface-favorite-award.svg-CLGZ65SX.js} +1 -1
- package/web/assets/{interface-favorite-flag.svg-CeHd37SC.js → interface-favorite-flag.svg-ju-VMCAF.js} +1 -1
- package/web/assets/{interface-favorite-heart.svg-D5dJ4sOz.js → interface-favorite-heart.svg-DsWpztN8.js} +1 -1
- package/web/assets/{interface-favorite-star.svg-B7YeWzmv.js → interface-favorite-star.svg-CCPUYvBO.js} +1 -1
- package/web/assets/{interface-favorite-stars-sparkles.svg-BwqCtLSB.js → interface-favorite-stars-sparkles.svg-nf2ra-Mg.js} +1 -1
- package/web/assets/{interface-hierarchy-flowchart.svg-q70-KJ80.js → interface-hierarchy-flowchart.svg-CPrjsUHp.js} +1 -1
- package/web/assets/{interface-home-house.svg-CUco1zSk.js → interface-home-house.svg-DyWL4dgs.js} +1 -1
- package/web/assets/{interface-hyperlink.svg-D6Z-QbxJ.js → interface-hyperlink.svg-DgjI4lGJ.js} +1 -1
- package/web/assets/{interface-lighting-brightness.svg-DDJ8wIbt.js → interface-lighting-brightness.svg-BhomgGV0.js} +1 -1
- package/web/assets/{interface-lock-closed.svg-1GuN2t9d.js → interface-lock-closed.svg-CDDGuaUG.js} +1 -1
- package/web/assets/{interface-lock-open-unlock.svg-CmSL9GCo.js → interface-lock-open-unlock.svg-DxOzefwC.js} +1 -1
- package/web/assets/{interface-login-key.svg-Cnur4uLY.js → interface-login-key.svg-CLs728UT.js} +1 -1
- package/web/assets/{interface-search.svg-3TqtroIY.js → interface-search.svg-CSE2bUM-.js} +1 -1
- package/web/assets/{interface-setting-cog.svg-B7nRfZ1y.js → interface-setting-cog.svg-SfBQ-E_y.js} +1 -1
- package/web/assets/{interface-share-megaphone-bullhorn.svg-DraAk4oI.js → interface-share-megaphone-bullhorn.svg-Cg9QEbsW.js} +1 -1
- package/web/assets/{interface-share-rocket.svg-CGRtk6J4.js → interface-share-rocket.svg-V9fWt6R5.js} +1 -1
- package/web/assets/{interface-share-satellite.svg-COo3kZqu.js → interface-share-satellite.svg-BoAJlAy3.js} +1 -1
- package/web/assets/{interface-share-space-ship.svg-iYhfpKY2.js → interface-share-space-ship.svg-CWoqBiZI.js} +1 -1
- package/web/assets/{interface-share.svg-BqVe3lWw.js → interface-share.svg-DW6AG6rC.js} +1 -1
- package/web/assets/{interface-signal-square.svg-DmGT2kio.js → interface-signal-square.svg-DktTeL2e.js} +1 -1
- package/web/assets/{interface-time-clock-circle.svg-Djt_VZVX.js → interface-time-clock-circle.svg-BBnimglQ.js} +1 -1
- package/web/assets/{interface-time-hour-glass.svg-DxZVLqJ6.js → interface-time-hour-glass.svg-WNSRow4o.js} +1 -1
- package/web/assets/{interface-users-multiple.svg-n8dIXu9r.js → interface-users-multiple.svg-DoeSSDNX.js} +1 -1
- package/web/assets/{interface-weather-moon.svg-CExHl6HQ.js → interface-weather-moon.svg-BzUq31T3.js} +1 -1
- package/web/assets/{javascript-6lVkE6gP.js → javascript-CDsgZK6E.js} +1 -1
- package/web/assets/{jsonMode-CySg6s8T.js → jsonMode-BOQojnkz.js} +1 -1
- package/web/assets/{liquid-DSLZY9bf.js → liquid-CT8_Ig_a.js} +1 -1
- package/web/assets/{lspLanguageFeatures-C6Gb5-pg.js → lspLanguageFeatures-BW3wbtds.js} +1 -1
- package/web/assets/{mail-chat-bubble-square.svg-BqpIkvR_.js → mail-chat-bubble-square.svg-BB3D-jS5.js} +1 -1
- package/web/assets/{mail-send-email-paper-airplane.svg-DUkiRZ1x.js → mail-send-email-paper-airplane.svg-BGUFNdDy.js} +1 -1
- package/web/assets/{mail-send-envelope.svg-DjjLaPUo.js → mail-send-envelope.svg-CiEf_X3v.js} +1 -1
- package/web/assets/{mdx-DuCKQZ3-.js → mdx-BzJqzXG7.js} +1 -1
- package/web/assets/{message-CJ-X_z47.js → message-DQfiz3F1.js} +1 -1
- package/web/assets/{minus-RXlNS6-g.js → minus-Bh-ngAnz.js} +1 -1
- package/web/assets/modal-B6tgGww3.js +1 -0
- package/web/assets/{modal-DfNn2ioJ.js → modal-BH8tCrqE.js} +1 -1
- package/web/assets/{money-cashier-receipt.svg-CUzOL6J5.js → money-cashier-receipt.svg-nbLywLCi.js} +1 -1
- package/web/assets/{money-currency-dollar-pay.svg-CQY_KC9b.js → money-currency-dollar-pay.svg-HtpV_93j.js} +1 -1
- package/web/assets/{money-graph-arrow-increase.svg-BDu5i5aF.js → money-graph-arrow-increase.svg-BG4s2n8-.js} +1 -1
- package/web/assets/{money-graph-bar-chart-increase.svg-xBlBZYiv.js → money-graph-bar-chart-increase.svg-7ivMfz5M.js} +1 -1
- package/web/assets/{multiselect-BbY8SFyO.js → multiselect-CE72JxFr.js} +1 -1
- package/web/assets/{nature-ecology-leaf.svg-C_T6wTIZ.js → nature-ecology-leaf.svg-D60IfAE-.js} +1 -1
- package/web/assets/{password-B_pKmF_I.js → password-CZ-A_ePM.js} +1 -1
- package/web/assets/{phone-telephone.svg-DzUP7zCx.js → phone-telephone.svg-B0OCaSQr.js} +1 -1
- package/web/assets/{plus-DfsTcd_H.js → plus-DZy8IO4Z.js} +1 -1
- package/web/assets/process.store-XR7BoPqt.js +1 -0
- package/web/assets/{programming-bug.svg-C1NvPH7_.js → programming-bug.svg-DDZ7-1a6.js} +1 -1
- package/web/assets/{programming-cloud.svg-hVwd5xzu.js → programming-cloud.svg-BZHqbFE1.js} +1 -1
- package/web/assets/{programming-computer-database-server.svg-DXvcm62E.js → programming-computer-database-server.svg-CPK0axOF.js} +1 -1
- package/web/assets/{programming-computer-database.svg-w2w_GH3u.js → programming-computer-database.svg-Dat_iKWZ.js} +1 -1
- package/web/assets/{programming-module-four-layout.svg-DLcwogv0.js → programming-module-four-layout.svg-DYTRTKmF.js} +1 -1
- package/web/assets/{programming-module-three.svg-Cfjjs8tf.js → programming-module-three.svg-CU563xPB.js} +1 -1
- package/web/assets/{programming-module.svg-ChyMdD4E.js → programming-module.svg-DdRe2d3E.js} +1 -1
- package/web/assets/{programming-script-code.svg-D8N99_E3.js → programming-script-code.svg-D5dDzg1B.js} +1 -1
- package/web/assets/{python-BT-UPVMQ.js → python-C0tzbgs4.js} +1 -1
- package/web/assets/{radiobutton-C9iiy1zq.js → radiobutton-BYEniO96.js} +1 -1
- package/web/assets/{razor-DKUraACi.js → razor-BNCtUdbo.js} +1 -1
- package/web/assets/router-BpJBXGio.js +1 -0
- package/web/assets/{settings.store-PSHvWAzl.js → settings.store-hW2r6ht2.js} +1 -1
- package/web/assets/{shopping-cart.svg-C_kTBKvf.js → shopping-cart.svg-yNDOoxiE.js} +1 -1
- package/web/assets/{shopping-gift-present.svg-DIfbUecw.js → shopping-gift-present.svg-ZAFtf911.js} +1 -1
- package/web/assets/{shopping-shipping-box-parcel-package.svg-DgeqoYij.js → shopping-shipping-box-parcel-package.svg-C_128hOx.js} +1 -1
- package/web/assets/{TiptapEditor-CI1pNNDH.js → src-BTZHXzoT.js} +78 -78
- package/web/assets/src-CmzYYWZd.css +1 -0
- package/web/assets/src-DtlOQm4K.js +1 -0
- package/web/assets/src-ZfecJkW9.css +1 -0
- package/web/assets/{tabpanel-tgozju6m.js → tabpanel-BiifLLS6.js} +2 -2
- package/web/assets/{tag-new-circle.svg-yzrCIErB.js → tag-new-circle.svg-0OOws8vC.js} +1 -1
- package/web/assets/{travel-map-earth-globe.svg-C9CMICQQ.js → travel-map-earth-globe.svg-CvwB8JlN.js} +1 -1
- package/web/assets/trpc-D0HTyuMG.js +1 -0
- package/web/assets/{tsMode-gblCXC3w.js → tsMode-CadFFP73.js} +1 -1
- package/web/assets/{typescript-DeVzlCKf.js → typescript-TsqAe_2a.js} +1 -1
- package/web/assets/useAiChatDrawer-2ELNp1KU.js +1 -0
- package/web/assets/useCloudOrg-BAtUa48Z.css +1 -0
- package/web/assets/useCloudOrg-DuypVndp.js +1 -0
- package/web/assets/{xml-UwUjH4rq.js → xml-bgdRCuvM.js} +1 -1
- package/web/assets/{yaml-DSs0npSB.js → yaml-BRUv0H85.js} +1 -1
- package/web/index.html +2 -2
- package/agent-manager-QPZUYLJA.js +0 -8
- package/chunk-LZWBXYUE.js +0 -354
- package/chunk-LZWBXYUE.js.map +0 -1
- package/chunk-PUNE7P6S.js.map +0 -1
- package/chunk-Q4N37KNN.js +0 -202
- package/chunk-Q4N37KNN.js.map +0 -1
- package/kanban-commands-53WWMCHQ.js +0 -14
- package/kanban-commands-53WWMCHQ.js.map +0 -1
- package/src-K32WI425.js.map +0 -1
- package/web/assets/AgentScalarChatInterface.vue-S7bbKRqw.js +0 -13
- package/web/assets/AgentTerminalPage-c0fCTCzP.js +0 -1
- package/web/assets/AiChatPage-B-kfiUI-.js +0 -1
- package/web/assets/AppLayout-COTo6zQf.js +0 -1
- package/web/assets/CloudAccountPage-H1QGj9tJ.js +0 -1
- package/web/assets/CloudMessagingPage-BEtd8B8B.js +0 -2
- package/web/assets/CloudMessagingPage-sgMxCh6j.css +0 -1
- package/web/assets/EnvironmentFormPage-DMpiq3Zx.js +0 -1
- package/web/assets/EnvironmentListPage-C21qJ3iw.js +0 -1
- package/web/assets/EnvironmentSelector-Be9yMkjY.js +0 -1
- package/web/assets/KanbanBoardPage-CyUTDl_W.css +0 -1
- package/web/assets/KanbanBoardPage-SNCSxTz7.js +0 -4
- package/web/assets/KanbanListPage-B3JpbFlv.css +0 -1
- package/web/assets/KanbanListPage-D-kgPmxI.js +0 -1
- package/web/assets/LaunchProjectPage-BbNDYePE.js +0 -1
- package/web/assets/LogViewer-CHyPfODD.js +0 -3
- package/web/assets/ProcessDetailPage-BlQJDM-W.js +0 -1
- package/web/assets/ProjectDetailPage-DdRYMfcl.js +0 -1
- package/web/assets/ProjectListPage-BDLXGuEj.js +0 -1
- package/web/assets/ScenarioEditorPage-CFNTrVlY.js +0 -14
- package/web/assets/SendToChatDialog-BJjY1MAh.css +0 -1
- package/web/assets/SendToChatDialog-CtGhyaOw.js +0 -1
- package/web/assets/ServiceControlsBar-m_AQmRiR.js +0 -1
- package/web/assets/ServiceDetailPage-RCl6IsBs.js +0 -2
- package/web/assets/ServiceFormPage-CIJ-tFub.js +0 -1
- package/web/assets/SettingsPage-CPF7w35a.css +0 -1
- package/web/assets/SettingsPage-tK-RiJrj.js +0 -2062
- package/web/assets/SetupKeyPage-CzB_AMfr.js +0 -1
- package/web/assets/SetupKeyPage-DoY1Ua1s.css +0 -1
- package/web/assets/TiptapEditor-bdEPMd-W.css +0 -1
- package/web/assets/UnlockPage-DWM5symg.js +0 -1
- package/web/assets/UnlockPage-EZOi-H7d.css +0 -1
- package/web/assets/VariablesTable-Bkv0MOKi.css +0 -1
- package/web/assets/VariablesTable-DoNJ4OIn.js +0 -1
- package/web/assets/WikiPage-COdO-49s.js +0 -1
- package/web/assets/WikiView-BS9HHroX.js +0 -1
- package/web/assets/auth-errors-D-uOLmKt.js +0 -1
- package/web/assets/cloud-chat.store-DHiYOkkN.js +0 -1
- package/web/assets/cloud-client-COpvz58o.js +0 -1
- package/web/assets/interface-content-folder.svg-Bijbx45w.js +0 -1
- package/web/assets/modal-BvVbc_6u.js +0 -1
- package/web/assets/process.store-BLMSPw2l.js +0 -1
- package/web/assets/router-DBNATEGs.js +0 -1
- package/web/assets/trpc-3qbDCsqO.js +0 -1
- package/web/assets/useAiChatDrawer-BtC-0qN-.js +0 -1
- /package/{agent-manager-QPZUYLJA.js.map → agent-manager-2P4THUVA.js.map} +0 -0
- /package/web/assets/{abap-lJFTLuI6.js → abap-DMmvWZUy.js} +0 -0
- /package/web/assets/{apex-Bp0KWav8.js → apex-D89PiTzU.js} +0 -0
- /package/web/assets/{azcli-DBOe7Uvy.js → azcli-ChnjTTA5.js} +0 -0
- /package/web/assets/{bat-Dk_NT_by.js → bat-uLzQ_FhK.js} +0 -0
- /package/web/assets/{bicep-B07Mrlc7.js → bicep-CMOK7Q1v.js} +0 -0
- /package/web/assets/{cameligo-DL5eNXGn.js → cameligo-D1AyojFH.js} +0 -0
- /package/web/assets/{clojure-BzV2Yqu_.js → clojure-D9JoUgXn.js} +0 -0
- /package/web/assets/{coffee-Bjlj5hmf.js → coffee-D-5sSToL.js} +0 -0
- /package/web/assets/{cpp-C9oth5qz.js → cpp-BqT_t_y9.js} +0 -0
- /package/web/assets/{csharp-HyGd049S.js → csharp-CuToYI91.js} +0 -0
- /package/web/assets/{csp-DjCDOBuX.js → csp-CffcxvlO.js} +0 -0
- /package/web/assets/{css-DIL8RTJ3.js → css-CUD0biQW.js} +0 -0
- /package/web/assets/{cypher-DX1zPXL5.js → cypher-ByyWL_9U.js} +0 -0
- /package/web/assets/{dart-BBQZd_ZZ.js → dart-B__ipcUn.js} +0 -0
- /package/web/assets/{dockerfile-Cj0CaWYx.js → dockerfile-DS-_8bWw.js} +0 -0
- /package/web/assets/{ecl-BjmWCTJg.js → ecl-DWsNCBUj.js} +0 -0
- /package/web/assets/{elixir-3uWoEjXX.js → elixir-OfjEy-3g.js} +0 -0
- /package/web/assets/{flow9-D4r739e9.js → flow9-BPX22hxS.js} +0 -0
- /package/web/assets/{fsharp-B3ycAx5T.js → fsharp-CVJcfIUn.js} +0 -0
- /package/web/assets/{go-DFHBjfCl.js → go-CfRHZ3yg.js} +0 -0
- /package/web/assets/{graphql-DBjIbM_e.js → graphql-BZaO3ttK.js} +0 -0
- /package/web/assets/{hcl-Buu_1Hsp.js → hcl-BF9-qUku.js} +0 -0
- /package/web/assets/{ini-CgzZhgz_.js → ini-BUvw6xhr.js} +0 -0
- /package/web/assets/{java-BczDO0q5.js → java-BZ5BNd2x.js} +0 -0
- /package/web/assets/{julia-B142kn-7.js → julia-DN38cgYT.js} +0 -0
- /package/web/assets/{kotlin-42XMP7p1.js → kotlin-CjEJKT8q.js} +0 -0
- /package/web/assets/{less-BCIsKRqU.js → less-DMEH_Nwq.js} +0 -0
- /package/web/assets/{lexon-DTDOH1dQ.js → lexon-CKQUX8Ov.js} +0 -0
- /package/web/assets/{lua-BrH-CeNs.js → lua-CuWjKLJ0.js} +0 -0
- /package/web/assets/{m3-D-eUeHOI.js → m3-CEp1bVrM.js} +0 -0
- /package/web/assets/{markdown-DwpSjZTn.js → markdown-DxtQ_puq.js} +0 -0
- /package/web/assets/{mips-DoGTrjVk.js → mips-Dx7qydpO.js} +0 -0
- /package/web/assets/{msdax-CQ8McnjQ.js → msdax-DpNCaSiO.js} +0 -0
- /package/web/assets/{mysql-Cj3do0ZO.js → mysql-C3xsBDPP.js} +0 -0
- /package/web/assets/{objective-c-BZbR8TG8.js → objective-c-BbaVHCX1.js} +0 -0
- /package/web/assets/{pascal-23PRDHRq.js → pascal-sDju2faq.js} +0 -0
- /package/web/assets/{pascaligo-CxasKTLJ.js → pascaligo-ChCdOH6b.js} +0 -0
- /package/web/assets/{perl-Dhxz2Lhx.js → perl-BCgLFj01.js} +0 -0
- /package/web/assets/{pgsql-BIbUy7yD.js → pgsql-DtKby69f.js} +0 -0
- /package/web/assets/{php-B5qS9qgM.js → php-NYvR17Qb.js} +0 -0
- /package/web/assets/{pla-Bolz9fha.js → pla-gSg-RBG0.js} +0 -0
- /package/web/assets/{postiats-Ba6dE5lj.js → postiats-BQxHyDfy.js} +0 -0
- /package/web/assets/{powerquery-2jW3ONgo.js → powerquery-DzDmbVZN.js} +0 -0
- /package/web/assets/{powershell-CMfBIiJp.js → powershell-yy4Q5BEQ.js} +0 -0
- /package/web/assets/{protobuf-BpaquOUj.js → protobuf-B_hIk9q0.js} +0 -0
- /package/web/assets/{pug-cBG82Ydz.js → pug-CdeEb1ft.js} +0 -0
- /package/web/assets/{qsharp-DtqL8Lmt.js → qsharp-CiSquEgT.js} +0 -0
- /package/web/assets/{r-CKLew4sj.js → r-D1Ocz1x4.js} +0 -0
- /package/web/assets/{redis-BdDxRU-N.js → redis-D42Y12yz.js} +0 -0
- /package/web/assets/{redshift-X4a4MlqW.js → redshift-CS62MYfG.js} +0 -0
- /package/web/assets/{restructuredtext-LA4Fv05h.js → restructuredtext-CKFSMEXw.js} +0 -0
- /package/web/assets/{ruby-CibE_WVM.js → ruby-C4gTaeU3.js} +0 -0
- /package/web/assets/{rust-BK6RsiL0.js → rust-C_f2AiHQ.js} +0 -0
- /package/web/assets/{sb-BnCCt0Qj.js → sb-CdNdpP1r.js} +0 -0
- /package/web/assets/{scala-oaBDrVqj.js → scala-N4EWaFTL.js} +0 -0
- /package/web/assets/{scheme-C-wkLC01.js → scheme-CttIARxx.js} +0 -0
- /package/web/assets/{scss-BceVGOJY.js → scss-v0wtbxaE.js} +0 -0
- /package/web/assets/{shell-CxhBAFA5.js → shell-BJdEWXbc.js} +0 -0
- /package/web/assets/{solidity-D9sXgTfx.js → solidity-DKDa59zZ.js} +0 -0
- /package/web/assets/{sophia-C4VBhIEM.js → sophia--Kw-vDpr.js} +0 -0
- /package/web/assets/{sparql-DbsK2s9y.js → sparql-BI8jS9Pc.js} +0 -0
- /package/web/assets/{sql-CuGfE0wH.js → sql-Dz6z--6O.js} +0 -0
- /package/web/assets/{st-rB6Bqb2h.js → st-CT8D05gv.js} +0 -0
- /package/web/assets/{swift-BtHGe_4T.js → swift-Ayb3KzWx.js} +0 -0
- /package/web/assets/{systemverilog-CgKnzwU4.js → systemverilog-BtWJM9O5.js} +0 -0
- /package/web/assets/{tcl-DyqQWf87.js → tcl-BJvUWpbV.js} +0 -0
- /package/web/assets/{twig-C980XO5P.js → twig-c3YaBCU6.js} +0 -0
- /package/web/assets/{typespec-CVmA80px.js → typespec-gFCWLBoZ.js} +0 -0
- /package/web/assets/{uuid-2Kb5PDpq.js → uuid-B3B8HIK9.js} +0 -0
- /package/web/assets/{vb-rdNQv5VQ.js → vb-CVtfWXV2.js} +0 -0
- /package/web/assets/{w3c-keyname-B2B-WOb1.js → w3c-keyname-nn0G3QC2.js} +0 -0
- /package/web/assets/{wgsl-64oVbimL.js → wgsl-C_huaGQy.js} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../server/src/create-server.ts","../../server/src/trpc/trpc.ts","../../server/src/services/auth-token.ts","../../server/src/services/api-key-store.ts","../../server/src/trpc/routers/health.ts","../../server/src/trpc/routers/project.ts","../../server/src/services/project-store.ts","../../server/src/services/environment-overrides-store.ts","../../server/src/services/environment-resolver.ts","../../server/src/services/audit-service.ts","../../server/src/trpc/routers/service.ts","../../server/src/services/settings-manager.ts","../../server/src/trpc/routers/agent.ts","../../server/src/trpc/routers/process.ts","../../server/src/trpc/routers/audit.ts","../../server/src/trpc/routers/setup.ts","../../server/src/trpc/routers/environment.ts","../../server/src/trpc/routers/settings.ts","../../server/src/trpc/routers/editor.ts","../../server/src/services/user-config-manager.ts","../../server/src/trpc/routers/api-keys.ts","../../server/src/trpc/routers/chat.ts","../../../packages/ai-capabilities/src/capabilities.ts","../../../packages/ai-capabilities/src/adapters/anthropic.ts","../../../packages/ai-capabilities/src/adapters/openai.ts","../../../packages/ai-capabilities/src/adapters/prompt.ts","../../../packages/ai-capabilities/src/trpc-caller.ts","../../server/src/services/ai-runners/runeya-api-docs.ts","../../server/src/services/claude-transcript-sync.ts","../../server/src/services/conversation-store.ts","../../server/src/services/codex-sessions.ts","../../server/src/trpc/shared-schemas.ts","../../server/src/services/llms-txt-generator.ts","../../server/src/services/chat-tools.ts","../../server/src/services/claude-usage.ts","../../server/src/services/codex-usage.ts","../../server/src/services/active-session-registry.ts","../../server/src/services/scenario-store.ts","../../server/src/services/scenario-run-store.ts","../../server/src/services/run-store-utils.ts","../../server/src/services/ai-provider-utils.ts","../../server/src/services/image-storage.service.ts","../../server/src/services/message-images.ts","../../server/src/services/kanban-commands.ts","../../server/src/trpc/routers/cloud-auth.ts","../../server/src/services/cloud-session-store.ts","../../server/src/services/kanban-store.ts","../../server/src/services/ai-runners/claude-code-runner.ts","../../server/src/services/ai-runners/scenario-tokens.ts","../../server/src/services/ai-runners/claude-pty-runner.ts","../../server/src/services/ai-runners/claude-pty-tail.ts","../../server/src/services/ai-runners/codex-app-server-client.ts","../../server/src/services/ai-runners/codex-runner.ts","../../server/src/trpc/routers/git.ts","../../server/src/trpc/routers/scenario.ts","../../server/src/trpc/crud-procedure-utils.ts","../../server/src/trpc/ai-generation-procedure-utils.ts","../../server/src/services/ai-generation.ts","../../server/src/services/scenario-runner.ts","../../server/src/services/scenario-presets.ts","../../server/src/trpc/routers/debug.ts","../../server/src/trpc/routers/kanban-queue.ts","../../server/src/services/kanban-queue.ts","../../server/src/trpc/routers/kanban.ts","../../server/src/trpc/routers/terminal.ts","../../server/src/trpc/routers/utility.ts","../../server/src/trpc/routers/wiki.ts","../../server/src/trpc/routers/config.ts","../../server/src/trpc/routers/cloud-sync.ts","../../server/src/services/cloud-sync-store.ts","../../server/src/services/cloud-sync-bridge.ts","../../server/src/services/master-password.ts","../../server/src/trpc/router.ts","../../server/src/middleware/error-handler.ts","../../server/src/services/migration-engine.ts","../../server/src/services/file-security.ts","../../server/src/utils/ensure-data-gitignore.ts","../../server/src/migrations/migrate-from-legacy.ts","../../server/src/services/server-state.ts","../../server/src/services/openapi.ts","../../server/src/services/image-cleanup.service.ts","../../server/src/index.ts","../../server/src/commands/pull-env.ts"],"sourcesContent":["import express from 'express';\nimport cors from 'cors';\nimport { createServer, type Server } from 'node:http';\nimport { resolve } from 'node:path';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport { createExpressMiddleware } from '@trpc/server/adapters/express';\nimport { applyWSSHandler } from '@trpc/server/adapters/ws';\nimport { appRouter } from './trpc/router.js';\nimport { createContext } from './trpc/trpc.js';\nimport { getCloudApiUrl } from './trpc/routers/cloud-auth.js';\nimport { cloudSessionStore } from './services/cloud-session-store.js';\nimport { errorHandler } from './middleware/error-handler.js';\nimport { agentManager } from './services/agent-manager.js';\nimport { agentSpawner } from './services/agent-spawner.js';\nimport { startClaudeTranscriptWatcher, stopClaudeTranscriptWatcher } from './services/claude-transcript-sync.js';\nimport { settingsManager } from './services/settings-manager.js';\nimport { migrationEngine } from './services/migration-engine.js';\nimport { ensureFilePermissions } from './services/file-security.js';\nimport { auditService } from './services/audit-service.js';\nimport { environmentStore } from './services/environment-store.js';\nimport { ensureDataGitignore } from './utils/ensure-data-gitignore.js';\nimport { projectStore } from './services/project-store.js';\nimport { cloudSyncBridge } from './services/cloud-sync-bridge.js';\nimport { serviceStore } from './services/service-store.js';\nimport { runLegacyMigration, runOverrideOnlyMigration, findLegacyKeyInBackup } from './migrations/migrate-from-legacy.js';\nimport { env } from './config/env.js';\nimport {\n setEncryptionKeyInMemory,\n loadFromEnv,\n hasEncryptionKey,\n isCiMode,\n setPendingLegacyKey,\n getPendingLegacyKey,\n clearPendingLegacyKey,\n hasPendingLegacyKey,\n} from './utils/encryption-key.js';\nimport {\n generateJwtSecret,\n signJwt,\n verifyJwt,\n getJwtSecretGeneratedAt,\n} from './services/auth-token.js';\nimport {\n writeEncryptedKey,\n readEncryptedKey,\n writeVerifyFile,\n verifyEncryptionKey,\n hasEncryptedKeyFile,\n hasVerifyFile,\n} from './services/master-password.js';\nimport { getServerState } from './services/server-state.js';\nimport { apiKeyStore } from './services/api-key-store.js';\nimport { generateLlmsTxt } from './services/llms-txt-generator.js';\nimport { getOpenApiDocument } from './services/openapi.js';\nimport rateLimit from 'express-rate-limit';\nimport { existsSync, createReadStream } from 'node:fs';\nimport { mkdir } from 'node:fs/promises';\nimport multer from 'multer';\nimport { imageStorageService, ALLOWED_MIME_TYPES, MAX_IMAGE_SIZE_BYTES } from './services/image-storage.service.js';\nimport { imageCleanupService } from './services/image-cleanup.service.js';\n\nexport interface ServerInstance {\n app: express.Express;\n server: Server;\n wss: WebSocketServer;\n shutdown: () => Promise<void>;\n}\n\nfunction csrfMiddleware(req: express.Request, res: express.Response, next: express.NextFunction): void {\n const contentType = req.headers['content-type'] ?? '';\n if (!contentType.includes('application/json')) {\n res.status(415).json({ error: 'Content-Type must be application/json' });\n return;\n }\n const origin = req.headers['origin'];\n if (origin) {\n const allowedOrigins = [\n `http://localhost:${env.PORT}`,\n `http://127.0.0.1:${env.PORT}`,\n 'http://localhost:5173', // dev Vite\n 'http://127.0.0.1:5173',\n ];\n // In LAN mode, allow any origin pointing to the server port (e.g. tablet on local network)\n if (env.RUNEYA_LAN_PROXY) {\n try {\n const parsed = new URL(origin);\n const originPort = parsed.port || (parsed.protocol === 'https:' ? '443' : '80');\n if (originPort === String(env.PORT) || originPort === '5173') {\n next();\n return;\n }\n } catch {\n // invalid origin URL — fall through to deny\n }\n }\n if (!allowedOrigins.includes(origin)) {\n res.status(403).json({ error: 'Forbidden origin' });\n return;\n }\n }\n next();\n}\n\nconst authLimiter = rateLimit({\n windowMs: 15 * 60 * 1000,\n max: 5,\n standardHeaders: true,\n legacyHeaders: false,\n message: { error: 'Trop de tentatives. Réessayez dans 15 minutes.' },\n});\n\nconst llmsLimiter = rateLimit({\n windowMs: 60 * 1000, // 1 minute\n max: 60,\n standardHeaders: true,\n legacyHeaders: false,\n message: { error: 'Rate limit exceeded. Retry in 1 minute.' },\n});\n\nexport async function createLocalServer(): Promise<ServerInstance> {\n // Generate JWT signing secret first\n generateJwtSecret();\n\n // Load encryption key from env var (CI mode) or check state\n const ciMode = await loadFromEnv();\n\n // Run legacy migration FIRST — loads key temporarily, re-encrypts, then stores in pending holder\n await runLegacyMigration(env.DATA_DIR);\n\n // Handle server restart between migration and setup:\n // The pending key is in-memory only, so recover it from backup if needed.\n // Only attempt recovery if .runeya-verify doesn't exist — if it does, setup\n // was already completed at least once and we should not treat this as a migration.\n if (!ciMode && !hasPendingLegacyKey() && !(await hasEncryptedKeyFile(env.DATA_DIR)) && !(await hasVerifyFile(env.DATA_DIR))) {\n const recoveredKey = await findLegacyKeyInBackup(env.DATA_DIR);\n if (recoveredKey) {\n setPendingLegacyKey(recoveredKey);\n console.log('[server] Legacy key recovered from backup — setup required to migrate');\n }\n }\n\n if (!ciMode) {\n const { state } = await getServerState();\n if (state === 'locked') {\n console.log('[server] Serveur verrouillé — master password requis');\n } else if (state === 'setup') {\n console.log('[server] Premier lancement — setup requis');\n }\n }\n\n if(!existsSync(env.DATA_DIR)) await mkdir(env.DATA_DIR);\n const absoluteDataDir = resolve(env.DATA_DIR);\n console.log(`[server] Data directory: ${absoluteDataDir}`);\n // Ensure data/.gitignore exists (prevents committing secrets & backups)\n await ensureDataGitignore(env.DATA_DIR);\n\n // Initialize settings and run migrations\n await settingsManager.getSettings();\n await migrationEngine.run();\n\n // Enforce secure file permissions on sensitive data files\n await ensureFilePermissions();\n\n // Clean up old audit log entries\n auditService.cleanup().catch((err) => console.error('[server] Audit cleanup failed:', err));\n\n const app = express();\n\n // CORS: restrict to localhost in dev, configurable via env\n // In LAN mode, allow any origin pointing to the server port or Vite dev port\n const corsOrigin = env.CORS_ORIGIN ?? (env.RUNEYA_LAN_PROXY\n ? (origin: string | undefined, cb: (err: Error | null, allow?: boolean) => void) => {\n if (!origin) { cb(null, false); return; }\n try {\n const parsed = new URL(origin);\n const port = parsed.port || (parsed.protocol === 'https:' ? '443' : '80');\n cb(null, port === String(env.PORT) || port === '5173');\n } catch {\n cb(null, false);\n }\n }\n : 'http://localhost:5173');\n app.use(cors({\n origin: corsOrigin,\n credentials: true,\n }));\n\n // Called once after the encryption key is set in memory (unlock or setup).\n // Idempotent: safe to call even if already done.\n let postUnlockDone = false;\n async function runPostUnlock(): Promise<void> {\n if (postUnlockDone) return;\n postUnlockDone = true;\n\n await runOverrideOnlyMigration(env.DATA_DIR);\n\n if (env.MODE === 'local-simple') {\n const projects = await projectStore.list();\n if (projects.length === 0) {\n const project = await projectStore.create({\n name: 'My Local Project',\n description: 'Auto-generated default project for local development',\n });\n const localEnv = await environmentStore.create({\n projectId: project.id,\n name: 'Local',\n description: 'Default local environment (immutable)',\n variables: {},\n parentIds: [],\n color: '#22c55e',\n immutable: true,\n });\n await projectStore.update({\n id: project.id,\n environmentIds: [localEnv.id],\n activeEnvironmentId: localEnv.id,\n });\n console.log('[server] Created default project with Local environment');\n }\n }\n\n // Initialize agent manager (loads persisted remote agents — requires encryption key)\n await agentManager.init();\n\n await agentSpawner.spawnLocalAgent();\n\n // Watch Claude Code's on-disk transcripts so PTY conversations stay\n // synced live with the non-PTY message view.\n startClaudeTranscriptWatcher().catch((err) => {\n console.warn('[server] Failed to start Claude transcript watcher:', err);\n });\n\n // Start continuous project sync for every linked organization (requires the\n // encryption key, now loaded, to decrypt stored sync tokens).\n cloudSyncBridge.start().catch((err) => {\n console.warn('[server] Failed to start cloud sync bridge:', err);\n });\n }\n\n // If key is already available at startup (CI mode or legacy plaintext key), run now\n if (hasEncryptionKey()) {\n await runPostUnlock();\n }\n\n // GET /api/status — public\n app.get('/api/status', async (_req, res) => {\n try {\n const state = await getServerState();\n res.json({ ...state, ciMode: isCiMode() });\n } catch {\n res.status(500).json({ error: 'Internal server error' });\n }\n });\n\n // GET /api/cloud/callback — lands here from the cloud authorization page,\n // carrying a single-use token. Exchanges it for a session token, which stays\n // on this server: the browser never receives a cloud credential.\n app.get('/api/cloud/callback', authLimiter, async (req, res) => {\n const token = typeof req.query['token'] === 'string' ? req.query['token'] : null;\n const state = typeof req.query['state'] === 'string' ? req.query['state'] : null;\n if (!token || !state) {\n res.status(400).send('Missing token or state.');\n return;\n }\n // Binds the callback to a login this server started; also stops a stray\n // redirect from installing someone else's token.\n const returnTo = cloudSessionStore.consumeState(state);\n if (!returnTo) {\n res.status(400).send('Unknown or expired login attempt. Please start again.');\n return;\n }\n try {\n const verifyRes = await fetch(`${getCloudApiUrl()}/api/auth/one-time-token/verify`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ token }),\n signal: AbortSignal.timeout(15_000),\n });\n if (!verifyRes.ok) {\n res.status(401).send('The cloud rejected this login token.');\n return;\n }\n // The bearer plugin exposes the SIGNED session token here. The JSON body\n // carries the raw, unsigned one, which `bearer({ requireSignature: true })`\n // would reject — so this header is the only usable source.\n const sessionToken = verifyRes.headers.get('set-auth-token');\n if (!sessionToken) {\n res.status(502).send('The cloud did not return a session token.');\n return;\n }\n await cloudSessionStore.set(getCloudApiUrl(), sessionToken);\n // Sync authenticates with this session, so a fresh sign-in is exactly what\n // links paused on a rejected session were waiting for.\n void cloudSyncBridge.resumeAll();\n res.redirect(`${returnTo}?cloud=linked`);\n } catch {\n res.status(502).send('Could not reach the Runeya cloud.');\n }\n });\n\n // GET /api/cloud/{chat,kanban}/stream — proxies the cloud's SSE streams.\n // EventSource cannot send an Authorization header, so the local JWT travels\n // as a query param, exactly as the tRPC WebSocket already does. The cloud\n // token itself never leaves this process — it is attached here.\n function proxyCloudStream(localPath: string, upstreamPath: string): void {\n app.get(localPath, async (req, res) => {\n const jwt = typeof req.query['token'] === 'string' ? req.query['token'] : '';\n try {\n await verifyJwt(jwt);\n } catch {\n res.status(401).end();\n return;\n }\n const organizationId = typeof req.query['organizationId'] === 'string' ? req.query['organizationId'] : '';\n if (!organizationId) {\n res.status(400).end();\n return;\n }\n const token = await cloudSessionStore.getToken();\n if (!token) {\n res.status(401).end();\n return;\n }\n // Long-lived stream: aborted when the browser disconnects, not on a timeout.\n const upstreamAbort = new AbortController();\n req.on('close', () => upstreamAbort.abort());\n try {\n const upstream = await fetch(\n `${getCloudApiUrl()}${upstreamPath}?organizationId=${encodeURIComponent(organizationId)}`,\n {\n headers: { Authorization: `Bearer ${token}`, Accept: 'text/event-stream' },\n signal: upstreamAbort.signal,\n },\n );\n if (!upstream.ok || !upstream.body) {\n res.status(upstream.status === 401 ? 401 : 502).end();\n return;\n }\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n Connection: 'keep-alive',\n 'X-Accel-Buffering': 'no',\n });\n const reader = upstream.body.getReader();\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n // nosemgrep: direct-response-write -- relais d'un flux SSE amont (text/event-stream), octets opaques, jamais du HTML\n res.write(value);\n }\n res.end();\n } catch {\n // Client disconnect or upstream failure — nothing left to send.\n if (!res.headersSent) res.status(502).end();\n else res.end();\n }\n });\n }\n\n // POST /api/cloud/kanban/image — relays a card attachment to the cloud, which\n // stores it in S3. The browser has no cloud credential, so the token is\n // attached here; the JWT in the query is what proves the local session, as on\n // the streams above.\n // The body limit here is only a memory guard, deliberately above the cloud's\n // own cap (55 MB, MAX_ATTACHMENT_BYTES): the cloud is the single authority on\n // what is too large, and it answers with a clear message. A tighter limit here\n // would reject the file first, with a bare 413 and no explanation.\n app.post(\n '/api/cloud/kanban/image',\n express.raw({ type: () => true, limit: '64mb' }),\n async (req, res) => {\n const jwt = typeof req.query['token'] === 'string' ? req.query['token'] : '';\n try {\n await verifyJwt(jwt);\n } catch {\n res.status(401).end();\n return;\n }\n const organizationId = typeof req.query['organizationId'] === 'string' ? req.query['organizationId'] : '';\n if (!organizationId) {\n res.status(400).end();\n return;\n }\n const token = await cloudSessionStore.getToken();\n if (!token) {\n res.status(401).end();\n return;\n }\n // The original file name has to be forwarded too: the cloud stores it and\n // serves it back in Content-Disposition. Dropping it here is what made\n // every attachment land as \"file\".\n const upstreamQuery = new URLSearchParams({ organizationId });\n if (typeof req.query['name'] === 'string') upstreamQuery.set('name', req.query['name']);\n try {\n const upstream = await fetch(\n `${getCloudApiUrl()}/api/kanban/image?${upstreamQuery.toString()}`,\n {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': String(req.headers['content-type'] ?? 'application/octet-stream'),\n },\n body: req.body as Buffer,\n // A 55 MB body over a home upstream link takes minutes, not seconds.\n signal: AbortSignal.timeout(300_000),\n },\n );\n res.status(upstream.status).json(await upstream.json().catch(() => ({})));\n } catch {\n res.status(502).json({ error: 'upload-failed' });\n }\n },\n );\n\n // GET /api/cloud/kanban/file/:id — relays an attachment's bytes. Reading is\n // authenticated on the cloud side, and the browser holds no cloud credential,\n // so the local JWT proves the session here and the cloud token is added on\n // the way out.\n // DELETE goes through the same shape: the browser proves the local session\n // with its JWT, the cloud token is added here.\n app.delete('/api/cloud/kanban/file/:id', async (req, res) => {\n const jwt = typeof req.query['token'] === 'string' ? req.query['token'] : '';\n try {\n await verifyJwt(jwt);\n } catch {\n res.status(401).end();\n return;\n }\n const token = await cloudSessionStore.getToken();\n if (!token) {\n res.status(401).end();\n return;\n }\n try {\n const upstream = await fetch(\n `${getCloudApiUrl()}/api/kanban/file/${encodeURIComponent(req.params.id)}`,\n { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, signal: AbortSignal.timeout(15_000) },\n );\n res.status(upstream.status).end();\n } catch {\n res.status(502).end();\n }\n });\n\n app.get('/api/cloud/kanban/file/:id', async (req, res) => {\n const jwt = typeof req.query['token'] === 'string' ? req.query['token'] : '';\n try {\n await verifyJwt(jwt);\n } catch {\n res.status(401).end();\n return;\n }\n const token = await cloudSessionStore.getToken();\n if (!token) {\n res.status(401).end();\n return;\n }\n try {\n const upstream = await fetch(\n `${getCloudApiUrl()}/api/kanban/file/${encodeURIComponent(req.params.id)}`,\n { headers: { Authorization: `Bearer ${token}` }, signal: AbortSignal.timeout(300_000) },\n );\n if (!upstream.ok) {\n res.status(upstream.status).end();\n return;\n }\n res.set('Content-Type', upstream.headers.get('content-type') ?? 'application/octet-stream');\n const disposition = upstream.headers.get('content-disposition');\n if (disposition) res.set('Content-Disposition', disposition);\n res.set('X-Content-Type-Options', 'nosniff');\n res.set('Content-Security-Policy', \"default-src 'none'; sandbox\");\n // nosemgrep: direct-response-write -- relais d'octets de pièce jointe, en-têtes de durcissement conservés\n res.send(Buffer.from(await upstream.arrayBuffer()));\n } catch {\n res.status(502).end();\n }\n });\n\n proxyCloudStream('/api/cloud/chat/stream', '/api/chat/stream');\n proxyCloudStream('/api/cloud/kanban/stream', '/api/kanban/stream');\n\n // POST /api/unlock — public, rate limited + CSRF\n app.post('/api/unlock', authLimiter, csrfMiddleware, express.json({ limit: '10kb' }), async (req, res) => {\n try {\n const body = req.body as { masterPassword?: unknown };\n const masterPassword = body.masterPassword;\n if (typeof masterPassword !== 'string' || masterPassword.length < 1 || masterPassword.length > 1024) {\n res.status(400).json({ error: 'masterPassword invalide' });\n return;\n }\n const encKey = await readEncryptedKey(env.DATA_DIR, masterPassword);\n setEncryptionKeyInMemory(encKey);\n await runPostUnlock();\n const token = await signJwt();\n res.json({ token });\n } catch (err) {\n console.error('[server] Unlock error:', err);\n res.status(401).json({ error: 'Master password incorrect' });\n }\n });\n\n // POST /api/setup — public, rate limited + CSRF\n app.post('/api/setup', authLimiter, csrfMiddleware, express.json({ limit: '10kb' }), async (req, res) => {\n try {\n const { state, hasVerifyFile: hasVerify, isLegacyMigration } = await getServerState();\n\n // Reject if already unlocked\n if (state === 'unlocked') {\n res.status(409).json({ error: 'Serveur déjà déverrouillé' });\n return;\n }\n\n const body = req.body as { masterPassword?: unknown; encryptionKey?: unknown };\n const masterPassword = body.masterPassword;\n if (typeof masterPassword !== 'string' || masterPassword.length < 1 || masterPassword.length > 1024) {\n res.status(400).json({ error: 'masterPassword invalide' });\n return;\n }\n\n let encKey: Buffer;\n\n if (isLegacyMigration) {\n // Read pending legacy key from in-memory holder\n const legacyKey = getPendingLegacyKey();\n if (!legacyKey) {\n res.status(500).json({ error: 'Clé legacy introuvable — redémarrez le serveur' });\n return;\n }\n encKey = legacyKey;\n } else if (hasVerify) {\n // New member: encryptionKey required\n const encryptionKeyHex = body.encryptionKey;\n if (typeof encryptionKeyHex !== 'string' || !/^[0-9a-f]{64}$/i.test(encryptionKeyHex)) {\n res.status(400).json({ error: 'encryptionKey invalide (attendu 64 hex)' });\n return;\n }\n encKey = Buffer.from(encryptionKeyHex, 'hex');\n // Verify against canary\n await verifyEncryptionKey(env.DATA_DIR, encKey);\n } else {\n // Fresh setup: generate new key or use provided key\n if (body.encryptionKey !== undefined) {\n const encryptionKeyHex = body.encryptionKey;\n if (typeof encryptionKeyHex !== 'string' || !/^[0-9a-f]{64}$/i.test(encryptionKeyHex)) {\n res.status(400).json({ error: 'encryptionKey invalide (attendu 64 hex)' });\n return;\n }\n encKey = Buffer.from(encryptionKeyHex, 'hex');\n } else {\n const { randomBytes } = await import('node:crypto');\n encKey = randomBytes(32);\n }\n }\n\n // Write .encryption.key.enc\n await writeEncryptedKey(env.DATA_DIR, masterPassword, encKey);\n\n // Verify round-trip (critical for legacy migration)\n const readBack = await readEncryptedKey(env.DATA_DIR, masterPassword);\n if (!readBack.equals(encKey)) {\n res.status(500).json({ error: 'Erreur de vérification round-trip — opération annulée' });\n return;\n }\n\n // Write .runeya-verify if not exists\n if (!hasVerify) {\n await writeVerifyFile(env.DATA_DIR, encKey);\n }\n\n setEncryptionKeyInMemory(encKey);\n if (isLegacyMigration) {\n clearPendingLegacyKey();\n }\n await runPostUnlock();\n const token = await signJwt();\n res.json({ token });\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Erreur interne';\n if (message.includes('incorrecte')) {\n res.status(400).json({ error: message });\n } else {\n console.error('[server] Setup error:', err);\n res.status(500).json({ error: 'Erreur interne' });\n }\n }\n });\n\n // GET /:apikey/llms.txt — LLM API keys scopées\n app.get('/:apikey/llms.txt', llmsLimiter, async (req, res) => {\n const apikey = Array.isArray(req.params['apikey']) ? req.params['apikey'][0] : req.params['apikey'];\n // Validate format first — always 401 to avoid oracle\n if (!apikey || !/^[0-9a-f]{64}$/i.test(apikey)) {\n res.status(401).send('Unauthorized');\n return;\n }\n try {\n const key = await apiKeyStore.validateKey(apikey);\n if (!key) {\n res.status(401).send('Unauthorized');\n return;\n }\n if (!hasEncryptionKey()) {\n res.setHeader('Content-Type', 'text/plain; charset=utf-8');\n res.setHeader('Cache-Control', 'no-store');\n const uiUrl = process.env.NODE_ENV === 'development' ? 'http://localhost:5173' : `http://localhost:${env.PORT}`;\n res.status(503).send(`# Runeya — Service Management API\\n\\n> Server is locked. Unlock with your master password at ${uiUrl} to access the full service list.\\n`);\n return;\n }\n const allServices = await serviceStore.list();\n const services = allServices.filter(s =>\n key.scopes.services.some(p => p.serviceId === s.id),\n );\n\n const content = generateLlmsTxt(key, services);\n res.setHeader('Content-Type', 'text/plain; charset=utf-8');\n res.setHeader('Cache-Control', 'no-store');\n res.send(content);\n } catch (err) {\n console.error('[server] llms.txt error:', err);\n res.status(500).send('Internal server error');\n }\n });\n\n // GET /api/docs — Scalar API reference UI (standalone HTML, no auth required)\n app.get('/api/docs', (req, res) => {\n const dark = req.query['dark'] === '1';\n res.setHeader('Content-Type', 'text/html; charset=utf-8');\n res.setHeader('Cache-Control', 'no-store');\n res.send(`<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>Runeya API Docs</title>\n <meta name=\"description\" content=\"Runeya service management API reference\" />\n <style>\n body { margin: 0; }\n </style>\n</head>\n<body>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n <script>\n Scalar.createApiReference(document.body, {\n url: '/api/openapi.json',\n darkMode: ${dark},\n layout: 'modern',\n defaultHttpClient: { targetKey: 'shell', clientKey: 'curl' },\n defaultOpenAllTags: false,\n persistAuth: true,\n agent: { disabled: true },\n metaData: {\n title: 'Runeya API Docs',\n description: 'Runeya service management API reference',\n ogTitle: 'Runeya API Docs',\n ogDescription: 'Runeya service management API reference',\n },\n });\n </script>\n</body>\n</html>`);\n });\n\n // GET /api/openapi.json — OpenAPI specification (public, no auth required)\n app.get('/api/openapi.json', (_req, res) => {\n try {\n res.json(getOpenApiDocument());\n } catch (err) {\n console.error('[server] openapi.json error:', err instanceof Error ? err.stack : err);\n res.status(500).json({ error: 'Failed to generate OpenAPI document', detail: err instanceof Error ? err.message : String(err) });\n }\n });\n\n // ── Image upload & serve endpoints ──────────────────────────────────────\n const memStorage = multer.memoryStorage();\n const upload = multer({\n storage: memStorage,\n limits: { fileSize: MAX_IMAGE_SIZE_BYTES },\n fileFilter: (_req, file, cb) => {\n if (ALLOWED_MIME_TYPES.has(file.mimetype)) {\n cb(null, true);\n } else {\n cb(new Error(`Unsupported MIME type: ${file.mimetype}`));\n }\n },\n });\n\n const CONV_ID_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/;\n const IMAGE_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n // Les erreurs de multer (MIME refusé par fileFilter, dépassement de taille)\n // sont des erreurs client : sans ce wrapper elles remontent au gestionnaire\n // d'erreurs global, qui répond 500 « Internal server error ».\n const uploadSingleImage = (req: express.Request, res: express.Response, next: express.NextFunction) => {\n upload.single('image')(req, res, (err: unknown) => {\n if (err) {\n const isTooLarge = (err as { code?: string }).code === 'LIMIT_FILE_SIZE';\n const message = err instanceof Error ? err.message : 'Upload failed';\n res.status(isTooLarge ? 413 : 400).json({ error: message });\n return;\n }\n next();\n });\n };\n\n app.post('/api/images/upload', uploadSingleImage, async (req, res) => {\n try {\n if (!req.file) {\n res.status(400).json({ error: 'No image file provided' });\n return;\n }\n const conversationId = (req.query?.['conversationId'] ?? req.body?.conversationId) as string | undefined;\n if (!conversationId || !CONV_ID_RE.test(conversationId)) {\n res.status(400).json({ error: 'Missing or invalid conversationId' });\n return;\n }\n const stored = await imageStorageService.saveImage(\n req.file.buffer,\n req.file.originalname,\n req.file.mimetype,\n conversationId,\n );\n res.json({\n imageId: stored.imageId,\n url: `/api/images/${conversationId}/${stored.imageId}`,\n mimeType: stored.mimeType,\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Upload failed';\n res.status(400).json({ error: message });\n }\n });\n\n app.get('/api/images/:conversationId/:imageId', async (req, res) => {\n try {\n const { conversationId, imageId } = req.params as { conversationId: string; imageId: string };\n if (!conversationId || !CONV_ID_RE.test(conversationId)) {\n res.status(400).json({ error: 'Invalid conversationId' });\n return;\n }\n if (!imageId || !IMAGE_ID_RE.test(imageId)) {\n res.status(400).json({ error: 'Invalid imageId' });\n return;\n }\n // Le conversationId de l'URL doit correspondre au contexte enregistré :\n // sans ça le scoping par conversation n'est que décoratif.\n const result = await imageStorageService.getImagePath(imageId, conversationId);\n if (!result) {\n res.status(404).json({ error: 'Image not found' });\n return;\n }\n res.setHeader('Content-Type', result.mimeType);\n res.setHeader('Cache-Control', 'no-store');\n createReadStream(result.filePath).pipe(res);\n } catch (err) {\n console.error('[server] image serve error:', err);\n res.status(500).json({ error: 'Internal server error' });\n }\n });\n\n // tRPC HTTP handler\n app.use('/api/trpc', createExpressMiddleware({\n router: appRouter,\n createContext,\n }));\n\n // Global error handler\n app.use(errorHandler);\n\n const server = createServer(app);\n\n // tRPC WebSocket handler — noServer mode so we control the upgrade\n const wss = new WebSocketServer({ noServer: true });\n applyWSSHandler({\n wss,\n router: appRouter,\n createContext: ({ req }) => {\n const headerAuth = req.headers.authorization ?? null;\n // Browser WebSocket can't set headers — also accept token from query param\n const urlObj = new URL(req.url ?? '/', `http://localhost:${env.PORT}`);\n const queryToken = urlObj.searchParams.get('token');\n const queryAuth = queryToken ? `Bearer ${queryToken}` : null;\n return { authorization: headerAuth ?? queryAuth };\n },\n });\n\n // Registry of active WS connections (stores only exp + iat, never the JWT)\n interface WsConnMeta { exp: number; iat: number; }\n const wsConnRegistry = new Map<WebSocket, WsConnMeta>();\n\n // Intercept HTTP→WS upgrade: validate JWT BEFORE handleUpgrade (spec Point 3)\n // Mirror protectedProcedure: skip JWT check when encryption key is in memory\n // (covers both CI mode and normal mode after master-password unlock).\n server.on('upgrade', async (req, socket, head) => {\n const auth = req.headers['authorization'] as string | undefined;\n const headerToken = auth?.startsWith('Bearer ') ? auth.slice(7) : null;\n // Browser WebSocket API can't set headers — accept token from query param as fallback\n const urlObj = new URL(req.url ?? '/', `http://localhost:${env.PORT}`);\n const queryToken = urlObj.searchParams.get('token');\n const token = headerToken ?? queryToken;\n\n if (!hasEncryptionKey()) {\n // Encryption key not in memory — require JWT (not yet unlocked)\n if (!token) {\n socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');\n socket.destroy();\n return;\n }\n try {\n await verifyJwt(token);\n } catch {\n socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');\n socket.destroy();\n return;\n }\n }\n\n wss.handleUpgrade(req, socket, head, (ws) => {\n wss.emit('connection', ws, req);\n });\n });\n\n // Register connection — JWT already verified at upgrade, safe to use verifyJwt for exp/iat\n wss.on('connection', (ws, req) => {\n const auth = req.headers['authorization'] as string | undefined;\n const headerToken = auth?.startsWith('Bearer ') ? auth.slice(7) : null;\n const urlObj2 = new URL(req.url ?? '/', `http://localhost:${env.PORT}`);\n const token = headerToken ?? urlObj2.searchParams.get('token');\n if (token) {\n verifyJwt(token).then(({ exp, iat }) => {\n wsConnRegistry.set(ws, { exp, iat });\n }).catch(() => {});\n }\n ws.on('close', () => wsConnRegistry.delete(ws));\n });\n\n // Tick every 30s — close expired connections\n const wsTickInterval = setInterval(() => {\n const now = Math.floor(Date.now() / 1000);\n const secretGeneratedAt = getJwtSecretGeneratedAt();\n for (const [ws, meta] of wsConnRegistry) {\n if (meta.exp <= now || meta.iat < secretGeneratedAt) {\n ws.close(4401, 'JWT expired or signing secret rotated');\n wsConnRegistry.delete(ws);\n }\n }\n }, 30_000);\n\n const shutdown = async () => {\n console.log('[server] Shutting down...');\n clearInterval(wsTickInterval);\n stopClaudeTranscriptWatcher();\n imageCleanupService.stop();\n cloudSyncBridge.stopAll();\n // Kill agent immediately (SIGKILL, stateless) and close WS bridges in parallel\n await Promise.all([\n agentSpawner.shutdown(),\n agentManager.shutdown(),\n ]);\n // Force-close all active connections so the port is released instantly\n server.closeAllConnections();\n await Promise.race([\n new Promise<void>((resolve) => wss.close(() => resolve())),\n new Promise<void>((resolve) => setTimeout(resolve, 2_000)),\n ]);\n await Promise.race([\n new Promise<void>((resolve) => server.close(() => resolve())),\n new Promise<void>((resolve) => setTimeout(resolve, 2_000)),\n ]);\n console.log('[server] Shutdown complete');\n };\n\n return { app, server, wss, shutdown };\n}\n","import { initTRPC, TRPCError } from '@trpc/server';\nimport type { OpenApiMeta } from 'trpc-to-openapi';\nimport type { CreateExpressContextOptions } from '@trpc/server/adapters/express';\nimport { verifyJwt } from '../services/auth-token.js';\nimport { hasEncryptionKey, isCiMode } from '../utils/encryption-key.js';\nimport { apiKeyStore } from '../services/api-key-store.js';\nimport type { ApiKey, ApiServiceAction, ApiEnvAction } from '@runeya/packages-shared';\n\ntype CallerType = 'app' | 'api';\n\nexport function createContext({ req }: CreateExpressContextOptions) {\n return {\n authorization: req.headers.authorization ?? null,\n };\n}\n\ntype Context = Awaited<ReturnType<typeof createContext>>;\n\nexport type AuthContext = Context & {\n callerType: CallerType;\n apiKey: ApiKey | null;\n};\n\nconst t = initTRPC.context<Context>().meta<OpenApiMeta>().create({\n errorFormatter({ shape, error }) {\n return {\n ...shape,\n data: {\n ...shape.data,\n message: error.message,\n },\n };\n },\n});\n\nexport const router = t.router;\nexport const publicProcedure = t.procedure;\n\nconst API_KEY_REGEX = /^[0-9a-f]{64}$/i;\n\nconst authMiddleware = t.middleware(async ({ ctx, next }) => {\n const { authorization } = ctx;\n\n // API API key: 64 hex chars — checked before the JWT/encryption-key bypass\n if (authorization?.startsWith('Bearer ') && API_KEY_REGEX.test(authorization.slice(7))) {\n if (!hasEncryptionKey()) {\n throw new TRPCError({ code: 'PRECONDITION_FAILED', message: 'Server is locked — master password must be unlocked before using API API keys' });\n }\n const token = authorization.slice(7);\n const apiKey = await apiKeyStore.validateKey(token);\n if (!apiKey) {\n throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Invalid API API key' });\n }\n return next({ ctx: { ...ctx, callerType: 'api' as CallerType, apiKey } });\n }\n\n // CI mode: key loaded from RUNEYA_ENCRYPTION_KEY env var — no JWT in circulation, bypass auth.\n if (isCiMode()) {\n return next({ ctx: { ...ctx, callerType: 'app' as CallerType, apiKey: null } });\n }\n\n if (!authorization?.startsWith('Bearer ')) {\n throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Missing or invalid Authorization header' });\n }\n\n const token = authorization.slice(7);\n\n try {\n await verifyJwt(token);\n } catch {\n throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Invalid or expired token' });\n }\n\n return next({ ctx: { ...ctx, callerType: 'app' as CallerType, apiKey: null } });\n});\n\nexport const protectedProcedure = t.procedure.use(authMiddleware);\n\n// ---------------------------------------------------------------------------\n// API scope enforcement helpers\n// Call these at the top of route handlers that API callers can reach.\n// App callers (callerType === 'app') always pass through.\n// ---------------------------------------------------------------------------\n\n/** Throw FORBIDDEN if an API caller lacks `action` on `serviceId`. */\nexport function requireServiceAction(\n ctx: AuthContext,\n serviceId: string,\n action: ApiServiceAction,\n): void {\n if (ctx.callerType !== 'api') return;\n const perm = ctx.apiKey!.scopes.services.find(p => p.serviceId === serviceId);\n if (!perm?.actions.includes(action)) {\n throw new TRPCError({\n code: 'FORBIDDEN',\n message: `API key lacks '${action}' permission on service ${serviceId}`,\n });\n }\n}\n\n/**\n * Return the set of service IDs an API caller is allowed to see.\n * Returns null for app callers (= all services allowed).\n */\nexport function getAllowedServiceIds(ctx: AuthContext): Set<string> | null {\n if (ctx.callerType !== 'api') return null;\n return new Set(ctx.apiKey!.scopes.services.map(p => p.serviceId));\n}\n\n/**\n * Throw FORBIDDEN if an API caller lacks `action` on `environmentId`.\n * Returns whether secrets are allowed (always true for app callers).\n *\n * @param serviceId - when provided, the check is restricted to the permission entry for that\n * specific service. This prevents cross-service escalation: a global env ID shared across\n * multiple services cannot grant access via a different service's permission entry.\n */\nexport function requireEnvAction(\n ctx: AuthContext,\n environmentId: string,\n action: ApiEnvAction,\n serviceId?: string,\n): { includeSecrets: boolean } {\n if (ctx.callerType !== 'api') return { includeSecrets: true };\n const permsToCheck = serviceId\n ? ctx.apiKey!.scopes.services.filter(p => p.serviceId === serviceId)\n : ctx.apiKey!.scopes.services;\n for (const svcPerm of permsToCheck) {\n const envPerm = svcPerm.environments.find(e => e.environmentId === environmentId);\n if (envPerm?.actions.includes(action)) {\n return { includeSecrets: envPerm.includeSecrets };\n }\n }\n throw new TRPCError({\n code: 'FORBIDDEN',\n message: `API key lacks '${action}' permission on environment ${environmentId}`,\n });\n}\n","import { randomBytes } from 'node:crypto';\nimport { SignJWT, jwtVerify } from 'jose';\n\nlet jwtSecret: Uint8Array | null = null;\nlet jwtSecretGeneratedAt: number = 0; // Unix timestamp seconds\n\nexport function generateJwtSecret(): void {\n jwtSecret = new Uint8Array(randomBytes(32));\n jwtSecretGeneratedAt = Math.floor(Date.now() / 1000);\n}\n\nexport function getJwtSecretGeneratedAt(): number {\n return jwtSecretGeneratedAt;\n}\n\nfunction getJwtSecret(): Uint8Array {\n if (!jwtSecret) throw new Error('JWT secret not yet generated');\n return jwtSecret;\n}\n\n/** Sign a JWT valid for 8 hours */\nexport async function signJwt(): Promise<string> {\n const secret = getJwtSecret();\n return new SignJWT({ sub: 'app' })\n .setProtectedHeader({ alg: 'HS256' })\n .setIssuedAt()\n .setExpirationTime('8h')\n .sign(secret);\n}\n\nexport interface JwtPayload {\n exp: number;\n iat: number;\n}\n\n/** Verify a JWT — throws if invalid/expired */\nexport async function verifyJwt(token: string): Promise<JwtPayload> {\n const secret = getJwtSecret();\n const { payload } = await jwtVerify(token, secret);\n return { exp: payload.exp as number, iat: payload.iat as number };\n}\n","import { randomBytes, randomUUID, timingSafeEqual } from 'node:crypto';\nimport { readFile, writeFile, rename, mkdir, chmod } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { env } from '../config/env.js';\nimport { ApiKeysFileSchema, type ApiKey, type ApiKeyScope, type MaskedApiKey } from '@runeya/packages-shared';\nimport { encryptValue, decryptValue, isEncryptedValue } from './crypto-helpers.js';\n\n/** Strips the secret from a key before it leaves the store. */\nexport function maskApiKey(apiKey: ApiKey): MaskedApiKey {\n const { key, ...rest } = apiKey;\n return { ...rest, keyPreview: key.slice(-4) };\n}\n\nconst FILE_PUBLIC = 'api-keys.json';\nconst FILE_PRIVATE = 'api-keys.private.json';\n\nclass ApiKeyStore {\n private keys: Map<string, ApiKey> = new Map();\n private loaded = false;\n\n private filePath(isPublic: boolean): string {\n return join(env.DATA_DIR, isPublic ? FILE_PUBLIC : FILE_PRIVATE);\n }\n\n private async ensureDir(): Promise<void> {\n await mkdir(env.DATA_DIR, { recursive: true });\n }\n\n private async persistFile(isPublic: boolean): Promise<void> {\n await this.ensureDir();\n const path = this.filePath(isPublic);\n // Le secret est chiffré au repos, comme partout ailleurs dans le serveur :\n // le mode 0600 protège des autres utilisateurs, pas d'une copie du dataDir.\n const keys = Array.from(this.keys.values())\n .filter(k => k.isPublic === isPublic)\n .map(k => ({ ...k, key: encryptValue(k.key) }));\n const tmp = path + '.tmp';\n await writeFile(tmp, JSON.stringify({ keys }, null, 2), 'utf-8');\n await rename(tmp, path);\n await chmod(path, 0o600);\n }\n\n private async persist(isPublic: boolean): Promise<void> {\n await this.persistFile(isPublic);\n }\n\n private async loadFile(path: string): Promise<void> {\n try {\n const raw = await readFile(path, 'utf-8');\n const parsed = ApiKeysFileSchema.safeParse(JSON.parse(raw));\n if (parsed.success) {\n for (const k of parsed.data.keys) {\n // Les fichiers écrits avant le chiffrement contiennent le secret en\n // clair : on les accepte et le prochain persist les rechiffrera.\n const key = isEncryptedValue(k.key) ? decryptValue(k.key) : k.key;\n this.keys.set(k.id, { ...k, key });\n }\n }\n } catch {\n // File doesn't exist yet — start empty\n }\n }\n\n async load(): Promise<void> {\n if (this.loaded) return;\n this.loaded = true;\n await this.loadFile(this.filePath(true));\n await this.loadFile(this.filePath(false));\n }\n\n /**\n * Keys as exposed to callers — secrets stripped. Use `reveal` to obtain one\n * deliberately; never hand the whole set of secrets out at once.\n */\n async list(): Promise<MaskedApiKey[]> {\n await this.load();\n return Array.from(this.keys.values()).map(maskApiKey);\n }\n\n /** The plaintext secret of a single key, or null when unknown. */\n async reveal(id: string): Promise<string | null> {\n await this.load();\n return this.keys.get(id)?.key ?? null;\n }\n\n async create(name: string, scopes: ApiKeyScope, isPublic: boolean): Promise<ApiKey> {\n await this.load();\n const apiKey: ApiKey = {\n id: `apikey-${randomUUID()}`,\n name,\n key: randomBytes(32).toString('hex'),\n scopes,\n createdAt: new Date().toISOString(),\n isPublic,\n };\n this.keys.set(apiKey.id, apiKey);\n await this.persist(isPublic);\n return apiKey;\n }\n\n async update(id: string, name: string, scopes: ApiKeyScope, isPublic: boolean): Promise<ApiKey | null> {\n await this.load();\n const existing = this.keys.get(id);\n if (!existing) return null;\n const updated: ApiKey = { ...existing, name, scopes, isPublic };\n this.keys.set(id, updated);\n // If isPublic changed, persist both files (remove from old, add to new)\n if (existing.isPublic !== isPublic) {\n await this.persistFile(existing.isPublic);\n await this.persistFile(isPublic);\n } else {\n await this.persist(isPublic);\n }\n return updated;\n }\n\n async remove(id: string): Promise<boolean> {\n await this.load();\n const existing = this.keys.get(id);\n if (!existing) return false;\n this.keys.delete(id);\n await this.persist(existing.isPublic);\n return true;\n }\n\n async renewKey(id: string): Promise<ApiKey | null> {\n await this.load();\n const existing = this.keys.get(id);\n if (!existing) return null;\n const renewed: ApiKey = { ...existing, key: randomBytes(32).toString('hex') };\n this.keys.set(id, renewed);\n await this.persist(renewed.isPublic);\n return renewed;\n }\n\n async validateKey(candidateHex: string): Promise<ApiKey | null> {\n await this.load();\n if (!/^[0-9a-f]{64}$/i.test(candidateHex)) return null;\n const candidate = Buffer.from(candidateHex, 'hex');\n for (const apiKey of this.keys.values()) {\n const stored = Buffer.from(apiKey.key, 'hex');\n if (candidate.length === stored.length && timingSafeEqual(candidate, stored)) {\n return apiKey;\n }\n }\n return null;\n }\n}\n\nexport const apiKeyStore = new ApiKeyStore();\n","import os from 'node:os';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { z } from 'zod';\nimport { router, publicProcedure, protectedProcedure } from '../trpc.js';\n\nconst execFileAsync = promisify(execFile);\n\n/** Récupère la version de Docker si le binaire est présent, sinon null. */\nasync function getDockerVersion(): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync('docker', ['--version'], {\n timeout: 3000,\n windowsHide: true,\n });\n // Format typique : \"Docker version 27.3.1, build ce12230\"\n const match = /Docker version\\s+([^,\\s]+)/i.exec(stdout);\n return match?.[1] ?? (stdout.trim() || null);\n } catch {\n return null;\n }\n}\n\ndeclare const __RUNEYA_VERSION__: string;\n\nconst startedAt = Date.now();\nconst appVersion = process.env['RUNEYA_VERSION'] ?? (typeof __RUNEYA_VERSION__ !== 'undefined' ? __RUNEYA_VERSION__ : 'dev');\n\nconst NPM_LATEST_URL = 'https://registry.npmjs.org/@runeya%2Fruneya/latest';\n\n/** Compare deux versions semver simples. Renvoie 1 si a>b, -1 si a<b, 0 si égales. */\nfunction compareSemver(a: string, b: string): number {\n const pa = a.split('.').map((n) => Number.parseInt(n, 10) || 0);\n const pb = b.split('.').map((n) => Number.parseInt(n, 10) || 0);\n for (let i = 0; i < 3; i++) {\n const da = pa[i] ?? 0;\n const db = pb[i] ?? 0;\n if (da > db) return 1;\n if (da < db) return -1;\n }\n return 0;\n}\n\nexport const healthRouter = router({\n check: publicProcedure\n .meta({ openapi: { method: 'GET', path: '/health', tags: ['health'], summary: 'Health check' } })\n .output(z.object({ status: z.literal('ok'), uptime: z.number(), version: z.string() }))\n .query(() => {\n return {\n status: 'ok' as const,\n uptime: Date.now() - startedAt,\n version: appVersion,\n };\n }),\n versionInfo: publicProcedure\n .output(\n z.object({\n current: z.string(),\n latest: z.string().nullable(),\n status: z.enum(['up-to-date', 'outdated', 'ahead', 'dev', 'unknown']),\n }),\n )\n .query(async () => {\n // En mode dev, pas de version publiée à comparer.\n if (appVersion === 'dev') {\n return { current: appVersion, latest: null, status: 'dev' as const };\n }\n\n try {\n const res = await fetch(NPM_LATEST_URL, {\n headers: { accept: 'application/json' },\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) {\n return { current: appVersion, latest: null, status: 'unknown' as const };\n }\n const parsed = z.object({ version: z.string().max(64) }).safeParse(await res.json());\n if (!parsed.success) {\n return { current: appVersion, latest: null, status: 'unknown' as const };\n }\n const latest = parsed.data.version;\n const cmp = compareSemver(appVersion, latest);\n const status = cmp === 0 ? 'up-to-date' : cmp < 0 ? 'outdated' : 'ahead';\n return { current: appVersion, latest, status };\n } catch {\n return { current: appVersion, latest: null, status: 'unknown' as const };\n }\n }),\n systemInfo: protectedProcedure\n .output(\n z.object({\n version: z.string(),\n nodeVersion: z.string(),\n platform: z.string(),\n arch: z.string(),\n osType: z.string(),\n osRelease: z.string(),\n hostname: z.string(),\n cpuModel: z.string(),\n cpuCount: z.number(),\n totalMemoryBytes: z.number(),\n freeMemoryBytes: z.number(),\n serverUptimeMs: z.number(),\n osUptimeSec: z.number(),\n dockerVersion: z.string().nullable(),\n }),\n )\n .query(async () => {\n const cpus = os.cpus();\n const dockerVersion = await getDockerVersion();\n return {\n version: appVersion,\n nodeVersion: process.version,\n platform: process.platform,\n arch: process.arch,\n osType: os.type(),\n osRelease: os.release(),\n hostname: os.hostname(),\n cpuModel: cpus[0]?.model.trim() ?? 'unknown',\n cpuCount: cpus.length,\n totalMemoryBytes: os.totalmem(),\n freeMemoryBytes: os.freemem(),\n serverUptimeMs: Date.now() - startedAt,\n osUptimeSec: os.uptime(),\n dockerVersion,\n };\n }),\n});\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { projectStore } from '../../services/project-store.js';\nimport { serviceStore } from '../../services/service-store.js';\nimport { environmentStore } from '../../services/environment-store.js';\nimport { environmentResolver } from '../../services/environment-resolver.js';\nimport { agentManager } from '../../services/agent-manager.js';\nimport { auditService } from '../../services/audit-service.js';\n\nexport const projectRouter = router({\n list: protectedProcedure.query(async () => {\n return projectStore.list();\n }),\n\n get: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(async ({ input }) => {\n const project = await projectStore.get(input.id);\n if (!project) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Project ${input.id} not found` });\n }\n return project;\n }),\n\n /**\n * Build a portable snapshot of a project for cloud storage: the project\n * record plus its services in sanitized (secret-free) on-disk form.\n * Environments are intentionally excluded — they carry secret values that\n * stay local.\n */\n export: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(async ({ input }) => {\n const project = await projectStore.get(input.id);\n if (!project) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Project ${input.id} not found` });\n }\n const services = (\n await Promise.all(project.serviceIds.map((sid) => serviceStore.getSanitized(sid)))\n ).filter((s): s is NonNullable<typeof s> => s !== null);\n return { project, services };\n }),\n\n create: protectedProcedure\n .input(\n z.object({\n name: z.string().min(1).max(200),\n description: z.string().max(10000).optional(),\n orgId: z.string().max(128).nullable().optional(),\n serviceIds: z.array(z.string().max(128)).max(10000).optional(),\n }),\n )\n .mutation(async ({ input }) => {\n // Create the project first (with empty environmentIds, will be updated after creating local env)\n const project = await projectStore.create({\n ...input,\n description: input.description ?? '',\n serviceIds: input.serviceIds ?? [],\n environmentIds: [],\n });\n\n // Create the default 'local' immutable environment for this project\n const localEnv = await environmentStore.create({\n projectId: project.id,\n name: 'local',\n description: 'Default local environment (immutable)',\n parentIds: [],\n immutable: true,\n });\n\n // Update the project with the local environment\n const result = await projectStore.update({\n id: project.id,\n environmentIds: [localEnv.id],\n activeEnvironmentId: localEnv.id,\n });\n\n await auditService.log({ userId: 'local', action: 'create', entityType: 'project', entityId: project.id, metadata: { name: input.name } });\n return result!;\n }),\n\n update: protectedProcedure\n .input(\n z.object({\n id: z.string().max(128),\n name: z.string().min(1).max(200).optional(),\n description: z.string().max(10000).optional(),\n orgId: z.string().max(128).nullable().optional(),\n serviceIds: z.array(z.string().max(128)).max(10000).optional(),\n groupOrder: z.array(z.string().max(200)).max(100).optional(),\n }),\n )\n .mutation(async ({ input }) => {\n const project = await projectStore.update(input);\n if (!project) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Project ${input.id} not found` });\n }\n await auditService.log({ userId: 'local', action: 'update', entityType: 'project', entityId: input.id });\n return project;\n }),\n\n delete: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const deleted = await projectStore.delete(input.id);\n if (!deleted) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Project ${input.id} not found` });\n }\n await auditService.log({ userId: 'local', action: 'delete', entityType: 'project', entityId: input.id });\n return { success: true as const };\n }),\n\n addService: protectedProcedure\n .input(z.object({ projectId: z.string().max(128), serviceId: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const project = await projectStore.addService(input.projectId, input.serviceId);\n if (!project) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Project ${input.projectId} not found` });\n }\n\n // Auto-create service-scoped environments for each global env in the project\n const service = await serviceStore.get(input.serviceId);\n if (service) {\n const globalEnvs = await environmentStore.listByScope(input.projectId, 'global');\n for (const globalEnv of globalEnvs) {\n const svcEnv = await environmentStore.create({\n projectId: input.projectId,\n name: `${service.name} (${globalEnv.name})`,\n scope: 'service',\n reference: input.serviceId,\n activateOn: globalEnv.id,\n parentIds: [globalEnv.id],\n variables: {},\n });\n await projectStore.addEnvironment(input.projectId, svcEnv.id);\n }\n }\n\n await auditService.log({\n userId: 'local',\n action: 'update',\n entityType: 'project',\n entityId: input.projectId,\n metadata: { operation: 'addService', serviceId: input.serviceId },\n });\n return project;\n }),\n\n removeService: protectedProcedure\n .input(z.object({ projectId: z.string().max(128), serviceId: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const project = await projectStore.removeService(input.projectId, input.serviceId);\n if (!project) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Project ${input.projectId} not found` });\n }\n await auditService.log({\n userId: 'local',\n action: 'update',\n entityType: 'project',\n entityId: input.projectId,\n metadata: { operation: 'removeService', serviceId: input.serviceId },\n });\n return project;\n }),\n\n setActiveEnvironment: protectedProcedure\n .input(z.object({ projectId: z.string().max(128), environmentId: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const project = await projectStore.get(input.projectId);\n if (!project) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Project ${input.projectId} not found` });\n }\n\n // Validate environment exists\n const environment = await environmentStore.get(input.environmentId);\n if (!environment) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Environment ${input.environmentId} not found` });\n }\n if (environment.projectId !== input.projectId) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Environment does not belong to this project' });\n }\n\n // Collect running services before changing environment\n const runningServices: { serviceId: string; agentId: string }[] = [];\n\n for (const serviceId of project.serviceIds) {\n const service = await serviceStore.get(serviceId);\n if (!service || !service.agentId) continue;\n\n const agentStatus = agentManager.getStatus(service.agentId);\n if (!agentStatus?.connected) continue;\n\n try {\n const processStatus = await agentManager.agentQuery<{ status: string }>(\n service.agentId,\n 'process.get',\n { id: serviceId }\n );\n\n if (processStatus?.status === 'running' || processStatus?.status === 'starting') {\n runningServices.push({ serviceId, agentId: service.agentId });\n }\n } catch {\n // Agent unreachable or process not deployed — skip\n }\n }\n\n // Update environment\n const updated = await projectStore.setActiveEnvironment(input.projectId, input.environmentId);\n\n if (!updated) {\n throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: 'Failed to set active environment' });\n }\n\n // Push resolved config to ALL assigned services (running or not)\n for (const serviceId of project.serviceIds) {\n const service = await serviceStore.get(serviceId);\n if (!service || !service.agentId) continue;\n\n const agentStatus = agentManager.getStatus(service.agentId);\n if (!agentStatus?.connected) continue;\n\n // Always resolve — the resolver handles empty service variables\n let resolvedService = service;\n try {\n const resolved = await environmentResolver.resolveForService({\n serviceId: service.id,\n activeEnvironmentId: input.environmentId,\n });\n\n resolvedService = {\n ...service,\n env: { ...resolved.env },\n envSecrets: [...resolved.envSecrets],\n };\n } catch (err) {\n console.error('[project-router] Failed to resolve variables for service', serviceId + ':', (err as Error).message);\n }\n\n const wasRunning = runningServices.some(rs => rs.serviceId === serviceId);\n\n if (wasRunning) {\n // Stop → deploy (with new env) → start\n // Uses deploy instead of updateConfig for consistency with the lazy deploy pattern\n try {\n await agentManager.agentMutation(service.agentId, 'process.stop', { id: serviceId });\n await agentManager.agentMutation(service.agentId, 'process.deploy', resolvedService);\n await agentManager.agentMutation(service.agentId, 'process.start', { id: serviceId });\n } catch (err) {\n console.error('[project-router] Failed to restart service', serviceId + ':', (err as Error).message);\n }\n }\n // Stopped services: no need to push config — the next start will\n // lazy-deploy with the freshly resolved environment anyway.\n }\n\n return updated;\n }),\n});\n","import { randomUUID } from 'node:crypto';\nimport { EventEmitter } from 'node:events';\nimport { readFile, writeFile, rename, mkdir, chmod } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { env } from '../config/env.js';\nimport type { Project, CreateProject, UpdateProject } from '@runeya/packages-shared';\nimport { ProjectSchema } from '@runeya/packages-shared';\nimport { environmentStore } from './environment-store.js';\n\nconst FILENAME = 'projects.json';\n\n/**\n * A project as persisted: `activeEnvironmentId` is runtime-only and never hits\n * disk. This is also exactly what the cloud mirrors — the sync shares what git\n * shares, so \"is it persisted?\" is the only question that decides it.\n */\nfunction toDiskForm(project: Project): Omit<Project, 'activeEnvironmentId'> {\n const { activeEnvironmentId: _runtimeOnly, ...rest } = project;\n return rest;\n}\n\nclass ProjectStore {\n private projects: Map<string, Project> = new Map();\n private loaded = false;\n /** Emits `'saved'` after every persisted mutation, for the cloud sync bridge. */\n readonly events = new EventEmitter();\n\n private getFilePath(): string {\n return join(env.DATA_DIR, FILENAME);\n }\n\n private async ensureDir(): Promise<void> {\n await mkdir(env.DATA_DIR, { recursive: true });\n }\n\n private async load(): Promise<void> {\n if (this.loaded) return;\n try {\n const raw = await readFile(this.getFilePath(), 'utf-8');\n const data: Project[] = JSON.parse(raw);\n for (const p of data) {\n const projectEnvs = await environmentStore.getByProjectId(p.id).catch(() => []);\n const defaultEnv = projectEnvs.find(e => e.default);\n this.projects.set(p.id, {\n ...p,\n environmentIds: p.environmentIds ?? [],\n groupOrder: p.groupOrder ?? [],\n // Prefer the env marked default, fall back to first env\n activeEnvironmentId: defaultEnv?.id ?? p.environmentIds?.[0],\n });\n }\n } catch {\n // File doesn't exist yet, start empty\n }\n this.loaded = true;\n }\n\n private async save(): Promise<void> {\n await this.ensureDir();\n const filePath = this.getFilePath();\n const tmpPath = filePath + '.tmp';\n\n // Omit activeEnvironmentId from persistence (runtime-only field)\n const projectsToSave = Array.from(this.projects.values()).map(toDiskForm);\n\n const data = JSON.stringify(projectsToSave, null, 2);\n await writeFile(tmpPath, data, 'utf-8');\n await rename(tmpPath, filePath);\n await chmod(filePath, 0o600);\n this.events.emit('saved');\n }\n\n async list(): Promise<Project[]> {\n await this.load();\n return Array.from(this.projects.values());\n }\n\n async get(id: string): Promise<Project | null> {\n await this.load();\n return this.projects.get(id) ?? null;\n }\n\n async create(input: CreateProject): Promise<Project> {\n await this.load();\n const project: Project = {\n id: randomUUID(),\n orgId: input.orgId ?? null,\n name: input.name,\n description: input.description ?? '',\n serviceIds: input.serviceIds ?? [],\n environmentIds: input.environmentIds ?? [],\n activeEnvironmentId: input.activeEnvironmentId,\n groupOrder: input.groupOrder ?? [],\n };\n this.projects.set(project.id, project);\n await this.save();\n return project;\n }\n\n async update(input: UpdateProject): Promise<Project | null> {\n await this.load();\n const existing = this.projects.get(input.id);\n if (!existing) return null;\n const updated: Project = {\n ...existing,\n ...(input.name !== undefined && { name: input.name }),\n ...(input.description !== undefined && { description: input.description }),\n ...(input.serviceIds !== undefined && { serviceIds: input.serviceIds }),\n ...(input.environmentIds !== undefined && { environmentIds: input.environmentIds }),\n ...(input.activeEnvironmentId !== undefined && { activeEnvironmentId: input.activeEnvironmentId }),\n ...(input.orgId !== undefined && { orgId: input.orgId }),\n ...(input.groupOrder !== undefined && { groupOrder: input.groupOrder }),\n };\n this.projects.set(input.id, updated);\n await this.save();\n return updated;\n }\n\n async delete(id: string): Promise<boolean> {\n await this.load();\n if (!this.projects.has(id)) return false;\n this.projects.delete(id);\n await this.save();\n return true;\n }\n\n /** All projects linked to a given organization (for the sync bridge). */\n async listByOrg(orgId: string): Promise<Project[]> {\n await this.load();\n return Array.from(this.projects.values()).filter((p) => p.orgId === orgId);\n }\n\n /** Projects of an organization in their on-disk form (what the cloud mirrors). */\n async listDiskFormByOrg(orgId: string): Promise<Omit<Project, 'activeEnvironmentId'>[]> {\n return (await this.listByOrg(orgId)).map(toDiskForm);\n }\n\n /**\n * Apply a project received from the cloud, in its on-disk form.\n *\n * Validated rather than trusted: a peer on another version — or a tampered\n * doc — must not be able to write arbitrary shapes into `projects.json`.\n * `activeEnvironmentId` is runtime-only and stays whatever it is locally.\n * Diff-guarded: an identical project neither saves nor emits (loop-safe).\n * Returns whether a new local project was created, so the caller can\n * bootstrap project-local state (e.g. a default environment).\n */\n async applyRemoteUpsert(\n id: string,\n fields: unknown,\n ): Promise<{ project: Project; created: boolean } | null> {\n await this.load();\n const parsed = ProjectSchema.safeParse({ ...(fields as object), id });\n if (!parsed.success) {\n console.error('[project-store] Rejected remote project %s:', id, parsed.error.message);\n return null;\n }\n const incoming = toDiskForm(parsed.data);\n const existing = this.projects.get(id);\n if (existing) {\n if (JSON.stringify(toDiskForm(existing)) === JSON.stringify(incoming)) {\n return { project: existing, created: false };\n }\n const updated: Project = { ...incoming, activeEnvironmentId: existing.activeEnvironmentId };\n this.projects.set(id, updated);\n await this.save();\n return { project: updated, created: false };\n }\n const project: Project = { ...incoming, activeEnvironmentId: undefined };\n this.projects.set(id, project);\n await this.save();\n return { project, created: true };\n }\n\n /** Delete a project that was removed on another peer. */\n async applyRemoteDelete(id: string): Promise<boolean> {\n await this.load();\n if (!this.projects.has(id)) return false;\n this.projects.delete(id);\n await this.save();\n return true;\n }\n\n async addService(projectId: string, serviceId: string): Promise<Project | null> {\n await this.load();\n const project = this.projects.get(projectId);\n if (!project) return null;\n if (project.serviceIds.includes(serviceId)) return project;\n const updated = { ...project, serviceIds: [...project.serviceIds, serviceId] };\n this.projects.set(projectId, updated);\n await this.save();\n return updated;\n }\n\n async removeService(projectId: string, serviceId: string): Promise<Project | null> {\n await this.load();\n const project = this.projects.get(projectId);\n if (!project) return null;\n const updated = { ...project, serviceIds: project.serviceIds.filter(id => id !== serviceId) };\n this.projects.set(projectId, updated);\n await this.save();\n return updated;\n }\n\n async addEnvironment(projectId: string, environmentId: string): Promise<Project | null> {\n await this.load();\n const project = this.projects.get(projectId);\n if (!project) return null;\n if (project.environmentIds?.includes(environmentId)) return project;\n const updated = {\n ...project,\n environmentIds: [...(project.environmentIds ?? []), environmentId],\n };\n this.projects.set(projectId, updated);\n await this.save();\n return updated;\n }\n\n async removeEnvironment(projectId: string, environmentId: string): Promise<Project | null> {\n await this.load();\n const project = this.projects.get(projectId);\n if (!project) return null;\n const updated = {\n ...project,\n environmentIds: (project.environmentIds ?? []).filter(id => id !== environmentId),\n // Clear activeEnvironmentId if it was the removed environment\n ...(project.activeEnvironmentId === environmentId && { activeEnvironmentId: undefined }),\n };\n this.projects.set(projectId, updated);\n await this.save();\n return updated;\n }\n\n async setActiveEnvironment(projectId: string, environmentId: string): Promise<Project | null> {\n await this.load();\n const project = this.projects.get(projectId);\n if (!project) return null;\n\n // Update activeEnvironmentId in memory only (not persisted to JSON)\n // Do NOT update updatedAt since this is a runtime preference, not a project modification\n const updated: Project = {\n ...project,\n activeEnvironmentId: environmentId,\n };\n\n this.projects.set(projectId, updated);\n // No save() call - activeEnvironmentId is runtime-only\n return updated;\n }\n}\n\nexport const projectStore = new ProjectStore();\n","import { readFile, writeFile, rename, mkdir, chmod } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { env } from '../config/env.js';\nimport { getEncryptionKey } from '../utils/encryption-key.js';\nimport {\n encryptVariableSlots,\n decryptVariableSlots,\n extractEncryptedVariableSlots,\n} from './crypto-helpers.js';\nimport type { VariableOverride, VariableSlot } from '@runeya/packages-shared';\n\nconst FILENAME = 'environment-overrides.json';\n\n// On disk: flat Record<variableId, VariableOverride>\n// An override holds only a value slot — the env var name always comes from the\n// variable definition, resolved by variable ID.\ntype OverridesData = Record<string, VariableOverride>;\n\nclass EnvironmentOverridesStore {\n private data: OverridesData = {};\n private loaded = false;\n private diskEncryptedSlots: Record<string, string> = {};\n private saveQueue: Promise<void> = Promise.resolve();\n\n private getFilePath(): string {\n return join(env.DATA_DIR, FILENAME);\n }\n\n private async ensureDir(): Promise<void> {\n await mkdir(env.DATA_DIR, { recursive: true });\n }\n\n private async load(): Promise<void> {\n if (this.loaded) return;\n try {\n const raw = await readFile(this.getFilePath(), 'utf-8');\n const parsed: OverridesData = JSON.parse(raw);\n\n if (!getEncryptionKey()) {\n return;\n }\n\n // Cache encrypted slots then decrypt\n this.diskEncryptedSlots = extractEncryptedVariableSlots(\n parsed as Record<string, { value: VariableSlot }>,\n );\n const decrypted = decryptVariableSlots(\n parsed as Record<string, { value: VariableSlot }>,\n 'environment-overrides',\n ) as Record<string, { value: VariableSlot }>;\n\n // Drop any legacy `key` field written by older versions: it has no\n // authority and goes stale when the variable is renamed.\n this.data = Object.fromEntries(\n Object.entries(decrypted).map(([id, override]) => [id, { value: override.value }]),\n );\n } catch {\n this.data = {};\n }\n this.loaded = true;\n }\n\n private save(): Promise<void> {\n this.saveQueue = this.saveQueue.then(() => this.doSave()).catch(() => this.doSave());\n return this.saveQueue;\n }\n\n private async doSave(): Promise<void> {\n await this.ensureDir();\n const filePath = this.getFilePath();\n const tmpPath = filePath + '.tmp';\n\n const encrypted = encryptVariableSlots(\n this.data as Record<string, { value: VariableSlot }>,\n this.diskEncryptedSlots,\n ) as OverridesData;\n this.diskEncryptedSlots = extractEncryptedVariableSlots(\n encrypted as Record<string, { value: VariableSlot }>,\n );\n\n const json = JSON.stringify(encrypted, null, 2);\n await writeFile(tmpPath, json, 'utf-8');\n await rename(tmpPath, filePath);\n await chmod(filePath, 0o600);\n }\n\n async getOverride(variableId: string): Promise<VariableOverride | null> {\n await this.load();\n return this.data[variableId] ?? null;\n }\n\n async setOverride(variableId: string, override: VariableOverride): Promise<void> {\n await this.load();\n this.data[variableId] = { value: override.value };\n await this.save();\n }\n\n async removeOverride(variableId: string): Promise<void> {\n await this.load();\n if (!this.data[variableId]) return;\n delete this.data[variableId];\n await this.save();\n }\n\n async getAll(): Promise<Record<string, VariableOverride>> {\n await this.load();\n return { ...this.data };\n }\n\n async removeOverridesForVariables(variableIds: string[]): Promise<void> {\n await this.load();\n let changed = false;\n for (const id of variableIds) {\n if (this.data[id]) {\n delete this.data[id];\n changed = true;\n }\n }\n if (changed) await this.save();\n }\n}\n\nexport const environmentOverridesStore = new EnvironmentOverridesStore();\n","import type { Variable, VariableOverride, ResolvedEnvironment } from '@runeya/packages-shared';\nimport { environmentStore } from './environment-store.js';\nimport { environmentOverridesStore } from './environment-overrides-store.js';\n\ninterface VariableSource {\n environmentId: string;\n environmentName: string;\n overridden: boolean;\n resolvedFrom?: { environmentId: string; environmentName: string };\n /** Environment carrying the machine-local override that won for this key */\n overriddenBy?: { environmentId: string; environmentName: string };\n}\n\n/** Winning override for a variable key, plus the environment it comes from */\ninterface WinningOverride {\n variable: Variable;\n source?: { environmentId: string; environmentName: string };\n}\n\ninterface DagResult {\n variables: Record<string, Variable>;\n sources: Record<string, VariableSource>;\n /** Concrete parent values keyed by variable key (pre-dedup), used for interpolation context */\n parentEnv: Record<string, string>;\n /** Keys in parentEnv that are secret */\n parentSecretKeys: Set<string>;\n /** Maps variable key → source environment info for parent variables (before child override) */\n parentKeySources: Record<string, { environmentId: string; environmentName: string }>;\n}\n\n/**\n * Interpolate {{environment.KEY}} references in a value string.\n * envContext is the flat dict of resolved environment values.\n * Returns the interpolated string.\n * Missing keys are left as-is ({{environment.MISSING}} -> unchanged).\n */\nfunction interpolateValue(raw: string, envContext: Record<string, string>): string {\n return raw.replace(/\\{\\{environment\\.([^}]+)\\}\\}/g, (match, key) => {\n return envContext[key] !== undefined ? envContext[key] : match;\n });\n}\n\n/**\n * Resolve a Variable to its final string value.\n * Uses variable.value slot, computes pre + interpolate(value) + post.\n */\nfunction resolveVariable(\n variable: Variable,\n envContext: Record<string, string>,\n): { value: string; isSecret: boolean } {\n const slot = variable.value;\n const interpolated = interpolateValue(slot.value, envContext);\n const finalValue = slot.pre + interpolated + slot.post;\n return { value: finalValue, isSecret: slot.isSecret };\n}\n\nclass EnvironmentResolver {\n async resolveForService(ctx: { serviceId: string; activeEnvironmentId: string }): Promise<{ env: Record<string, string>; envSecrets: string[] }> {\n if (!ctx.activeEnvironmentId) {\n return { env: {}, envSecrets: [] };\n }\n\n // Find the service-scoped environment for this service + active global env\n const serviceEnv = await environmentStore.findServiceEnvironment(ctx.serviceId, ctx.activeEnvironmentId);\n\n if (!serviceEnv) {\n // No service env: resolve just the global env\n return this.resolveEnvironment(ctx.activeEnvironmentId);\n }\n\n // Resolve the service env (which inherits from global via parentIds)\n return this.resolveEnvironment(serviceEnv.id);\n }\n\n async resolveEnvironment(environmentId: string): Promise<{ env: Record<string, string>; envSecrets: string[] }> {\n const visited = new Set<string>();\n const result = await this.resolveDag(environmentId, visited);\n\n // Apply overrides, resolved as their own chain (see resolveOverridesByKey)\n const overridesByKey = await this.resolveOverridesByKey(environmentId);\n for (const [varId, variable] of Object.entries(result.variables)) {\n const override = overridesByKey[variable.key];\n if (override) {\n result.variables[varId] = { ...variable, value: override.variable.value };\n }\n }\n\n // First pass: build raw env dict (no interpolation yet)\n const rawEnv: Record<string, string> = {};\n for (const [_varId, variable] of Object.entries(result.variables)) {\n const slot = variable.value;\n rawEnv[variable.key] = slot.pre + slot.value + slot.post;\n }\n\n // Build interpolation context:\n // Start from parent concrete values, then overlay with current concrete values.\n // This ensures {{environment.KEY}} resolves against parent values when the child\n // redefines KEY as an interpolation reference.\n const { ctx: interpolationCtx, secretKeys: ctxSecretKeys } = await this.buildInterpolationContext(environmentId, rawEnv, result.parentEnv, result.parentSecretKeys, result.parentKeySources);\n const secretKeys = this.collectSecretKeys(result.variables, ctxSecretKeys);\n\n // Second pass: interpolate and build final env dict\n const env: Record<string, string> = {};\n const envSecrets: string[] = [];\n for (const [_varId, variable] of Object.entries(result.variables)) {\n const { value, isSecret } = resolveVariable(variable, interpolationCtx);\n env[variable.key] = value;\n if (isSecret || secretKeys.has(variable.key)) {\n envSecrets.push(variable.key);\n }\n }\n\n return { env, envSecrets };\n }\n\n /**\n * Resolve an environment (with inheritance) and return only the variables\n * flagged `injectIntoAi`, as a flat KEY→value dict ready to be injected into\n * the process environment of an AI agent spawn.\n */\n async resolveAiInjectedEnv(environmentId: string): Promise<Record<string, string>> {\n if (!environmentId) return {};\n\n const visited = new Set<string>();\n const result = await this.resolveDag(environmentId, visited);\n\n // Apply overrides (same as resolveEnvironment)\n const overridesByKey = await this.resolveOverridesByKey(environmentId);\n for (const [varId, variable] of Object.entries(result.variables)) {\n const override = overridesByKey[variable.key];\n if (override) {\n result.variables[varId] = { ...variable, value: override.variable.value };\n }\n }\n\n // Build raw env for interpolation context\n const rawEnv: Record<string, string> = {};\n for (const variable of Object.values(result.variables)) {\n const slot = variable.value;\n rawEnv[variable.key] = slot.pre + slot.value + slot.post;\n }\n const { ctx: interpolationCtx } = await this.buildInterpolationContext(\n environmentId,\n rawEnv,\n result.parentEnv,\n result.parentSecretKeys,\n result.parentKeySources,\n );\n\n // Keep only flagged variables, interpolating their final value.\n const injected: Record<string, string> = {};\n for (const variable of Object.values(result.variables)) {\n if (!variable.value.injectIntoAi) continue;\n const { value } = resolveVariable(variable, interpolationCtx);\n injected[variable.key] = value;\n }\n return injected;\n }\n\n async resolveEnvironmentWithSources(environmentId: string): Promise<ResolvedEnvironment> {\n const visited = new Set<string>();\n const result = await this.resolveDag(environmentId, visited);\n\n // Apply overrides, resolved as their own chain (see resolveOverridesByKey)\n const overridesByKey = await this.resolveOverridesByKey(environmentId);\n for (const [varId, variable] of Object.entries(result.variables)) {\n const override = overridesByKey[variable.key];\n if (override) {\n result.variables[varId] = { ...variable, value: override.variable.value };\n result.sources[varId] = {\n ...result.sources[varId],\n overridden: true,\n ...(override.source ? { overriddenBy: override.source } : {}),\n };\n }\n }\n\n // First pass: build raw env dict (no interpolation yet)\n const rawEnv: Record<string, string> = {};\n for (const [_varId, variable] of Object.entries(result.variables)) {\n const slot = variable.value;\n rawEnv[variable.key] = slot.pre + slot.value + slot.post;\n }\n\n // Build interpolation context\n const { ctx: interpolationCtx, secretKeys: ctxSecretKeys, keySources } = await this.buildInterpolationContext(environmentId, rawEnv, result.parentEnv, result.parentSecretKeys, result.parentKeySources);\n const secretKeys = this.collectSecretKeys(result.variables, ctxSecretKeys);\n\n // Second pass: interpolate and build final env dict\n const env: Record<string, string> = {};\n const envSecrets: string[] = [];\n for (const [_varId, variable] of Object.entries(result.variables)) {\n const { value, isSecret } = resolveVariable(variable, interpolationCtx);\n env[variable.key] = value;\n if (isSecret || secretKeys.has(variable.key)) {\n envSecrets.push(variable.key);\n }\n }\n\n // Post-process: for pure interpolation references, annotate `resolvedFrom`\n // so the frontend knows where the resolved value actually comes from,\n // while keeping the source pointing to where the variable is defined.\n const refPattern = /^\\{\\{environment\\.([^}]+)\\}\\}$/;\n for (const [varId, variable] of Object.entries(result.variables)) {\n const match = variable.value.value.match(refPattern);\n if (match) {\n const refSource = keySources[match[1]];\n if (refSource && result.sources[varId]?.environmentId !== refSource.environmentId) {\n result.sources[varId] = {\n ...result.sources[varId],\n resolvedFrom: refSource,\n };\n }\n }\n }\n\n return {\n variables: result.variables,\n env,\n envSecrets,\n sources: result.sources,\n };\n }\n\n /** Check if a raw value string interpolates any key that is secret in the context */\n /**\n * Toutes les clés dont la valeur est, directement ou par interpolation, un\n * secret.\n *\n * Le contexte d'interpolation ne connaît que les secrets *hérités* : les\n * secrets définis dans le même environnement n'y figurent pas, si bien qu'un\n * `AUTH='Bearer {{environment.TOKEN}}'` voisin de son propre `TOKEN` secret\n * ressortait non marqué — et donc non masqué par toute la chaîne en aval.\n *\n * On part des secrets hérités plus ceux déclarés ici, puis on propage\n * jusqu'au point fixe : une valeur qui référence une clé secrète devient\n * secrète à son tour, y compris en chaîne (A secret → B cite A → C cite B).\n */\n private collectSecretKeys(\n variables: Record<string, Variable>,\n parentSecretKeys: Set<string>,\n ): Set<string> {\n const secretKeys = new Set(parentSecretKeys);\n for (const variable of Object.values(variables)) {\n if (variable.value.isSecret) secretKeys.add(variable.key);\n }\n let changed = true;\n while (changed) {\n changed = false;\n for (const variable of Object.values(variables)) {\n if (secretKeys.has(variable.key)) continue;\n if (this.interpolatesSecretKey(variable.value.value, secretKeys)) {\n secretKeys.add(variable.key);\n changed = true;\n }\n }\n }\n return secretKeys;\n }\n\n private interpolatesSecretKey(rawValue: string, ctxSecretKeys: Set<string>): boolean {\n const refs = [...rawValue.matchAll(/\\{\\{environment\\.([^}]+)\\}\\}/g)].map(m => m[1]);\n return refs.some(ref => ctxSecretKeys.has(ref));\n }\n\n /**\n * Build the interpolation context for an environment.\n *\n * For inheriting envs (has parents): start from parent concrete values,\n * then overlay with current concrete values. This ensures that\n * {{environment.KEY}} resolves against the parent's value when the child\n * redefines KEY as an interpolation reference.\n *\n * For isolated service envs (scope=service, activateOn set, no parents):\n * the global env is resolved and used as fallback.\n */\n private async buildInterpolationContext(\n environmentId: string,\n rawEnv: Record<string, string>,\n parentEnv: Record<string, string>,\n parentSecretKeys: Set<string>,\n parentKeySources: Record<string, { environmentId: string; environmentName: string }>,\n ): Promise<{ ctx: Record<string, string>; secretKeys: Set<string>; keySources: Record<string, { environmentId: string; environmentName: string }> }> {\n const environment = await environmentStore.get(environmentId);\n\n // Isolated service env: resolve global env for interpolation context\n if (\n environment\n && environment.scope === 'service'\n && environment.activateOn\n && (!environment.parentIds || environment.parentIds.length === 0)\n ) {\n const globalResolved = await this.resolveEnvironmentWithSources(environment.activateOn);\n const secretKeys = new Set(globalResolved.envSecrets);\n // Build keySources from global env variables\n const keySources: Record<string, { environmentId: string; environmentName: string }> = {};\n for (const [varId, variable] of Object.entries(globalResolved.variables)) {\n const source = globalResolved.sources[varId];\n if (source) {\n keySources[variable.key] = { environmentId: source.environmentId, environmentName: source.environmentName };\n }\n }\n // Start with global values, then override with local values that are\n // concrete (not themselves interpolation references)\n const ctx = { ...globalResolved.env };\n for (const [key, value] of Object.entries(rawEnv)) {\n if (!/\\{\\{environment\\.[^}]+\\}\\}/.test(value)) {\n ctx[key] = value;\n }\n }\n return { ctx, secretKeys, keySources };\n }\n\n // Inheriting env: start from parent concrete values, overlay with concrete rawEnv values\n const ctx = { ...parentEnv };\n for (const [key, value] of Object.entries(rawEnv)) {\n if (!/\\{\\{environment\\.[^}]+\\}\\}/.test(value)) {\n ctx[key] = value;\n }\n }\n return { ctx, secretKeys: parentSecretKeys, keySources: parentKeySources };\n }\n\n /**\n * For service-scoped envs, compute effective parentIds by also including\n * the service-scoped envs of ancestor global environments.\n *\n * Example: \"Server (test)\" has parentIds=[test-global]. test-global has\n * parentIds=[Local-global]. This method adds \"Server (Local)\" to the\n * effective parents so service-specific variables from ancestor envs\n * are inherited correctly.\n */\n private async getEffectiveParentIds(environment: { scope?: string; reference?: string; activateOn?: string; parentIds: string[] }): Promise<string[]> {\n if (environment.scope !== 'service' || !environment.reference || !environment.activateOn) {\n return environment.parentIds;\n }\n\n // Walk each global parent and find the service-scoped env for the same service\n const additionalIds: string[] = [];\n for (const parentId of environment.parentIds) {\n const parentEnv = await environmentStore.get(parentId);\n if (!parentEnv || parentEnv.scope !== 'global') continue;\n\n for (const grandparentGlobalId of parentEnv.parentIds) {\n const ancestorServiceEnv = await environmentStore.findServiceEnvironment(environment.reference, grandparentGlobalId);\n if (ancestorServiceEnv && !environment.parentIds.includes(ancestorServiceEnv.id)) {\n additionalIds.push(ancestorServiceEnv.id);\n }\n }\n }\n\n if (additionalIds.length === 0) return environment.parentIds;\n return [...environment.parentIds, ...additionalIds];\n }\n\n /**\n * Project an environment's variables onto their overrides: keep only the\n * variables that have one, and swap in the override's value slot. The key\n * always comes from the definition.\n *\n * Feeding this projection back through `resolveDag` resolves the override\n * chain with the exact same inheritance and dedup-by-key rules as the value\n * chain — so an override set on a parent env is no longer swallowed when a\n * child (or a service env) redeclares the same key.\n */\n private projectOverrides(\n variables: Record<string, Variable>,\n overrides: Record<string, VariableOverride>,\n ): Record<string, Variable> {\n const projected: Record<string, Variable> = {};\n for (const [varId, variable] of Object.entries(variables)) {\n const override = overrides[varId];\n if (override) {\n projected[varId] = { key: variable.key, value: override.value };\n }\n }\n return projected;\n }\n\n /**\n * Resolve the override chain independently of the value chain and return the\n * winning override per variable key (empty when nothing is overridden).\n */\n private async resolveOverridesByKey(environmentId: string): Promise<Record<string, WinningOverride>> {\n const allOverrides = await environmentOverridesStore.getAll();\n if (Object.keys(allOverrides).length === 0) return {};\n\n const result = await this.resolveDag(environmentId, new Set(), (variables) =>\n this.projectOverrides(variables, allOverrides),\n );\n\n const byKey: Record<string, WinningOverride> = {};\n for (const [varId, variable] of Object.entries(result.variables)) {\n const source = result.sources[varId];\n byKey[variable.key] = {\n variable,\n ...(source ? { source: { environmentId: source.environmentId, environmentName: source.environmentName } } : {}),\n };\n }\n return byKey;\n }\n\n private async resolveDag(\n environmentId: string,\n visited: Set<string>,\n project?: (variables: Record<string, Variable>) => Record<string, Variable>,\n ): Promise<DagResult> {\n if (visited.has(environmentId)) {\n throw new Error(`Circular dependency detected in environment inheritance for ${environmentId}`);\n }\n\n const environment = await environmentStore.get(environmentId);\n if (!environment) {\n throw new Error(`Environment \"${environmentId}\" not found`);\n }\n\n visited.add(environmentId);\n\n // For service-scoped envs: ensure we also inherit from ancestor service-scoped envs.\n // When a service env's global parent itself has parent globals, we need to include\n // the service-scoped envs of those ancestor globals in the resolution chain.\n const effectiveParentIds = await this.getEffectiveParentIds(environment);\n\n // Resolve all parents first\n const parentResults: DagResult[] = [];\n for (const parentId of effectiveParentIds) {\n const parentVisited = new Set(visited);\n const parentResult = await this.resolveDag(parentId, parentVisited, project);\n parentResults.push(parentResult);\n }\n\n // Merge parent variables (left-to-right, later parents override earlier)\n const mergedVariables: Record<string, Variable> = {};\n const sources: Record<string, VariableSource> = {};\n\n for (const result of parentResults) {\n // Dedup by key: if a later parent has a variable with the same key, remove the earlier one\n for (const [varId, variable] of Object.entries(result.variables)) {\n for (const [existingId, existingVar] of Object.entries(mergedVariables)) {\n if (existingVar.key === variable.key && existingId !== varId) {\n delete mergedVariables[existingId];\n delete sources[existingId];\n }\n }\n mergedVariables[varId] = variable;\n sources[varId] = result.sources[varId] ?? sources[varId];\n }\n }\n\n // Build parentEnv: concrete values from parents BEFORE child dedup/override\n // Used as interpolation context so {{environment.KEY}} resolves against parent values\n const parentEnv: Record<string, string> = {};\n const parentSecretKeys = new Set<string>();\n const parentKeySources: Record<string, { environmentId: string; environmentName: string }> = {};\n for (const [varId, variable] of Object.entries(mergedVariables)) {\n const slot = variable.value;\n parentEnv[variable.key] = slot.pre + slot.value + slot.post;\n if (slot.isSecret) {\n parentSecretKeys.add(variable.key);\n }\n const source = sources[varId];\n if (source) {\n parentKeySources[variable.key] = { environmentId: source.environmentId, environmentName: source.environmentName };\n }\n }\n // Also include parent-of-parent values for deeper chains.\n // Prefer concrete values over interpolation references: if parentEnv already has a\n // raw {{environment.KEY}} ref for a key, replace it with a concrete value if found.\n const isInterpRef = (v: string) => /\\{\\{environment\\.[^}]+\\}\\}/.test(v);\n for (const result of parentResults) {\n for (const [key, value] of Object.entries(result.parentEnv)) {\n const existingIsRef = key in parentEnv && isInterpRef(parentEnv[key]);\n const newIsConcrete = !isInterpRef(value);\n if (!(key in parentEnv) || (existingIsRef && newIsConcrete)) {\n parentEnv[key] = value;\n }\n }\n for (const key of result.parentSecretKeys) {\n parentSecretKeys.add(key);\n }\n for (const [key, source] of Object.entries(result.parentKeySources)) {\n if (!(key in parentKeySources)) {\n parentKeySources[key] = source;\n }\n }\n }\n // Une variable héritée qui interpole un secret est elle-même un secret, et\n // doit le rester pour les descendants — sans ça le caractère secret se perd\n // dès qu'on descend d'un niveau.\n for (const key of this.collectSecretKeys(mergedVariables, parentSecretKeys)) {\n parentSecretKeys.add(key);\n }\n\n // Apply current environment's own variables\n const ownVariables = project ? project(environment.variables) : environment.variables;\n for (const [varId, variable] of Object.entries(ownVariables)) {\n // Remove any parent variable with the same key but different variableId (dedup by key)\n let wasInherited = varId in mergedVariables;\n for (const [existingId, existingVar] of Object.entries(mergedVariables)) {\n if (existingVar.key === variable.key && existingId !== varId) {\n delete mergedVariables[existingId];\n delete sources[existingId];\n wasInherited = true;\n }\n }\n mergedVariables[varId] = variable;\n sources[varId] = {\n environmentId: environment.id,\n environmentName: environment.name,\n overridden: wasInherited,\n };\n }\n\n return {\n variables: mergedVariables,\n sources,\n parentEnv,\n parentSecretKeys,\n parentKeySources,\n };\n }\n}\n\nexport const environmentResolver = new EnvironmentResolver();\n","import { appendFile, readFile, stat, rename, unlink, readdir, mkdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { env } from '../config/env.js';\n\nexport interface AuditEntry {\n timestamp: string;\n userId: string;\n action: string;\n entityType: string;\n entityId: string;\n metadata?: Record<string, unknown>;\n}\n\nconst AUDIT_FILENAME = 'audit.log';\nconst MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB\nconst MAX_AGE_DAYS = 30;\n\nclass AuditService {\n private getFilePath(): string {\n return join(env.DATA_DIR, AUDIT_FILENAME);\n }\n\n private getRotatedPath(): string {\n return join(env.DATA_DIR, `audit.log.${Date.now()}.bak`);\n }\n\n /** Append an audit entry (newline-delimited JSON) */\n async log(entry: Omit<AuditEntry, 'timestamp'>): Promise<void> {\n const record: AuditEntry = {\n ...entry,\n timestamp: new Date().toISOString(),\n };\n const line = JSON.stringify(record) + '\\n';\n const filepath = this.getFilePath();\n\n try {\n await mkdir(env.DATA_DIR, { recursive: true });\n await appendFile(filepath, line, 'utf-8');\n await this.rotateIfNeeded();\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n console.error('[audit] Failed to write audit log:', message);\n }\n }\n\n /** Read audit entries, optionally filtered */\n async list(options?: {\n action?: string;\n entityType?: string;\n entityId?: string;\n limit?: number;\n offset?: number;\n }): Promise<{ entries: AuditEntry[]; total: number }> {\n const filepath = this.getFilePath();\n let lines: string[];\n try {\n const content = await readFile(filepath, 'utf-8');\n lines = content.trim().split('\\n').filter(Boolean);\n } catch {\n return { entries: [], total: 0 };\n }\n\n let entries: AuditEntry[] = lines\n .map((line) => {\n try { return JSON.parse(line) as AuditEntry; } catch { return null; }\n })\n .filter((e): e is AuditEntry => e !== null)\n .reverse(); // newest first\n\n // Apply filters\n if (options?.action) {\n entries = entries.filter((e) => e.action === options.action);\n }\n if (options?.entityType) {\n entries = entries.filter((e) => e.entityType === options.entityType);\n }\n if (options?.entityId) {\n entries = entries.filter((e) => e.entityId === options.entityId);\n }\n\n const total = entries.length;\n const offset = options?.offset ?? 0;\n const limit = options?.limit ?? 50;\n entries = entries.slice(offset, offset + limit);\n\n return { entries, total };\n }\n\n /** Rotate log file if it exceeds MAX_FILE_SIZE */\n private async rotateIfNeeded(): Promise<void> {\n const filepath = this.getFilePath();\n try {\n const stats = await stat(filepath);\n if (stats.size > MAX_FILE_SIZE) {\n await rename(filepath, this.getRotatedPath());\n }\n } catch {\n // File doesn't exist, nothing to rotate\n }\n }\n\n /** Clean up old rotated logs (older than MAX_AGE_DAYS) */\n async cleanup(): Promise<void> {\n const files = await readdir(env.DATA_DIR);\n const cutoff = Date.now() - MAX_AGE_DAYS * 24 * 60 * 60 * 1000;\n\n for (const file of files) {\n if (file.startsWith('audit.log.') && file.endsWith('.bak')) {\n const tsStr = file.replace('audit.log.', '').replace('.bak', '');\n const ts = Number.parseInt(tsStr, 10);\n if (!Number.isNaN(ts) && ts < cutoff) {\n try {\n await unlink(join(env.DATA_DIR, file));\n } catch {\n // Ignore\n }\n }\n }\n }\n }\n}\n\nexport const auditService = new AuditService();\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { HealthCheckSchema, RestartStrategySchema } from '@runeya/packages-shared';\nimport type { ProcessStatus } from '@runeya/packages-shared';\nimport { router, protectedProcedure, requireServiceAction, getAllowedServiceIds } from '../trpc.js';\nimport type { AuthContext } from '../trpc.js';\nimport { serviceStore } from '../../services/service-store.js';\nimport { agentManager } from '../../services/agent-manager.js';\nimport { auditService } from '../../services/audit-service.js';\nimport { projectStore } from '../../services/project-store.js';\nimport { environmentResolver } from '../../services/environment-resolver.js';\nimport { environmentStore } from '../../services/environment-store.js';\nimport { settingsManager } from '../../services/settings-manager.js';\nimport { nativeParsers } from '@runeya/packages-shared';\nimport { ServiceShortcutSchema, ServiceCommandSchema, DockerConfigSchema, LogSourceConfigSchema, AGENT_STOP_FETCH_TIMEOUT } from '@runeya/packages-shared';\nimport type { ServiceConfig } from '@runeya/packages-shared';\nimport { env } from '../../config/env.js';\n\n/**\n * Resolve the effective agentId for a service.\n * Priority: service.agentId (explicit override) → activeEnvironment.agentId → null\n */\nexport async function resolveEffectiveAgentId(service: ServiceConfig): Promise<string | null> {\n if (service.agentId) return service.agentId;\n const projects = await projectStore.list();\n const project = projects.find(p => p.serviceIds.includes(service.id));\n if (!project?.activeEnvironmentId) return null;\n const activeEnv = await environmentStore.get(project.activeEnvironmentId);\n return activeEnv?.agentId ?? null;\n}\n\n/**\n * Helper to resolve service variables to env dict before deployment.\n * Finds the project containing this service and uses its activeEnvironmentId.\n * Also resolves parserIds to full parser definitions.\n */\nexport async function resolveServiceVariables(service: ServiceConfig): Promise<ServiceConfig> {\n // Find the project containing this service\n const projects = await projectStore.list();\n const project = projects.find(p => p.serviceIds.includes(service.id));\n\n let resolvedService: ServiceConfig = service;\n\n // Resolve parser IDs to full parser definitions (always, regardless of environment)\n try {\n if (service.parserIds && service.parserIds.length > 0) {\n const settings = await settingsManager.getSettings();\n const allParsers = [...nativeParsers, ...(settings.logParsers || [])];\n const resolvedParsers = service.parserIds\n .map(id => allParsers.find(p => p.id === id))\n .filter((p) => p !== undefined);\n resolvedService = { ...resolvedService, resolvedLogParsers: resolvedParsers };\n }\n } catch (err) {\n console.error('[service-router] Failed to resolve parsers for service', service.id + ':', (err as Error).message);\n }\n\n if (!project || !project.activeEnvironmentId) {\n // No project or no active environment — nothing more to resolve\n return resolvedService;\n }\n\n // Resolve variables to env dict\n try {\n const resolved = await environmentResolver.resolveForService({\n serviceId: service.id,\n activeEnvironmentId: project.activeEnvironmentId,\n });\n\n // Populate transient env/envSecrets on service config for agent consumption\n const serviceBuiltins: Record<string, string> = {\n HOST: env.HOST,\n HOST_LAN: '0.0.0.0',\n };\n\n // Interpolate {{service.KEY}} placeholders left untouched by the environment resolver\n const interpolatedEnv: Record<string, string> = {};\n for (const [key, value] of Object.entries(resolved.env)) {\n interpolatedEnv[key] = value.replace(/\\{\\{service\\.([^}]+)\\}\\}/g, (match, k) =>\n serviceBuiltins[k] !== undefined ? serviceBuiltins[k] : match,\n );\n }\n\n resolvedService = {\n ...resolvedService,\n env: interpolatedEnv,\n envSecrets: [...resolved.envSecrets],\n };\n } catch (err) {\n console.error('[service-router] Failed to resolve variables for service', service.id + ':', (err as Error).message);\n }\n\n return resolvedService;\n}\n\n\nconst DockerConfigInput = DockerConfigSchema;\n\nexport const serviceRouter = router({\n list: protectedProcedure\n .meta({ openapi: { method: 'GET', path: '/services', tags: ['services'], summary: 'List all services', protect: true } })\n .output(z.any())\n .query(async ({ ctx }) => {\n const all = await serviceStore.list();\n const allowedIds = getAllowedServiceIds(ctx as AuthContext);\n const filtered = allowedIds ? all.filter(s => allowedIds.has(s.id)) : all;\n return Promise.all(filtered.map(async (s) => ({\n ...s,\n effectiveAgentId: await resolveEffectiveAgentId(s),\n })));\n }),\n\n get: protectedProcedure\n .meta({ openapi: { method: 'GET', path: '/services/{id}', tags: ['services'], summary: 'Get a service by ID', protect: true } })\n .input(z.object({ id: z.string().max(128) }))\n .output(z.any())\n .query(async ({ input, ctx }) => {\n requireServiceAction(ctx as AuthContext, input.id, 'service:read');\n const service = await serviceStore.get(input.id);\n if (!service) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Service ${input.id} not found` });\n }\n return service;\n }),\n\n create: protectedProcedure\n .meta({ openapi: { method: 'POST', path: '/services', tags: ['services'], summary: 'Create a new service', protect: true } })\n .output(z.any())\n .input(\n z.object({\n agentId: z.string().max(128).optional(),\n name: z.string().min(1).max(200),\n commands: z.array(ServiceCommandSchema).max(50).optional(),\n cwd: z.string().max(4096).optional(),\n ports: z.array(z.number().int().min(1).max(65535)).max(20).optional(),\n groups: z.array(z.string().max(200)).max(20).optional(),\n description: z.string().max(2000).optional(),\n docsPath: z.string().max(4096).optional(),\n url: z.string().max(2048).optional(),\n localUrls: z.array(z.object({\n url: z.string().max(253),\n port: z.number().int().min(1).max(65535),\n })).max(20).optional(),\n openapiUrl: z.string().max(2048).optional(),\n git: z.object({ remote: z.string().max(2048).optional(), home: z.string().max(2048).optional() }).optional(),\n meta: z.record(z.string().max(256), z.string().max(2000)).optional()\n .refine((obj) => !obj || Object.keys(obj).length <= 100, { message: 'Too many meta keys (max 100)' }),\n runner: z.enum(['native', 'docker']).optional().default('native'),\n dockerConfig: DockerConfigInput.optional(),\n healthCheck: HealthCheckSchema.optional(),\n autoRestart: z.boolean().optional().default(false),\n restartStrategy: RestartStrategySchema.optional(),\n maxRestarts: z.number().int().nonnegative().optional(),\n restartBackoffMs: z.number().int().positive().optional().default(1000),\n orgId: z.string().max(128).nullable().optional(),\n shortcuts: z.array(ServiceShortcutSchema).max(50).optional(),\n parserIds: z.array(z.string().max(128)).max(50).optional(),\n }),\n )\n .mutation(async ({ input }) => {\n // Validate agent exists (only if explicitly provided)\n if (input.agentId) {\n const status = agentManager.getStatus(input.agentId);\n if (!status) {\n throw new TRPCError({\n code: 'NOT_FOUND',\n message: `Agent ${input.agentId} not found`\n });\n }\n }\n\n if (input.runner === 'docker') {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Docker runner is not yet supported. Use \"native\" runner.' });\n }\n const service = await serviceStore.create({\n ...input,\n agentId: input.agentId,\n });\n await auditService.log({ userId: 'local', action: 'create', entityType: 'service', entityId: service.id, metadata: { name: input.name } });\n return service;\n }),\n\n update: protectedProcedure\n .meta({ openapi: { method: 'PATCH', path: '/services/{id}', tags: ['services'], summary: 'Update a service', protect: true } })\n .output(z.any())\n .input(\n z.object({\n id: z.string().max(128),\n agentId: z.string().max(128).nullable().optional(), // null = clear (inherit from env)\n name: z.string().min(1).max(200).optional(),\n commands: z.array(ServiceCommandSchema).max(50).optional(),\n cwd: z.string().max(4096).nullable().optional(),\n ports: z.array(z.number().int().min(1).max(65535)).max(20).optional(),\n groups: z.array(z.string().max(200)).max(20).optional(),\n description: z.string().max(2000).optional(),\n docsPath: z.string().max(4096).optional(),\n url: z.string().max(2048).optional(),\n localUrls: z.array(z.object({\n url: z.string().max(253),\n port: z.number().int().min(1).max(65535),\n })).max(20).optional(),\n openapiUrl: z.string().max(2048).optional(),\n git: z.object({ remote: z.string().max(2048).optional(), home: z.string().max(2048).optional() }).nullable().optional(),\n meta: z.record(z.string().max(256), z.string().max(2000)).nullable().optional()\n .refine((obj) => !obj || Object.keys(obj).length <= 100, { message: 'Too many meta keys (max 100)' }),\n runner: z.enum(['native', 'docker']).optional(),\n dockerConfig: DockerConfigInput.optional(),\n healthCheck: HealthCheckSchema.nullable().optional(),\n autoRestart: z.boolean().optional(),\n clearLogsOnStart: z.boolean().optional(),\n restartStrategy: RestartStrategySchema.optional(),\n maxRestarts: z.number().int().nonnegative().optional(),\n restartBackoffMs: z.number().int().positive().optional(),\n orgId: z.string().max(128).nullable().optional(),\n shortcuts: z.array(ServiceShortcutSchema).max(50).optional(),\n parserIds: z.array(z.string().max(128)).max(50).optional(),\n logSources: z.array(LogSourceConfigSchema).max(20).optional(),\n }),\n )\n .mutation(async ({ input }) => {\n const existing = await serviceStore.get(input.id);\n if (!existing) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Service ${input.id} not found` });\n }\n\n // If changing agentId (including clearing it), stop the service on the old agent if running\n let stoppedForAgentChange = false;\n if (input.agentId !== undefined && input.agentId !== existing.agentId && existing.agentId) {\n const oldAgentStatus = agentManager.getStatus(existing.agentId);\n if (oldAgentStatus?.connected) {\n try {\n const processes = await agentManager.agentQuery<ProcessStatus[]>(existing.agentId, 'process.list');\n const proc = processes.find((p) => p.serviceId === input.id);\n if (proc && (proc.state === 'running' || proc.state === 'starting')) {\n await agentManager.agentMutation(existing.agentId, 'process.stop', { id: input.id }, AGENT_STOP_FETCH_TIMEOUT);\n stoppedForAgentChange = true;\n }\n } catch {\n // Agent unreachable or stop failed — allow the config change anyway\n }\n }\n\n // Validate new agent exists (only when setting a non-null agentId)\n if (input.agentId) {\n const newAgentStatus = agentManager.getStatus(input.agentId);\n if (!newAgentStatus) {\n throw new TRPCError({\n code: 'NOT_FOUND',\n message: `Agent ${input.agentId} not found`\n });\n }\n }\n }\n\n const service = await serviceStore.update(input);\n if (!service) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Service ${input.id} not found` });\n }\n\n // If service was renamed, cascade to service-scoped environment names\n if (input.name && input.name !== existing.name) {\n await environmentStore.renameByReference(input.id, input.name);\n }\n\n // Propagate config to assigned agent (only if service has an explicit agentId)\n if (service.agentId) {\n const agentStatus = agentManager.getStatus(service.agentId);\n if (agentStatus?.connected) {\n try {\n const resolvedService = await resolveServiceVariables(service);\n await agentManager.agentMutation(service.agentId, 'process.updateConfig', {\n serviceId: service.id,\n config: resolvedService,\n });\n } catch (err) {\n console.debug('[service-router] Failed to propagate config to agent', service.agentId + ':', (err as Error).message);\n }\n }\n }\n\n await auditService.log({ userId: 'local', action: 'update', entityType: 'service', entityId: input.id });\n return { ...service, effectiveAgentId: await resolveEffectiveAgentId(service), stoppedForAgentChange };\n }),\n\n delete: protectedProcedure\n .meta({ openapi: { method: 'DELETE', path: '/services/{id}', tags: ['services'], summary: 'Delete a service', protect: true } })\n .input(z.object({ id: z.string().max(128) }))\n .output(z.object({ success: z.literal(true) }))\n .mutation(async ({ input }) => {\n const deleted = await serviceStore.delete(input.id);\n if (!deleted) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Service ${input.id} not found` });\n }\n await auditService.log({ userId: 'local', action: 'delete', entityType: 'service', entityId: input.id });\n return { success: true as const };\n }),\n\n checkCwd: protectedProcedure\n .input(z.object({ id: z.string().max(128), checkReachability: z.boolean().optional() }))\n .query(async ({ input }) => {\n const service = await serviceStore.get(input.id);\n if (!service) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Service ${input.id} not found` });\n }\n const effectiveAgentId = await resolveEffectiveAgentId(service);\n if (!effectiveAgentId) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'No agent configured for this service' });\n }\n\n // Delegate entirely to the agent — it resolves $VAR from its own process.env\n const agentResult = await agentManager.agentQuery<{\n exists: boolean;\n actualRemote: string | null;\n unreachable: boolean;\n resolvedCwd: string;\n unresolvedVars: string[];\n }>(effectiveAgentId, 'git.checkCwd', {\n cwd: service.cwd || '.',\n remote: service.git?.remote,\n checkReachability: input.checkReachability,\n });\n\n const { exists, actualRemote, unreachable, resolvedCwd, unresolvedVars } = agentResult;\n\n if (unresolvedVars.length > 0) {\n return { exists: false, canClone: false, unresolvedVars, resolvedCwd, gitMismatch: null };\n }\n\n const canClone = !!service.git?.remote && (!exists || actualRemote === null);\n\n let gitMismatch: { actual: string | null; configured: string; unreachable?: boolean } | null = null;\n if (exists && service.git?.remote && !canClone) {\n if (actualRemote === null) {\n gitMismatch = { actual: null, configured: service.git.remote };\n } else if (actualRemote !== service.git.remote) {\n gitMismatch = { actual: actualRemote, configured: service.git.remote };\n } else if (unreachable) {\n gitMismatch = { actual: actualRemote, configured: service.git.remote, unreachable: true };\n }\n }\n\n return { exists, canClone, unresolvedVars: [], resolvedCwd, gitMismatch };\n }),\n\n cloneRepository: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const service = await serviceStore.get(input.id);\n if (!service) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Service ${input.id} not found` });\n }\n if (!service.git?.remote) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Service has no git remote configured' });\n }\n const effectiveAgentId = await resolveEffectiveAgentId(service);\n if (!effectiveAgentId) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'No agent configured for this service' });\n }\n\n // Delegate entirely to the agent — it resolves $VAR from its own process.env\n await agentManager.agentMutation(effectiveAgentId, 'git.clone', {\n remote: service.git.remote,\n cwd: service.cwd || '.',\n }, 5 * 60 * 1000);\n\n return { success: true as const };\n }),\n});\n","import { readFile, writeFile, rename, mkdir, chmod } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { env } from '../config/env.js';\nimport { SettingsSchema, SchemaVersionSchema, SettingsPrivateSchema } from '@runeya/packages-shared';\nimport type { Settings, SchemaVersion, SettingsPrivate } from '@runeya/packages-shared';\n\nconst SETTINGS_FILE = 'settings.json';\nconst SETTINGS_PRIVATE_FILE = 'settings.private.json';\nconst SCHEMA_VERSION_FILE = 'schema-version.json';\nconst CURRENT_SCHEMA_VERSION = 4;\n\nclass SettingsManager {\n private settings: Settings | null = null;\n private settingsPrivate: SettingsPrivate | null = null;\n private schemaVersion: SchemaVersion | null = null;\n\n private async ensureDir(): Promise<void> {\n await mkdir(env.DATA_DIR, { recursive: true });\n }\n\n private async atomicWrite(filename: string, data: unknown): Promise<void> {\n await this.ensureDir();\n const filePath = join(env.DATA_DIR, filename);\n const tmpPath = filePath + '.tmp';\n await writeFile(tmpPath, JSON.stringify(data, null, 2), 'utf-8');\n await rename(tmpPath, filePath);\n await chmod(filePath, 0o600);\n }\n\n private async readJson<T>(filename: string): Promise<T | null> {\n try {\n const raw = await readFile(join(env.DATA_DIR, filename), 'utf-8');\n return JSON.parse(raw) as T;\n } catch {\n return null;\n }\n }\n\n async getSettings(): Promise<Settings> {\n if (!this.settings) {\n const raw = await this.readJson<unknown>(SETTINGS_FILE);\n const parsed = raw ? SettingsSchema.safeParse(raw) : null;\n if (parsed?.success) {\n this.settings = parsed.data;\n } else {\n this.settings = SettingsSchema.parse({ mode: env.MODE, cloudUrl: env.CLOUD_URL ?? null });\n await this.saveSettings(this.settings);\n }\n }\n return this.settings;\n }\n\n async saveSettings(settings: Settings): Promise<void> {\n this.settings = settings;\n await this.atomicWrite(SETTINGS_FILE, settings);\n }\n\n async getPrivateSettings(): Promise<SettingsPrivate> {\n if (!this.settingsPrivate) {\n const raw = await this.readJson<unknown>(SETTINGS_PRIVATE_FILE);\n const parsed = raw ? SettingsPrivateSchema.safeParse(raw) : null;\n if (parsed?.success) {\n this.settingsPrivate = parsed.data;\n } else {\n this.settingsPrivate = SettingsPrivateSchema.parse({});\n await this.savePrivateSettings(this.settingsPrivate);\n }\n }\n return this.settingsPrivate;\n }\n\n async savePrivateSettings(settings: SettingsPrivate): Promise<void> {\n this.settingsPrivate = settings;\n await this.atomicWrite(SETTINGS_PRIVATE_FILE, settings);\n }\n\n async getSchemaVersion(): Promise<SchemaVersion> {\n if (!this.schemaVersion) {\n const raw = await this.readJson<unknown>(SCHEMA_VERSION_FILE);\n const parsed = raw ? SchemaVersionSchema.safeParse(raw) : null;\n if (parsed?.success) {\n this.schemaVersion = parsed.data;\n } else {\n this.schemaVersion = { version: CURRENT_SCHEMA_VERSION, migratedAt: new Date() };\n await this.saveSchemaVersion(this.schemaVersion);\n }\n }\n return this.schemaVersion;\n }\n\n async saveSchemaVersion(sv: SchemaVersion): Promise<void> {\n this.schemaVersion = sv;\n await this.atomicWrite(SCHEMA_VERSION_FILE, sv);\n }\n\n getCurrentSchemaVersion(): number {\n return CURRENT_SCHEMA_VERSION;\n }\n}\n\nexport const settingsManager = new SettingsManager();\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { LOG_BUFFER_SIZE } from '@runeya/packages-shared';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { agentManager } from '../../services/agent-manager.js';\nimport type { AgentStatus } from '@runeya/packages-shared';\n\nconst SUBSCRIPTION_QUEUE_MAX = LOG_BUFFER_SIZE;\n\nexport const agentRouter = router({\n /** List all registered agents with their connection status */\n list: protectedProcedure.query(() => {\n return agentManager.listAgents();\n }),\n\n /** Get a single agent's config and status */\n get: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(({ input }) => {\n const agent = agentManager.getAgent(input.id);\n if (!agent) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Agent ${input.id} not found` });\n }\n return {\n config: { ...agent.config, passphrase: '***' },\n status: agent.status,\n };\n }),\n\n /** Test connectivity to an agent given url + passphrase */\n testConnection: protectedProcedure\n .input(\n z.object({\n url: z.string().url().max(2048),\n passphrase: z.string().min(1).max(1024).optional(),\n agentId: z.string().max(128).optional(),\n }),\n )\n .mutation(async ({ input }) => {\n let passphrase = input.passphrase;\n let targetUrl = input.url;\n if (!passphrase && input.agentId) {\n const agent = agentManager.getAgentConfig(input.agentId);\n if (!agent) {\n throw new TRPCError({ code: 'NOT_FOUND', message: 'Agent not found' });\n }\n passphrase = agent.passphrase;\n // SECURITY: When using a stored passphrase, always use the stored agent URL\n // to prevent exfiltration of the passphrase to an attacker-controlled URL\n targetUrl = agent.url;\n }\n if (!passphrase) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Passphrase is required' });\n }\n\n const url = new URL('/api/trpc/health.check', targetUrl);\n try {\n const res = await fetch(url.toString(), {\n headers: { 'Authorization': `Bearer ${passphrase}`, 'Content-Type': 'application/json' },\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) {\n return { success: false as const, error: `HTTP ${res.status} ${res.statusText}` };\n }\n const json = await res.json() as { error?: { message?: string }; result?: { data?: { uptime?: number } } };\n if (json.error) {\n return { success: false as const, error: json.error.message ?? 'Agent returned an error' };\n }\n return { success: true as const, uptime: json.result?.data?.uptime };\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Unknown error';\n return { success: false as const, error: msg };\n }\n }),\n\n /** Register a new agent */\n register: protectedProcedure\n .input(\n z.object({\n name: z.string().min(1).max(100),\n url: z.string().url().max(2048),\n passphrase: z.string().min(1).max(1024),\n }),\n )\n .mutation(async ({ input }) => {\n const config = await agentManager.register(input.name, input.url, input.passphrase);\n return { ...config, passphrase: '***' };\n }),\n\n /** Update an existing agent */\n update: protectedProcedure\n .input(\n z.object({\n id: z.string().max(128),\n name: z.string().min(1).max(100).optional(),\n url: z.string().url().max(2048).optional(),\n passphrase: z.string().min(1).max(1024).optional(),\n passthroughEnv: z.array(\n z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/).max(256),\n ).max(100).optional(),\n }),\n )\n .mutation(async ({ input }) => {\n try {\n const { id, ...fields } = input;\n const config = await agentManager.update(id, fields);\n return { ...config, passphrase: '***' };\n } catch (err) {\n if (err instanceof Error) {\n if (err.message.includes('not found')) {\n throw new TRPCError({ code: 'NOT_FOUND', message: err.message });\n }\n if (err.message.includes('Cannot modify')) {\n throw new TRPCError({ code: 'FORBIDDEN', message: err.message });\n }\n }\n throw err;\n }\n }),\n\n /** Get resolved passthrough env values from an agent */\n getPassthroughEnv: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(async ({ input }) => {\n try {\n return await agentManager.agentQuery<Record<string, string>>(input.id, 'config.getPassthroughEnv');\n } catch {\n return {};\n }\n }),\n\n /** Remove a registered agent */\n remove: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n try {\n const removed = await agentManager.remove(input.id);\n if (!removed) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Agent ${input.id} not found` });\n }\n return { success: true as const };\n } catch (err) {\n if (err instanceof Error && err.message === 'Cannot remove the local agent') {\n throw new TRPCError({ code: 'FORBIDDEN', message: err.message });\n }\n throw err;\n }\n }),\n\n /** Subscribe to real-time agent status changes */\n onStatus: protectedProcedure.subscription(async function* () {\n // Yield current state of all agents immediately so the client\n // doesn't have to wait for the next health tick.\n for (const agent of agentManager.listAgents()) {\n yield { agentId: agent.config.id, status: agent.status };\n }\n\n const queue: Array<{ agentId: string; status: AgentStatus }> = [];\n let resolve: (() => void) | null = null;\n\n const handler = (event: { agentId: string; status: AgentStatus }) => {\n if (queue.length >= SUBSCRIPTION_QUEUE_MAX) queue.shift();\n queue.push(event);\n if (resolve) {\n resolve();\n resolve = null;\n }\n };\n\n agentManager.on('status', handler);\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n agentManager.off('status', handler);\n }\n }),\n});\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { LOG_BUFFER_SIZE, ServiceShortcutSchema, AGENT_LONG_FETCH_TIMEOUT, AGENT_STOP_FETCH_TIMEOUT } from '@runeya/packages-shared';\nimport type { ProcessStatus, ProcessMetrics } from '@runeya/packages-shared';\nimport { router, protectedProcedure, requireServiceAction, getAllowedServiceIds } from '../trpc.js';\nimport type { AuthContext } from '../trpc.js';\nimport { agentManager } from '../../services/agent-manager.js';\nimport { auditService } from '../../services/audit-service.js';\nimport { serviceStore } from '../../services/service-store.js';\nimport { resolveServiceVariables, resolveEffectiveAgentId } from './service.js';\n\n/** Max items in a subscription queue before dropping oldest */\nconst SUBSCRIPTION_QUEUE_MAX = LOG_BUFFER_SIZE;\n\n/**\n * Helper that creates a queued async generator forwarding events from agentManager.\n * Deduplicates the queue+handler pattern used by all process subscriptions.\n */\nasync function* forwardEvents<T = Record<string, unknown>>(\n eventName: string,\n filter?: (data: Record<string, unknown>) => boolean,\n): AsyncGenerator<T> {\n const queue: T[] = [];\n let resolve: (() => void) | null = null;\n\n const handler = (data: Record<string, unknown>) => {\n if (filter && !filter(data)) return;\n if (queue.length >= SUBSCRIPTION_QUEUE_MAX) queue.shift();\n queue.push(data as T);\n if (resolve) { resolve(); resolve = null; }\n };\n\n agentManager.on(eventName, handler);\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n agentManager.off(eventName, handler);\n }\n}\n\n/**\n * Helper for log batch forwarding. The AgentWSBridge wraps array data as\n * `{ batch: ParsedLog[], agentId }`. We filter by agentId + processId,\n * then yield the filtered batch to the frontend.\n */\nasync function* forwardLogBatches(\n agentId: string,\n processId: string,\n): AsyncGenerator<unknown[]> {\n const queue: unknown[][] = [];\n let resolve: (() => void) | null = null;\n\n const handler = (data: Record<string, unknown>) => {\n if (data.agentId !== agentId) return;\n const batch = data.batch as Array<Record<string, unknown>>;\n if (!Array.isArray(batch)) return;\n const filtered = batch.filter((log) => log.processId === processId);\n if (filtered.length === 0) return;\n if (queue.length >= SUBSCRIPTION_QUEUE_MAX) queue.shift();\n queue.push(filtered);\n if (resolve) { resolve(); resolve = null; }\n };\n\n agentManager.on('process:log', handler);\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n agentManager.off('process:log', handler);\n }\n}\n\nexport const processRouter = router({\n /** List all processes across all connected agents */\n list: protectedProcedure\n .meta({ openapi: { method: 'GET', path: '/processes', tags: ['processes'], summary: 'List all processes', protect: true } })\n .output(z.any())\n .query(async () => {\n const agents = agentManager.listAgents();\n const results: Array<ProcessStatus & { agentId: string }> = [];\n\n await Promise.allSettled(\n agents\n .filter(a => a.status.connected)\n .map(async (a) => {\n try {\n const processes = await agentManager.agentQuery<ProcessStatus[]>(a.config.id, 'process.list');\n for (const proc of processes) {\n results.push({ ...proc, agentId: a.config.id });\n }\n } catch {\n // Agent unreachable, skip\n }\n }),\n );\n\n return results;\n }),\n\n\n /** Get a single process from a specific agent */\n get: protectedProcedure\n .meta({ openapi: { method: 'GET', path: '/processes/{agentId}/{id}', tags: ['processes'], summary: 'Get a process by agent and ID', protect: true } })\n .input(z.object({ agentId: z.string().max(128), id: z.string().max(128) }))\n .output(z.any())\n .query(async ({ input, ctx }) => {\n requireServiceAction(ctx as AuthContext, input.id, 'service:read');\n const status = agentManager.getStatus(input.agentId);\n if (!status) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Agent ${input.agentId} not found` });\n }\n\n const proc = await agentManager.agentQuery<ProcessStatus>(input.agentId, 'process.get', { id: input.id });\n return { ...proc, agentId: input.agentId };\n }),\n\n\n /** Start a process on an agent.\n * Lazy deploy: the agent only learns about a service when it is first started\n * (or restarted). This avoids pushing configs for every service at agent boot,\n * which would be wasteful when many services are never started.\n * The deploy call is idempotent — creates the process if missing, updates config if it exists. */\n start: protectedProcedure\n .meta({ openapi: { method: 'POST', path: '/processes/{agentId}/{processId}/start', tags: ['processes'], summary: 'Start a process', protect: true } })\n .input(z.object({ agentId: z.string().max(128).optional(), processId: z.string().max(128) }))\n .output(z.any())\n .mutation(async ({ input, ctx }) => {\n requireServiceAction(ctx as AuthContext, input.processId, 'service:start');\n const service = await serviceStore.get(input.processId);\n\n // Resolve effective agentId: service.agentId > environment.agentId > explicit input (fallback)\n // Service/environment config always wins so that changing the agent takes effect immediately.\n const effectiveAgentId = (service ? await resolveEffectiveAgentId(service) : null) ?? input.agentId ?? null;\n if (!effectiveAgentId) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'No agent assigned to this service. Set an agent on the service or on the active environment.' });\n }\n\n // Always deploy first (idempotent — creates process if missing, updates config if exists)\n if (service) {\n try {\n const resolved = await resolveServiceVariables(service);\n await agentManager.agentMutation(effectiveAgentId, 'process.deploy', resolved);\n } catch (err) {\n console.debug('[process-router] Failed to deploy before start for', input.processId + ':', (err as Error).message);\n }\n }\n\n if (service?.clearLogsOnStart) {\n try {\n await agentManager.agentMutation(effectiveAgentId, 'process.clearLogBuffer', { id: input.processId });\n agentManager.emit('process:log', { agentId: effectiveAgentId, batch: [{ processId: input.processId, __clearLogBuffer: true }] });\n } catch (err) {\n console.debug('[process-router] Failed to clear logs before start for', input.processId + ':', (err as Error).message);\n }\n }\n\n let result: ProcessStatus;\n try {\n result = await agentManager.agentMutation<ProcessStatus>(effectiveAgentId, 'process.start', { id: input.processId });\n } catch (err: unknown) {\n const err_ = err as { cause?: { code?: string }; message?: string; name?: string };\n const isFetchError = err_?.cause?.code === 'ECONNREFUSED' || err_?.message === 'fetch failed' || err_?.name === 'TypeError';\n throw new TRPCError({\n code: 'INTERNAL_SERVER_ERROR',\n message: isFetchError\n ? `Cannot reach agent — make sure the agent is running`\n : (err_?.message ?? 'Failed to start process'),\n });\n }\n await auditService.log({ userId: 'local', action: 'start', entityType: 'process', entityId: input.processId, metadata: { agentId: effectiveAgentId } });\n return { ...result, agentId: effectiveAgentId };\n }),\n\n /** Stop a process on an agent */\n stop: protectedProcedure\n .meta({ openapi: { method: 'POST', path: '/processes/{agentId}/{processId}/stop', tags: ['processes'], summary: 'Stop a process', protect: true } })\n .input(z.object({ agentId: z.string().max(128), processId: z.string().max(128) }))\n .output(z.any())\n .mutation(async ({ input, ctx }) => {\n requireServiceAction(ctx as AuthContext, input.processId, 'service:stop');\n const result = await agentManager.agentMutation<ProcessStatus>(input.agentId, 'process.stop', { id: input.processId }, AGENT_STOP_FETCH_TIMEOUT);\n await auditService.log({ userId: 'local', action: 'stop', entityType: 'process', entityId: input.processId, metadata: { agentId: input.agentId } });\n return { ...result, agentId: input.agentId };\n }),\n\n /** Restart a process on an agent.\n * Sends stop → deploy (latest resolved config) → start so that\n * config/variable changes take effect. Same lazy deploy pattern as start. */\n restart: protectedProcedure\n .meta({ openapi: { method: 'POST', path: '/processes/{agentId}/{processId}/restart', tags: ['processes'], summary: 'Restart a process', protect: true } })\n .input(z.object({ agentId: z.string().max(128).optional(), processId: z.string().max(128) }))\n .output(z.any())\n .mutation(async ({ input, ctx }) => {\n requireServiceAction(ctx as AuthContext, input.processId, 'service:restart');\n const service = await serviceStore.get(input.processId);\n\n // Resolve effective agentId: service.agentId > environment.agentId > explicit input (fallback)\n // Service/environment config always wins so that changing the agent takes effect immediately.\n const effectiveAgentId = (service ? await resolveEffectiveAgentId(service) : null) ?? input.agentId ?? null;\n if (!effectiveAgentId) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'No agent assigned to this service. Set an agent on the service or on the active environment.' });\n }\n\n // 1. Stop the process (ignore \"not found\" — process may not exist on this agent yet)\n try {\n await agentManager.agentMutation<{ success: true }>(effectiveAgentId, 'process.stop', { id: input.processId }, AGENT_STOP_FETCH_TIMEOUT);\n } catch (err) {\n console.debug('[process-router] Stop before restart ignored (process not found on agent?):', (err as Error).message);\n }\n\n // 2. Re-deploy with latest config (idempotent — updates config now that process is stopped)\n if (service) {\n try {\n const resolved = await resolveServiceVariables(service);\n await agentManager.agentMutation(effectiveAgentId, 'process.deploy', resolved);\n } catch (err) {\n console.debug('[process-router] Failed to deploy before restart for', input.processId + ':', (err as Error).message);\n }\n }\n\n // 3. Clear logs if configured\n if (service?.clearLogsOnStart) {\n try {\n await agentManager.agentMutation(effectiveAgentId, 'process.clearLogBuffer', { id: input.processId });\n agentManager.emit('process:log', { agentId: effectiveAgentId, batch: [{ processId: input.processId, __clearLogBuffer: true }] });\n } catch (err) {\n console.debug('[process-router] Failed to clear logs before restart for', input.processId + ':', (err as Error).message);\n }\n }\n\n // 4. Start with updated config\n const result = await agentManager.agentMutation<ProcessStatus>(effectiveAgentId, 'process.start', { id: input.processId });\n await auditService.log({ userId: 'local', action: 'restart', entityType: 'process', entityId: input.processId, metadata: { agentId: effectiveAgentId } });\n return { ...result, agentId: effectiveAgentId };\n }),\n\n /** Get buffered logs for a process from an agent */\n logs: protectedProcedure\n .meta({ openapi: { method: 'GET', path: '/processes/{agentId}/{processId}/logs', tags: ['processes'], summary: 'Get buffered logs for a process', protect: true } })\n .input(z.object({ agentId: z.string().max(128), processId: z.string().max(128) }))\n .output(z.any())\n .query(async ({ input, ctx }) => {\n requireServiceAction(ctx as AuthContext, input.processId, 'logs:read');\n return agentManager.agentQuery(input.agentId, 'process.logs', { id: input.processId });\n }),\n\n /** Clear buffered logs for a process on an agent */\n clearLogBuffer: protectedProcedure\n .input(z.object({ agentId: z.string().max(128), processId: z.string().max(128) }))\n .mutation(async ({ input }) => {\n await agentManager.agentMutation(input.agentId, 'process.clearLogBuffer', { id: input.processId });\n await auditService.log({ userId: 'local', action: 'clearLogBuffer', entityType: 'process', entityId: input.processId, metadata: { agentId: input.agentId } });\n return { success: true };\n }),\n\n /** Execute a shortcut command on an agent, streaming output into the process log */\n executeShortcut: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n processId: z.string().max(128),\n shortcut: ServiceShortcutSchema,\n }))\n .mutation(async ({ input }) => {\n // Lazy deploy: ensure the agent knows about this service (same pattern as start/restart)\n const service = await serviceStore.get(input.processId);\n if (service) {\n try {\n const resolved = await resolveServiceVariables(service);\n await agentManager.agentMutation(input.agentId, 'process.deploy', resolved);\n } catch (err) {\n console.debug('[process-router] Failed to deploy before executeShortcut for', input.processId + ':', (err as Error).message);\n }\n }\n\n const result = await agentManager.agentMutation<{ exitCode: number | null }>(\n input.agentId, 'process.executeShortcut',\n { id: input.processId, shortcut: input.shortcut },\n AGENT_LONG_FETCH_TIMEOUT,\n );\n await auditService.log({\n userId: 'local',\n action: 'executeShortcut',\n entityType: 'process',\n entityId: input.processId,\n metadata: { agentId: input.agentId, shortcutId: input.shortcut.id, shortcutLabel: input.shortcut.label },\n });\n return result;\n }),\n\n /** Execute an ad-hoc command on an agent, streaming output into the process log */\n executeAdHocCommand: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n processId: z.string().max(128),\n command: z.string().min(1).max(4096),\n cwd: z.string().max(4096).optional(),\n commandId: z.string().max(128).optional(),\n }))\n .mutation(async ({ input }) => {\n // Lazy deploy: ensure the agent knows about this service (same pattern as start/restart)\n const service = await serviceStore.get(input.processId);\n if (service) {\n try {\n const resolved = await resolveServiceVariables(service);\n await agentManager.agentMutation(input.agentId, 'process.deploy', resolved);\n } catch (err) {\n console.debug('[process-router] Failed to deploy before executeAdHocCommand for', input.processId + ':', (err as Error).message);\n }\n }\n\n const result = await agentManager.agentMutation<{ exitCode: number | null }>(\n input.agentId, 'process.executeAdHocCommand',\n { id: input.processId, command: input.command, cwd: input.cwd, commandId: input.commandId },\n AGENT_LONG_FETCH_TIMEOUT,\n );\n await auditService.log({\n userId: 'local',\n action: 'executeAdHocCommand',\n entityType: 'process',\n entityId: input.processId,\n metadata: { agentId: input.agentId, command: input.command },\n });\n return result;\n }),\n\n /** Cancel a running shortcut command on an agent */\n cancelShortcut: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n processId: z.string().max(128),\n shortcutId: z.string().max(128),\n }))\n .mutation(async ({ input }) => {\n await agentManager.agentMutation(input.agentId, 'process.cancelShortcut', { id: input.processId, shortcutId: input.shortcutId });\n return { success: true };\n }),\n\n /** Cancel a running ad-hoc command on an agent */\n cancelAdHocCommand: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n processId: z.string().max(128),\n commandId: z.string().max(128).optional(),\n }))\n .mutation(async ({ input }) => {\n await agentManager.agentMutation(input.agentId, 'process.cancelAdHocCommand', { id: input.processId, commandId: input.commandId });\n return { success: true };\n }),\n\n /** Get current metrics for a process from an agent */\n metrics: protectedProcedure\n .input(z.object({ agentId: z.string().max(128), processId: z.string().max(128) }))\n .query(async ({ input }) => {\n return agentManager.agentQuery<ProcessMetrics>(input.agentId, 'process.metrics', { id: input.processId });\n }),\n\n /**\n * Subscribe to real-time log stream for a process.\n * Forwards batched events from the AgentWSBridge in real-time.\n * Historical logs are fetched separately via process.logs query.\n */\n onLog: protectedProcedure\n .input(z.object({ agentId: z.string().max(128), processId: z.string().max(128) }))\n .subscription(async function* ({ input, ctx }) {\n requireServiceAction(ctx as AuthContext, input.processId, 'logs:read');\n yield* forwardLogBatches(input.agentId, input.processId);\n }),\n\n /**\n * Subscribe to real-time status changes for processes.\n * Input is optional — omit agentId/processId for global monitoring (dashboard).\n * Forwards events from the AgentWSBridge in real-time.\n */\n onStatus: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128).optional(),\n processId: z.string().max(128).optional(),\n }).optional())\n .subscription(async function* ({ input, ctx }) {\n const allowedIds = getAllowedServiceIds(ctx as AuthContext);\n if (input?.processId) requireServiceAction(ctx as AuthContext, input.processId, 'service:status');\n\n // Yield initial state\n try {\n const agents = agentManager.listAgents();\n for (const agent of agents.filter(a => a.status.connected)) {\n if (input?.agentId && agent.config.id !== input.agentId) continue;\n try {\n const processes = await agentManager.agentQuery<any[]>(agent.config.id, 'process.list');\n for (const proc of processes) {\n if (input?.processId && proc.id !== input.processId) continue;\n if (allowedIds && !allowedIds.has(proc.id)) continue;\n yield { ...proc, agentId: agent.config.id };\n }\n } catch {\n // Agent unreachable, skip\n }\n }\n } catch {\n // Ignore errors during initial load\n }\n\n yield* forwardEvents('process:status', (d) => {\n if (input?.agentId && d.agentId !== input.agentId) return false;\n if (input?.processId && d.processId !== input.processId) return false;\n if (allowedIds && !allowedIds.has(d.processId as string)) return false;\n return true;\n });\n }),\n\n /** Subscribe to real-time metrics for a process. */\n onMetrics: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128).optional(),\n processId: z.string().max(128).optional(),\n }).optional())\n .subscription(async function* ({ input, ctx }) {\n const allowedIds = getAllowedServiceIds(ctx as AuthContext);\n if (input?.processId) requireServiceAction(ctx as AuthContext, input.processId, 'service:status');\n\n yield* forwardEvents<ProcessMetrics>('process:metrics', (d) => {\n if (input?.agentId && d.agentId !== input.agentId) return false;\n if (input?.processId && d.processId !== input.processId) return false;\n if (allowedIds && !allowedIds.has(d.processId as string)) return false;\n return true;\n });\n }),\n\n /** Subscribe to real-time health status changes. */\n onHealth: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128).optional(),\n processId: z.string().max(128).optional(),\n }).optional())\n .subscription(async function* ({ input, ctx }) {\n const allowedIds = getAllowedServiceIds(ctx as AuthContext);\n if (input?.processId) requireServiceAction(ctx as AuthContext, input.processId, 'service:healthcheck');\n\n yield* forwardEvents('process:health', (d) => {\n if (input?.agentId && d.agentId !== input.agentId) return false;\n if (input?.processId && d.processId !== input.processId) return false;\n if (allowedIds && !allowedIds.has(d.processId as string)) return false;\n return true;\n });\n }),\n});\n","import { z } from 'zod';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { auditService } from '../../services/audit-service.js';\n\nexport const auditRouter = router({\n list: protectedProcedure\n .input(z.object({\n action: z.string().max(50).optional(),\n entityType: z.string().max(50).optional(),\n entityId: z.string().max(100).optional(),\n limit: z.number().int().positive().max(100).default(50),\n offset: z.number().int().nonnegative().default(0),\n }).optional())\n .query(async ({ input }) => {\n return auditService.list(input ?? {});\n }),\n});\n","import { z } from 'zod';\nimport { router, publicProcedure, protectedProcedure } from '../trpc.js';\nimport { hasEncryptionKey, setEncryptionKey, getEncryptionKey } from '../../utils/encryption-key.js';\nimport { agentStore } from '../../services/agent-store.js';\nimport { agentSpawner } from '../../services/agent-spawner.js';\nimport { env } from '../../config/env.js';\n\nexport const setupRouter = router({\n /**\n * Check if encryption key is required (project initialized but no key).\n */\n needsEncryptionKey: publicProcedure.query(async () => {\n return {\n needsKey: !hasEncryptionKey(),\n };\n }),\n\n /**\n * Get current encryption key in hex format (for sharing with team).\n * Only available in local-simple mode for security.\n */\n getEncryptionKeyHex: protectedProcedure.query(async () => {\n if (env.MODE !== 'local-simple') {\n throw new Error('Encryption key export only available in local-simple mode');\n }\n\n const key = getEncryptionKey();\n if (!key) {\n throw new Error('No encryption key loaded');\n }\n\n return {\n keyHex: key.toString('hex'),\n };\n }),\n\n /**\n * Submit and validate encryption key.\n * Attempts to decrypt existing data to validate the key.\n * Spawns the local agent if in local-simple mode.\n */\n submitEncryptionKey: publicProcedure\n .input(\n z.object({\n keyHex: z.string().length(64).regex(/^[0-9a-f]+$/i, 'Invalid hex format'),\n }),\n )\n .mutation(async ({ input }) => {\n try {\n // Set the key\n await setEncryptionKey(input.keyHex);\n\n // Validate by attempting to read encrypted data\n // If agents.json exists with encrypted data, this will decrypt it\n await agentStore.list();\n\n // Spawn the local agent now that the encryption key is available\n // (in local-simple mode, the agent couldn't spawn during server startup\n // because the key wasn't available yet)\n if (env.MODE === 'local-simple') {\n console.log('[setup] Encryption key validated, spawning local agent...');\n await agentSpawner.spawnLocalAgent();\n }\n\n return { success: true };\n } catch (err: unknown) {\n // If decryption fails, the key is invalid\n const message = err instanceof Error ? err.message : 'Unknown error';\n throw new Error(`Invalid encryption key: ${message}`);\n }\n }),\n});\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { protectedProcedure, router, requireEnvAction } from '../trpc.js';\nimport type { AuthContext } from '../trpc.js';\nimport { environmentStore } from '../../services/environment-store.js';\nimport { environmentOverridesStore } from '../../services/environment-overrides-store.js';\nimport { environmentResolver } from '../../services/environment-resolver.js';\nimport { projectStore } from '../../services/project-store.js';\nimport { serviceStore } from '../../services/service-store.js';\nimport { CreateEnvironmentSchema, UpdateEnvironmentSchema, VariableSchema, VariableOverrideSchema } from '@runeya/packages-shared';\n\nexport const environmentRouter = router({\n list: protectedProcedure\n .input(z.object({ projectId: z.string().max(128) }))\n .query(async ({ input }) => {\n return await environmentStore.list(input.projectId);\n }),\n\n get: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(async ({ input }) => {\n const env = await environmentStore.get(input.id);\n if (!env) throw new TRPCError({ code: 'NOT_FOUND', message: `Environment ${input.id} not found` });\n return env;\n }),\n\n listByScope: protectedProcedure\n .input(z.object({ projectId: z.string().max(128), scope: z.enum(['global', 'service']) }))\n .query(async ({ input }) => {\n return await environmentStore.listByScope(input.projectId, input.scope);\n }),\n\n findServiceEnvironment: protectedProcedure\n .input(z.object({ serviceId: z.string().max(128), globalEnvId: z.string().max(128) }))\n .query(async ({ input }) => {\n return await environmentStore.findServiceEnvironment(input.serviceId, input.globalEnvId);\n }),\n\n create: protectedProcedure\n .input(CreateEnvironmentSchema)\n .mutation(async ({ input }) => {\n const env = await environmentStore.create(input);\n\n // Add environment to project's environmentIds list\n const project = await projectStore.get(input.projectId);\n if (project && !project.environmentIds?.includes(env.id)) {\n await projectStore.addEnvironment(input.projectId, env.id);\n }\n\n // If creating a global env, auto-create service-scoped envs for each service in the project\n if (env.scope === 'global' && project) {\n for (const serviceId of project.serviceIds) {\n const service = await serviceStore.get(serviceId);\n if (!service) continue;\n // Include service-scoped envs from parent globals so inheritance chains work correctly\n const parentServiceEnvIds: string[] = [];\n for (const parentGlobalId of env.parentIds) {\n const parentServiceEnv = await environmentStore.findServiceEnvironment(serviceId, parentGlobalId);\n if (parentServiceEnv) {\n parentServiceEnvIds.push(parentServiceEnv.id);\n }\n }\n const svcEnv = await environmentStore.create({\n projectId: input.projectId,\n name: `${service.name} (${env.name})`,\n scope: 'service',\n reference: serviceId,\n activateOn: env.id,\n parentIds: [env.id, ...parentServiceEnvIds],\n variables: {},\n });\n await projectStore.addEnvironment(input.projectId, svcEnv.id);\n }\n }\n\n return env;\n }),\n\n update: protectedProcedure\n .input(UpdateEnvironmentSchema)\n .mutation(async ({ input }) => {\n const existing = await environmentStore.get(input.id);\n if (!existing) throw new TRPCError({ code: 'NOT_FOUND', message: `Environment ${input.id} not found` });\n\n const env = await environmentStore.update(input);\n if (!env) throw new TRPCError({ code: 'NOT_FOUND', message: `Environment ${input.id} not found` });\n\n // If a global environment was renamed, cascade to service-scoped environment names\n if (env.scope === 'global' && input.name && input.name !== existing.name) {\n const project = await projectStore.get(env.projectId);\n if (project) {\n const serviceNames = new Map<string, string>();\n for (const serviceId of project.serviceIds) {\n const service = await serviceStore.get(serviceId);\n if (service) serviceNames.set(serviceId, service.name);\n }\n await environmentStore.renameByActivateOn(env.id, input.name, serviceNames);\n }\n }\n\n return env;\n }),\n\n delete: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const env = await environmentStore.get(input.id);\n if (!env) throw new TRPCError({ code: 'NOT_FOUND', message: `Environment ${input.id} not found` });\n\n if (env.immutable) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Cannot delete immutable environment' });\n }\n\n // If deleting a global env, also delete all service-scoped envs that activateOn it\n if (env.scope === 'global') {\n await environmentStore.deleteByActivateOn(input.id);\n }\n\n const deleted = await environmentStore.delete(input.id);\n if (!deleted) throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: 'Failed to delete environment' });\n\n // Remove environment from project\n await projectStore.removeEnvironment(env.projectId, input.id);\n\n return { success: true };\n }),\n\n resolve: protectedProcedure\n .input(z.object({ environmentId: z.string().max(128) }))\n .query(async ({ input, ctx }) => {\n const { includeSecrets } = requireEnvAction(ctx as AuthContext, input.environmentId, 'env:read');\n const env = await environmentStore.get(input.environmentId);\n if (!env) throw new TRPCError({ code: 'NOT_FOUND', message: `Environment ${input.environmentId} not found` });\n\n const resolved = await environmentResolver.resolveEnvironmentWithSources(input.environmentId);\n\n if (!includeSecrets) {\n // Strip secret values — replace with empty string to preserve variable shape\n const sanitized = { ...resolved };\n if (sanitized.variables) {\n sanitized.variables = Object.fromEntries(\n Object.entries(sanitized.variables).map(([id, v]) => [\n id,\n v.value?.isSecret ? { ...v, value: { ...v.value, value: '' } } : v,\n ]),\n );\n }\n return sanitized;\n }\n\n return resolved;\n }),\n\n resolveFlat: protectedProcedure\n .meta({ openapi: { method: 'GET', path: '/environments/{environmentId}/resolve-flat', tags: ['environments'], summary: 'Resolve environment variables as a flat key-value map', protect: true } })\n .input(z.object({ environmentId: z.string().max(128) }))\n .output(z.record(z.string(), z.string()))\n .query(async ({ input, ctx }) => {\n const { includeSecrets } = requireEnvAction(ctx as AuthContext, input.environmentId, 'env:read');\n const env = await environmentStore.get(input.environmentId);\n if (!env) throw new TRPCError({ code: 'NOT_FOUND', message: `Environment ${input.environmentId} not found` });\n\n const { env: resolved, envSecrets } = await environmentResolver.resolveEnvironment(input.environmentId);\n\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(resolved)) {\n if (!includeSecrets && envSecrets.includes(key)) {\n result[key] = '*****';\n } else {\n result[key] = value;\n }\n }\n return result;\n }),\n\n // --- Overrides (flat, by variableId) ---\n\n setOverride: protectedProcedure\n .input(z.object({\n variableId: z.string().max(128),\n // Only the value slot: the env var name comes from the variable\n // definition (a `key` sent by an older client is stripped here).\n variable: VariableOverrideSchema,\n }))\n .mutation(async ({ input }) => {\n await environmentOverridesStore.setOverride(input.variableId, input.variable);\n return { success: true };\n }),\n\n removeOverride: protectedProcedure\n .input(z.object({\n variableId: z.string().max(128),\n }))\n .mutation(async ({ input }) => {\n await environmentOverridesStore.removeOverride(input.variableId);\n return { success: true };\n }),\n\n getOverrides: protectedProcedure\n .query(async () => {\n return await environmentOverridesStore.getAll();\n }),\n\n upsertVariable: protectedProcedure\n .meta({ openapi: { method: 'PUT', path: '/environments/{environmentId}/variables/{variableId}', tags: ['environments'], summary: 'Upsert a variable in an environment', protect: true } })\n .output(z.any())\n .input(z.object({\n environmentId: z.string().max(128),\n variableId: z.string().max(128),\n variable: VariableSchema,\n }))\n .mutation(async ({ input, ctx }) => {\n requireEnvAction(ctx as AuthContext, input.environmentId, 'env:write');\n const env = await environmentStore.get(input.environmentId);\n if (!env) throw new TRPCError({ code: 'NOT_FOUND', message: `Environment ${input.environmentId} not found` });\n const result = await environmentStore.upsertVariable(input.environmentId, input.variableId, input.variable);\n if (!result) throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: 'Failed to update variable' });\n return result;\n }),\n\n /**\n * List everywhere a variable key is used inside a project: environments that\n * define it, and variables that reference it through {{environment.KEY}}.\n * Used by the UI to warn before editing a shared variable from a resolved view.\n */\n keyUsages: protectedProcedure\n .input(z.object({\n projectId: z.string().max(128),\n key: z.string().min(1).max(256),\n /** Environment holding the variable about to be edited — enables inherited-impact detection */\n environmentId: z.string().max(128).optional(),\n }))\n .query(async ({ input }) => {\n const environments = await environmentStore.list(input.projectId);\n const services = await serviceStore.list();\n const serviceName = (id?: string) => services.find(s => s.id === id)?.name;\n\n // Escape the key before embedding it in a regexp — it is user input.\n const escaped = input.key.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n // nosemgrep: detect-non-literal-regexp -- la clé est échappée juste au-dessus ; le motif reste linéaire (pas de quantificateur imbriqué)\n const refPattern = new RegExp(`\\\\{\\\\{environment\\\\.${escaped}\\\\}\\\\}`);\n\n const definedIn: Array<{ environmentId: string; environmentName: string; scope: string; serviceName?: string }> = [];\n const referencedBy: Array<{ environmentId: string; environmentName: string; scope: string; serviceName?: string; key: string }> = [];\n\n for (const env of environments) {\n const name = serviceName(env.reference);\n for (const variable of Object.values(env.variables ?? {})) {\n if (variable.key === input.key) {\n definedIn.push({\n environmentId: env.id,\n environmentName: env.name,\n scope: env.scope ?? 'global',\n ...(name ? { serviceName: name } : {}),\n });\n continue;\n }\n const slot = variable.value;\n if (refPattern.test(`${slot.pre}${slot.value}${slot.post}`)) {\n referencedBy.push({\n environmentId: env.id,\n environmentName: env.name,\n scope: env.scope ?? 'global',\n ...(name ? { serviceName: name } : {}),\n key: variable.key,\n });\n }\n }\n }\n\n // Indirect impact: environments that receive the variable through the\n // inheritance chain. We ask the resolver rather than re-deriving the\n // rules, so explicit parents, implicit service-ancestor inheritance and\n // dedup-by-key shadowing are all accounted for by construction.\n const inheritedBy: Array<{ environmentId: string; environmentName: string; scope: string; serviceName?: string }> = [];\n if (input.environmentId) {\n for (const env of environments) {\n if (env.id === input.environmentId) continue;\n try {\n const resolved = await environmentResolver.resolveEnvironmentWithSources(env.id);\n const inherits = Object.entries(resolved.variables).some(\n ([varId, variable]) =>\n variable.key === input.key\n && resolved.sources[varId]?.environmentId === input.environmentId,\n );\n if (inherits) {\n const name = serviceName(env.reference);\n inheritedBy.push({\n environmentId: env.id,\n environmentName: env.name,\n scope: env.scope ?? 'global',\n ...(name ? { serviceName: name } : {}),\n });\n }\n } catch {\n // Unresolvable environment (e.g. circular chain) — skip it\n }\n }\n }\n\n return { definedIn, referencedBy, inheritedBy };\n }),\n\n removeVariable: protectedProcedure\n .input(z.object({\n environmentId: z.string().max(128),\n variableId: z.string().max(128),\n }))\n .mutation(async ({ input }) => {\n const env = await environmentStore.get(input.environmentId);\n if (!env) throw new TRPCError({ code: 'NOT_FOUND', message: `Environment ${input.environmentId} not found` });\n const result = await environmentStore.removeVariable(input.environmentId, input.variableId);\n if (!result) throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: 'Failed to remove variable' });\n return result;\n }),\n});\n","import { promises as dns } from 'node:dns';\nimport { resolve } from 'node:path';\nimport { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { JSLogParserSchema, NotificationPreferencesSchema, SettingsSchema, type JSLogParserDef, nativeParsers, AIProviderSchema, type AIProvider, JSLogParser } from '@runeya/packages-shared';\nimport { settingsManager } from '../../services/settings-manager.js';\nimport { env } from '../../config/env.js';\nimport { encryptValue, decryptValue, stableEncryptValue } from '../../services/crypto-helpers.js';\nimport { traefikManager } from '../../services/traefik-manager.js';\nimport { agentStore } from '../../services/agent-store.js';\nimport { agentManager } from '../../services/agent-manager.js';\nimport { TraefikConfigSchema } from '@runeya/packages-shared';\n\nconst NotificationPreferencesPatchSchema = NotificationPreferencesSchema.partial().strict();\n\nfunction maskApiKey(plaintext: string): string {\n if (plaintext.length <= 8) return '****';\n return plaintext.slice(0, 4) + '****' + plaintext.slice(-4);\n}\n\nexport const settingsRouter = router({\n /**\n * Get all settings\n */\n get: protectedProcedure.query(async () => {\n const settings = await settingsManager.getSettings();\n return settings;\n }),\n\n /**\n * Paths the server is running from (working directory + data directory).\n * Read-only, purely informational for the settings UI.\n */\n getPaths: protectedProcedure.query(() => ({\n cwd: process.cwd(),\n dataDir: resolve(env.DATA_DIR),\n })),\n\n /**\n * Update settings (mode, cloudUrl)\n */\n update: protectedProcedure\n .input(SettingsSchema.pick({ mode: true, cloudUrl: true, globalDocsPath: true }).partial())\n .mutation(async ({ input }) => {\n const current = await settingsManager.getSettings();\n const updated = {\n ...current,\n ...input,\n };\n await settingsManager.saveSettings(updated);\n return updated;\n }),\n\n /**\n * Get notification preferences\n */\n getNotificationPreferences: protectedProcedure.query(async () => {\n const priv = await settingsManager.getPrivateSettings();\n return NotificationPreferencesSchema.parse(priv.notifications ?? {});\n }),\n\n /**\n * Update notification preferences (granular mute)\n */\n updateNotificationPreferences: protectedProcedure\n .input(NotificationPreferencesPatchSchema)\n .mutation(async ({ input }) => {\n const priv = await settingsManager.getPrivateSettings();\n const currentPrefs = NotificationPreferencesSchema.parse(priv.notifications ?? {});\n const updatedPrefs = {\n ...currentPrefs,\n ...input,\n };\n await settingsManager.savePrivateSettings({\n ...priv,\n notifications: updatedPrefs,\n });\n return updatedPrefs;\n }),\n\n /**\n * List all parsers\n */\n listParsers: protectedProcedure.query(async () => {\n const settings = await settingsManager.getSettings();\n return [...nativeParsers, ...(settings.logParsers || [])];\n }),\n\n /**\n * Get single parser by ID\n */\n getParser: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(async ({ input }) => {\n const settings = await settingsManager.getSettings();\n const parser = (settings.logParsers || []).find((p: JSLogParserDef) => p.id === input.id);\n if (!parser) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Parser not found: ${input.id}` });\n }\n return parser;\n }),\n\n /**\n * Create new parser\n */\n createParser: protectedProcedure\n .input(\n JSLogParserSchema.omit({\n id: true,\n createdAt: true,\n updatedAt: true,\n })\n )\n .mutation(async ({ input }) => {\n // Basic code validation (schema already validated forbiden patterns)\n if (!input.code.trim()) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Parser code cannot be empty' });\n }\n\n const id = `parser-${Date.now()}-${Math.random().toString(36).substring(7)}`;\n const now = new Date();\n const parser = {\n id,\n ...input,\n createdAt: now,\n updatedAt: now,\n };\n\n const settings = await settingsManager.getSettings();\n await settingsManager.saveSettings({\n ...settings,\n logParsers: [...(settings.logParsers || []), parser],\n });\n\n return parser;\n }),\n\n /**\n * Update existing parser\n */\n updateParser: protectedProcedure\n .input(\n JSLogParserSchema.omit({\n createdAt: true,\n updatedAt: true,\n }).partial()\n .required({ id: true })\n )\n .mutation(async ({ input }) => {\n const settings = await settingsManager.getSettings();\n const parserIndex = (settings.logParsers || []).findIndex(\n (p: JSLogParserDef) => p.id === input.id\n );\n\n if (parserIndex === -1) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Parser not found: ${input.id}` });\n }\n\n if (input.id.startsWith('native:')) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Cannot modify built-in parsers' });\n }\n\n const existing = (settings.logParsers || [])[parserIndex];\n\n // If code changed, do basic validation\n if (input.code && !input.code.trim()) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Parser code cannot be empty' });\n }\n\n const updated = {\n ...existing,\n ...input,\n updatedAt: new Date(),\n };\n\n const newParsers = [...(settings.logParsers || [])];\n newParsers[parserIndex] = updated;\n\n await settingsManager.saveSettings({\n ...settings,\n logParsers: newParsers,\n });\n\n return updated;\n }),\n\n /**\n * Delete parser by ID\n */\n deleteParser: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const settings = await settingsManager.getSettings();\n const newParsers = (settings.logParsers || []).filter(\n (p: JSLogParserDef) => p.id !== input.id\n );\n\n if (input.id.startsWith('native:')) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Cannot delete built-in parsers' });\n }\n\n if (newParsers.length === (settings.logParsers || []).length) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Parser not found: ${input.id}` });\n }\n\n await settingsManager.saveSettings({\n ...settings,\n logParsers: newParsers,\n });\n\n return { deleted: true };\n }),\n\n // ---------------------------------------------------------------------------\n // AI Providers\n // ---------------------------------------------------------------------------\n\n /**\n * List AI providers (API keys are masked)\n */\n listAIProviders: protectedProcedure.query(async () => {\n const priv = await settingsManager.getPrivateSettings();\n return (priv.aiProviders ?? []).map((p: AIProvider) => {\n let maskedKey = '(aucune)';\n if (p.encryptedApiKey) {\n try {\n maskedKey = maskApiKey(decryptValue(p.encryptedApiKey));\n } catch { maskedKey = '(clé invalide)'; }\n }\n return { id: p.id, name: p.name, provider: p.provider, model: p.model, active: p.active, maskedKey, createdAt: p.createdAt, updatedAt: p.updatedAt };\n });\n }),\n\n /**\n * Create AI provider\n */\n createAIProvider: protectedProcedure\n .input(z.object({\n name: z.string().min(1).max(200),\n provider: AIProviderSchema.shape.provider,\n apiKey: z.string().max(500).optional(), // optional for providers like Ollama\n model: z.string().max(200).optional(),\n }))\n .mutation(async ({ input }) => {\n if (input.provider !== 'ollama' && !input.apiKey?.trim()) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Une clé API est requise pour ce provider.' });\n }\n const priv = await settingsManager.getPrivateSettings();\n const id = `aiprovider-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n const now = new Date();\n const plainKey = input.apiKey ?? '';\n const newProvider: AIProvider = {\n id,\n name: input.name,\n provider: input.provider,\n encryptedApiKey: plainKey ? encryptValue(plainKey) : '',\n model: input.model,\n active: (priv.aiProviders ?? []).length === 0, // first one is active by default\n createdAt: now,\n updatedAt: now,\n };\n await settingsManager.savePrivateSettings({\n ...priv,\n aiProviders: [...(priv.aiProviders ?? []), newProvider],\n });\n return { ...newProvider, maskedKey: plainKey ? maskApiKey(plainKey) : '(aucune)', encryptedApiKey: undefined };\n }),\n\n /**\n * Update AI provider (apiKey optional — omit to keep existing)\n */\n updateAIProvider: protectedProcedure\n .input(z.object({\n id: z.string().min(1).max(128),\n name: z.string().min(1).max(200).optional(),\n provider: AIProviderSchema.shape.provider.optional(),\n apiKey: z.string().min(1).max(500).optional(),\n model: z.string().max(200).optional(),\n }))\n .mutation(async ({ input }) => {\n const priv = await settingsManager.getPrivateSettings();\n const providers = priv.aiProviders ?? [];\n const idx = providers.findIndex((p: AIProvider) => p.id === input.id);\n if (idx === -1) throw new TRPCError({ code: 'NOT_FOUND', message: `AI provider not found: ${input.id}` });\n const existing = providers[idx];\n const encryptedApiKey = input.apiKey\n ? stableEncryptValue(input.apiKey, existing.encryptedApiKey)\n : existing.encryptedApiKey;\n const updated: AIProvider = {\n ...existing,\n ...(input.name ? { name: input.name } : {}),\n ...(input.provider ? { provider: input.provider } : {}),\n ...(input.model !== undefined ? { model: input.model || undefined } : {}),\n encryptedApiKey,\n updatedAt: new Date(),\n };\n const newProviders = [...providers];\n newProviders[idx] = updated;\n await settingsManager.savePrivateSettings({ ...priv, aiProviders: newProviders });\n let maskedKey = '(aucune)';\n if (updated.encryptedApiKey) {\n try { maskedKey = maskApiKey(decryptValue(updated.encryptedApiKey)); } catch { /* */ }\n }\n return { ...updated, maskedKey, encryptedApiKey: undefined };\n }),\n\n /**\n * Delete AI provider\n */\n deleteAIProvider: protectedProcedure\n .input(z.object({ id: z.string().min(1).max(128) }))\n .mutation(async ({ input }) => {\n const priv = await settingsManager.getPrivateSettings();\n const providers = priv.aiProviders ?? [];\n const filtered = providers.filter((p: AIProvider) => p.id !== input.id);\n if (filtered.length === providers.length) throw new TRPCError({ code: 'NOT_FOUND', message: `AI provider not found: ${input.id}` });\n // If deleted was active, promote first remaining to active\n const deletedWasActive = providers.find((p: AIProvider) => p.id === input.id)?.active ?? false;\n if (deletedWasActive && filtered.length > 0) filtered[0].active = true;\n await settingsManager.savePrivateSettings({ ...priv, aiProviders: filtered });\n return { deleted: true };\n }),\n\n /**\n * Set one provider as active (clears active flag on all others)\n */\n setActiveAIProvider: protectedProcedure\n .input(z.object({ id: z.string().min(1).max(128) }))\n .mutation(async ({ input }) => {\n const priv = await settingsManager.getPrivateSettings();\n const providers = priv.aiProviders ?? [];\n const idx = providers.findIndex((p: AIProvider) => p.id === input.id);\n if (idx === -1) throw new TRPCError({ code: 'NOT_FOUND', message: `AI provider not found: ${input.id}` });\n const updated = providers.map((p: AIProvider) => ({ ...p, active: p.id === input.id }));\n await settingsManager.savePrivateSettings({ ...priv, aiProviders: updated });\n return { id: input.id, active: true };\n }),\n\n // ---------------------------------------------------------------------------\n // Traefik config\n // ---------------------------------------------------------------------------\n\n /**\n * Get Traefik config for a specific agent (never returns credentials or cert key in plain text)\n */\n getAgentTraefikConfig: protectedProcedure\n .input(z.object({ agentId: z.string().max(128) }))\n .query(async ({ input }) => {\n const raw = agentStore.getTraefikConfig(input.agentId);\n const parsed = raw ? TraefikConfigSchema.safeParse(raw) : null;\n const config = parsed?.success ? parsed.data : null;\n return {\n enabled: config?.enabled ?? false,\n acmeEmail: config?.acmeEmail,\n wildcardDomain: config?.wildcardDomain,\n httpPort: config?.httpPort ?? 80,\n httpsPort: config?.httpsPort ?? 443,\n dnsProvider: config?.dnsProvider,\n hasDnsCredentials: Object.keys(config?.dnsCredentials ?? {}).length > 0,\n dnsCredentialKeys: Object.keys(config?.dnsCredentials ?? {}),\n hasCert: !!config?.encryptedCert,\n acmeStaging: config?.acmeStaging ?? false,\n };\n }),\n\n /**\n * Update Traefik config for a specific agent (credentials are encrypted before saving)\n */\n updateAgentTraefikConfig: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n enabled: z.boolean().optional(),\n acmeEmail: z.string().email().max(256).optional(),\n wildcardDomain: z.string().max(253).optional(),\n httpPort: z.number().int().min(1).max(65535).optional(),\n httpsPort: z.number().int().min(1).max(65535).optional(),\n dnsProvider: z.string().max(64).optional(),\n dnsCredentials: z.record(z.string().max(64), z.string().max(2048)).optional(),\n acmeStaging: z.boolean().optional(),\n }))\n .mutation(async ({ input }) => {\n const { agentId, ...fields } = input;\n const raw = agentStore.getTraefikConfig(agentId);\n const parsed = raw ? TraefikConfigSchema.safeParse(raw) : null;\n const existing = parsed?.success ? parsed.data : { enabled: false, dnsCredentials: {}, httpPort: 80, httpsPort: 443 };\n\n const encryptedCredentials = fields.dnsCredentials\n ? traefikManager.encryptDnsCredentials(fields.dnsCredentials)\n : existing.dnsCredentials;\n\n const updated = {\n ...existing,\n ...(fields.enabled !== undefined && { enabled: fields.enabled }),\n ...(fields.acmeEmail !== undefined && { acmeEmail: fields.acmeEmail }),\n ...(fields.wildcardDomain !== undefined && { wildcardDomain: fields.wildcardDomain }),\n ...(fields.httpPort !== undefined && { httpPort: fields.httpPort }),\n ...(fields.httpsPort !== undefined && { httpsPort: fields.httpsPort }),\n ...(fields.dnsProvider !== undefined && { dnsProvider: fields.dnsProvider }),\n ...(fields.acmeStaging !== undefined && { acmeStaging: fields.acmeStaging }),\n dnsCredentials: encryptedCredentials,\n };\n\n await agentStore.saveTraefikConfig(agentId, updated);\n\n // Déchiffrer les credentials avant push à l'agent\n const configToPush = {\n ...updated,\n dnsCredentials: traefikManager.decryptDnsCredentials(updated.dnsCredentials ?? {}),\n };\n // Push to connected agent\n await agentManager.pushTraefikConfig(agentId, configToPush);\n\n return { success: true };\n }),\n\n /**\n * Get Traefik config files content for a specific agent\n */\n getAgentTraefikConfigFiles: protectedProcedure\n .input(z.object({ agentId: z.string().max(128) }))\n .query(async ({ input }) => {\n return agentManager.agentQuery<{ static: string; dynamic: string }>(\n input.agentId,\n 'config.getTraefikConfigFiles',\n );\n }),\n\n getAgentTraefikFileTree: protectedProcedure\n .input(z.object({ agentId: z.string().max(128) }))\n .query(async ({ input }) => {\n return agentManager.agentQuery<Array<{ path: string; content: string }>>(\n input.agentId,\n 'config.getTraefikFileTree',\n );\n }),\n\n /**\n * Get Traefik container logs for a specific agent (snapshot)\n */\n getAgentTraefikLogs: protectedProcedure\n .input(z.object({ agentId: z.string().max(128), lines: z.number().int().min(1).max(500).default(100) }))\n .query(async ({ input }) => {\n const result = await agentManager.agentQuery<{ logs: string }>(\n input.agentId,\n 'config.getTraefikLogs',\n { lines: input.lines },\n );\n return result;\n }),\n\n /**\n * Stream Traefik logs in real-time (subscription, yields new lines every 500ms)\n */\n streamAgentTraefikLogs: protectedProcedure\n .input(z.object({ agentId: z.string().max(128) }))\n .subscription(async function* ({ input, signal }) {\n let seen = 0;\n while (!signal?.aborted) {\n try {\n const result = await agentManager.agentQuery<{ logs: string }>(\n input.agentId,\n 'config.getTraefikLogs',\n { lines: 500 },\n );\n const lines = result.logs?.trim() ? result.logs.split('\\n') : [];\n if (lines.length > seen) {\n const newLines = lines.slice(seen);\n seen = lines.length;\n yield { lines: newLines };\n }\n } catch {\n // agent not reachable yet — wait and retry\n }\n await new Promise(resolve => setTimeout(resolve, 500));\n }\n }),\n\n /**\n * Restart Traefik container on a specific agent (re-pushes config first to handle agent restarts)\n */\n restartAgentTraefik: protectedProcedure\n .input(z.object({ agentId: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const raw = agentStore.getTraefikConfig(input.agentId);\n const parsed = raw ? TraefikConfigSchema.safeParse(raw) : null;\n const config = parsed?.success ? parsed.data : null;\n if (!config?.enabled) throw new TRPCError({ code: 'BAD_REQUEST', message: 'Traefik non activé sur cet agent' });\n const decrypted = { ...config, dnsCredentials: traefikManager.decryptDnsCredentials(config.dnsCredentials ?? {}) };\n await agentManager.agentMutation(input.agentId, 'config.initTraefikConfig', decrypted, 5000);\n await agentManager.agentMutation(input.agentId, 'config.restartTraefik', undefined, 30000);\n return { success: true };\n }),\n\n /**\n * Force certificate renewal for a specific agent (wipes acme.json + restarts container)\n */\n renewAgentTraefikCert: protectedProcedure\n .input(z.object({ agentId: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const raw = agentStore.getTraefikConfig(input.agentId);\n const parsed = raw ? TraefikConfigSchema.safeParse(raw) : null;\n const config = parsed?.success ? parsed.data : null;\n if (!config?.enabled) throw new TRPCError({ code: 'BAD_REQUEST', message: 'Traefik non activé sur cet agent' });\n const decrypted = { ...config, dnsCredentials: traefikManager.decryptDnsCredentials(config.dnsCredentials ?? {}) };\n await agentManager.agentMutation(input.agentId, 'config.initTraefikConfig', decrypted, 5000);\n await agentManager.agentMutation(input.agentId, 'config.renewTraefikCert', undefined, 30000);\n return { success: true };\n }),\n\n /**\n * Validate Traefik configuration for a specific agent\n */\n validateAgentTraefikConfig: protectedProcedure\n .input(z.object({ agentId: z.string().max(128) }))\n .query(async ({ input }) => {\n const raw = agentStore.getTraefikConfig(input.agentId);\n const parsed = raw ? TraefikConfigSchema.safeParse(raw) : null;\n const config = parsed?.success ? parsed.data : null;\n\n const checks: Array<{ id: string; ok: boolean; message: string }> = [];\n\n // Config completeness checks (server-side)\n checks.push({\n id: 'enabled',\n ok: config?.enabled === true,\n message: config?.enabled ? 'Traefik activé' : 'Traefik non activé',\n });\n checks.push({\n id: 'domain',\n ok: !!config?.wildcardDomain?.trim(),\n message: config?.wildcardDomain ? `Domaine : ${config.wildcardDomain}` : 'Domaine wildcard non configuré',\n });\n checks.push({\n id: 'email',\n ok: !!config?.acmeEmail?.trim(),\n message: config?.acmeEmail ? `Email ACME : ${config.acmeEmail}` : 'Email ACME non configuré',\n });\n checks.push({\n id: 'dns_provider',\n ok: !!config?.dnsProvider?.trim(),\n message: config?.dnsProvider ? `Provider DNS : ${config.dnsProvider}` : 'Provider DNS non configuré',\n });\n checks.push({\n id: 'credentials',\n ok: Object.keys(config?.dnsCredentials ?? {}).length > 0,\n message: Object.keys(config?.dnsCredentials ?? {}).length > 0\n ? `${Object.keys(config!.dnsCredentials!).length} variable(s) configurée(s)`\n : 'Variables d\\'environnement DNS manquantes',\n });\n\n // DNS resolution check — only proceed if domain contains valid hostname characters.\n if (config?.wildcardDomain?.trim()) {\n const sanitisedDomain = config.wildcardDomain.replace(/^\\*\\./, '').replace(/[^a-z0-9.-]/gi, '');\n const probe = `probe.${sanitisedDomain}`;\n try {\n const addresses = await dns.resolve4(probe);\n const pointsToLocalhost = addresses.some(a => a === '127.0.0.1');\n checks.push({\n id: 'dns_resolution',\n ok: pointsToLocalhost,\n message: pointsToLocalhost\n ? `${probe} → 127.0.0.1 ✓`\n : `${probe} résout vers ${addresses.join(', ')} (attendu : 127.0.0.1)`,\n });\n } catch {\n checks.push({\n id: 'dns_resolution',\n ok: false,\n message: `${probe} ne résout pas — vérifiez le DNS wildcard`,\n });\n }\n }\n\n // Agent-side checks (Docker, container status)\n let agentChecks: Array<{ id: string; ok: boolean; message: string }> = [];\n try {\n const status = await agentManager.agentQuery<{\n containerRunning: boolean;\n dockerAvailable: boolean;\n configFileExists: boolean;\n cert: { hasCert: boolean; domain: string | null; expiresAt: string | null; daysLeft: number | null; expired: boolean };\n }>(input.agentId, 'config.getTraefikStatus');\n agentChecks.push({\n id: 'docker',\n ok: status.dockerAvailable,\n message: status.dockerAvailable ? 'Docker disponible' : 'Docker non trouvé dans PATH',\n });\n agentChecks.push({\n id: 'container',\n ok: status.containerRunning,\n message: status.containerRunning ? 'Container Traefik en cours d\\'exécution' : 'Container Traefik arrêté',\n });\n agentChecks.push({\n id: 'config_file',\n ok: status.configFileExists,\n message: status.configFileExists ? 'Fichier de configuration présent' : 'Fichier traefik.yml absent (enregistrez la config)',\n });\n const c = status.cert;\n if (c.hasCert && !c.expired) {\n agentChecks.push({\n id: 'ssl_cert',\n ok: true,\n message: `Certificat SSL valide pour ${c.domain} — expire dans ${c.daysLeft} jour(s) (${c.expiresAt})`,\n });\n } else if (c.hasCert && c.expired) {\n agentChecks.push({\n id: 'ssl_cert',\n ok: false,\n message: `Certificat SSL expiré pour ${c.domain} (depuis ${c.expiresAt})`,\n });\n } else {\n agentChecks.push({\n id: 'ssl_cert',\n ok: false,\n message: c.domain\n ? `Aucun certificat SSL pour ${c.domain} — Traefik doit être actif pour déclencher le challenge DNS-01`\n : 'Aucun certificat SSL trouvé dans acme.json',\n });\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n const isNotFound = msg.includes('not found') || msg.includes('not connected');\n agentChecks.push({\n id: 'agent_reachable',\n ok: false,\n message: isNotFound\n ? `Agent non connecté au serveur (id: ${input.agentId})`\n : `Agent non joignable — ${msg}`,\n });\n }\n\n return { checks: [...checks, ...agentChecks] };\n }),\n\n /**\n * Test parser code: compile and run it against sample logs, return per-line results\n */\n testParser: protectedProcedure\n .input(\n z.object({\n code: z.string().max(50000),\n sampleLogs: z\n .array(\n z.object({\n raw: z.string().max(16384),\n stream: z.enum(['stdout', 'stderr']),\n })\n )\n .max(100)\n .default([]),\n })\n )\n .mutation(async ({ input }) => {\n // Compile via shared JSLogParser (same implementation as the agent)\n let jsParser: JSLogParser;\n try {\n jsParser = new JSLogParser([{\n id: 'preview',\n name: 'preview',\n code: input.code,\n enabled: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n }]);\n } catch (err) {\n throw new TRPCError({\n code: 'BAD_REQUEST',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n\n let idCounter = 0;\n const results = input.sampleLogs.map((log) => {\n const inputLine = {\n raw: log.raw,\n stream: log.stream as 'stdout' | 'stderr',\n level: 'info' as const,\n message: log.raw,\n hidden: false,\n metadata: {} as Record<string, unknown>,\n };\n\n try {\n const output = jsParser.parse({ ...inputLine });\n const logCard = output.json\n ? { id: `sim-${++idCounter}`, type: 'json', header: output.jsonHeader ?? 'JSON', state: 'self' as const, collapsable: true }\n : undefined;\n return { input: inputLine, output: { ...output, logCard }, error: null };\n } catch (err) {\n return { input: inputLine, output: null, error: err instanceof Error ? err.message : String(err) };\n }\n });\n\n return { validated: true, results };\n }),\n});\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { execFile, spawn } from 'node:child_process';\nimport { stat } from 'node:fs/promises';\nimport { resolve, join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { SUPPORTED_EDITORS, EDITOR_BY_KEY } from '@runeya/packages-shared';\nimport { userConfigManager } from '../../services/user-config-manager.js';\nimport { serviceStore } from '../../services/service-store.js';\n\nfunction resolveCwd(cwd: string): string {\n const withHome = cwd.replace(/^~(\\/|$)/, `${homedir()}$1`);\n return withHome.replace(/\\$\\{(\\w+)\\}|\\$(\\w+)/g, (match, braced, plain) => {\n const name = braced ?? plain;\n return process.env[name] ?? match;\n });\n}\n\nasync function getServiceCwd(serviceId: string): Promise<string> {\n const services = await serviceStore.list();\n const service = services.find((s) => s.id === serviceId);\n if (!service) {\n throw new TRPCError({ code: 'NOT_FOUND', message: 'Service not found' });\n }\n const rawCwd = service.cwd?.trim() || '.';\n return resolveCwd(rawCwd);\n}\n\nasync function isCommandAvailable(command: string): Promise<boolean> {\n return new Promise((resolve) => {\n execFile('which', [command], { timeout: 5_000 }, (err) => {\n resolve(!err);\n });\n });\n}\n\nexport const editorRouter = router({\n listAvailable: protectedProcedure.query(async () => {\n const results = await Promise.all(\n SUPPORTED_EDITORS.map(async (editor) => ({\n ...editor,\n installed: await isCommandAvailable(editor.command),\n })),\n );\n return results;\n }),\n\n getPreferences: protectedProcedure\n .input(z.object({ projectId: z.string().max(128) }))\n .query(async ({ input }) => {\n return userConfigManager.getEditorPreferences(input.projectId);\n }),\n\n setDefault: protectedProcedure\n .input(z.object({\n projectId: z.string().max(128),\n editorKey: z.string().max(64),\n }))\n .mutation(async ({ input }) => {\n if (!EDITOR_BY_KEY.has(input.editorKey)) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: `Unknown editor: ${input.editorKey}` });\n }\n await userConfigManager.setEditorPreference(input.projectId, 'default', input.editorKey);\n return { success: true };\n }),\n\n setServiceEditor: protectedProcedure\n .input(z.object({\n projectId: z.string().max(128),\n serviceId: z.string().max(128),\n editorKey: z.string().max(64),\n }))\n .mutation(async ({ input }) => {\n if (!EDITOR_BY_KEY.has(input.editorKey)) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: `Unknown editor: ${input.editorKey}` });\n }\n await userConfigManager.setEditorPreference(input.projectId, input.serviceId, input.editorKey);\n return { success: true };\n }),\n\n removeServiceEditor: protectedProcedure\n .input(z.object({\n projectId: z.string().max(128),\n serviceId: z.string().max(128),\n }))\n .mutation(async ({ input }) => {\n await userConfigManager.removeEditorPreference(input.projectId, input.serviceId);\n return { success: true };\n }),\n\n open: protectedProcedure\n .input(z.object({\n editorKey: z.string().max(64),\n path: z.string().max(4096),\n }))\n .mutation(async ({ input }) => {\n const editor = EDITOR_BY_KEY.get(input.editorKey);\n if (!editor) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: `Unknown editor: ${input.editorKey}` });\n }\n\n // Expand ~ and $VAR/${VAR} from process.env, then resolve relative paths\n const expanded = input.path\n .replace(/^~(\\/|$)/, `${process.env['HOME'] ?? '/tmp'}$1`)\n .replace(/\\$\\{(\\w+)\\}|\\$(\\w+)/g, (_, a, b) => process.env[a || b] ?? '');\n const resolvedPath = resolve(expanded || '.');\n\n // Validate path exists (directory or file)\n try {\n await stat(resolvedPath);\n } catch (err) {\n if (err instanceof TRPCError) throw err;\n throw new TRPCError({ code: 'BAD_REQUEST', message: `Path does not exist: ${resolvedPath}` });\n }\n\n const child = spawn(editor.command, [resolvedPath], {\n shell: false,\n detached: true,\n stdio: 'ignore',\n windowsHide: true,\n });\n child.unref();\n\n return { success: true };\n }),\n\n openFile: protectedProcedure\n .input(z.object({\n editorKey: z.string().max(64),\n serviceId: z.string().max(128),\n relativePath: z.string().max(4096),\n }))\n .mutation(async ({ input }) => {\n const editor = EDITOR_BY_KEY.get(input.editorKey);\n if (!editor) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: `Unknown editor: ${input.editorKey}` });\n }\n\n const cwd = await getServiceCwd(input.serviceId);\n const filePath = join(cwd, input.relativePath);\n\n // Prevent path traversal\n if (!filePath.startsWith(cwd)) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Path traversal not allowed' });\n }\n\n try {\n await stat(filePath);\n } catch {\n throw new TRPCError({ code: 'BAD_REQUEST', message: `File does not exist: ${filePath}` });\n }\n\n const child = spawn(editor.command, [filePath], {\n shell: false,\n detached: true,\n stdio: 'ignore',\n windowsHide: true,\n });\n child.unref();\n\n return { success: true };\n }),\n});\n","import { readFile, writeFile, rename, mkdir, chmod } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { z } from 'zod';\n\nconst CONFIG_DIR = join(homedir(), '.runeya');\nconst CONFIG_FILE = 'runeya.conf';\n\nconst EditorPreferencesSchema = z.object({\n default: z.string().max(64).optional(),\n}).catchall(z.string().max(64))\n .refine((obj) => Object.keys(obj).length <= 500, 'Too many editor preferences');\n\nconst ProjectSettingsSchema = z.object({\n settings: z.object({\n editors: EditorPreferencesSchema.optional(),\n }).optional(),\n});\n\nconst UserConfigSchema = z.record(\n z.string().max(128),\n ProjectSettingsSchema,\n).refine((obj) => Object.keys(obj).length <= 100, 'Too many projects in config');\n\ntype UserConfig = z.infer<typeof UserConfigSchema>;\n\nclass UserConfigManager {\n private config: UserConfig | null = null;\n\n private async ensureDir(): Promise<void> {\n await mkdir(CONFIG_DIR, { recursive: true });\n }\n\n private async atomicWrite(data: unknown): Promise<void> {\n await this.ensureDir();\n const filePath = join(CONFIG_DIR, CONFIG_FILE);\n const tmpPath = filePath + '.tmp';\n await writeFile(tmpPath, JSON.stringify(data, null, 2), 'utf-8');\n await rename(tmpPath, filePath);\n await chmod(filePath, 0o600);\n }\n\n async getConfig(): Promise<UserConfig> {\n if (!this.config) {\n try {\n const raw = await readFile(join(CONFIG_DIR, CONFIG_FILE), 'utf-8');\n const parsed = UserConfigSchema.safeParse(JSON.parse(raw));\n this.config = parsed.success ? parsed.data : {};\n } catch {\n this.config = {};\n }\n }\n return this.config;\n }\n\n async saveConfig(config: UserConfig): Promise<void> {\n this.config = config;\n await this.atomicWrite(config);\n }\n\n async getEditorPreferences(projectId: string): Promise<Record<string, string>> {\n const config = await this.getConfig();\n return config[projectId]?.settings?.editors ?? {};\n }\n\n async setEditorPreference(projectId: string, target: string, editorKey: string): Promise<void> {\n const config = await this.getConfig();\n if (!config[projectId]) config[projectId] = {};\n if (!config[projectId].settings) config[projectId].settings = {};\n if (!config[projectId].settings!.editors) config[projectId].settings!.editors = {};\n config[projectId].settings!.editors![target] = editorKey;\n await this.saveConfig(config);\n }\n\n async removeEditorPreference(projectId: string, target: string): Promise<void> {\n const config = await this.getConfig();\n const editors = config[projectId]?.settings?.editors;\n if (editors && target in editors) {\n delete editors[target];\n await this.saveConfig(config);\n }\n }\n}\n\nexport const userConfigManager = new UserConfigManager();\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { join, dirname } from 'node:path';\nimport { protectedProcedure, router } from '../trpc.js';\nimport { apiKeyStore, maskApiKey } from '../../services/api-key-store.js';\nimport { ApiKeyScopeSchema } from '@runeya/packages-shared';\n\nconst ALLOWED_SKILL_PATHS = new Set([\n '.claude/skills/runeya/SKILL.md',\n '.cursor/rules/runeya.mdc',\n '.windsurf/rules/runeya.md',\n]);\n\nconst KeyInputSchema = z.object({\n name: z.string().min(1).max(200),\n scopes: ApiKeyScopeSchema,\n isPublic: z.boolean().default(false),\n});\n\nexport const apiKeysRouter = router({\n list: protectedProcedure\n .query(() => apiKeyStore.list()),\n\n create: protectedProcedure\n .input(KeyInputSchema)\n .mutation(({ input }) =>\n apiKeyStore.create(input.name, input.scopes, input.isPublic),\n ),\n\n /**\n * Renvoie le secret d'une seule clé, sur demande explicite. `list` ne le\n * contient pas : une clé ne doit jamais être re-servie en masse.\n */\n reveal: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(async ({ input }) => {\n const key = await apiKeyStore.reveal(input.id);\n if (!key) throw new TRPCError({ code: 'NOT_FOUND', message: 'API key not found' });\n return { key };\n }),\n\n update: protectedProcedure\n .input(KeyInputSchema.extend({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const updated = await apiKeyStore.update(input.id, input.name, input.scopes, input.isPublic);\n if (!updated) throw new TRPCError({ code: 'NOT_FOUND', message: 'API key not found' });\n // Un renommage n'est pas une raison de re-révéler le secret.\n return maskApiKey(updated);\n }),\n\n remove: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const removed = await apiKeyStore.remove(input.id);\n if (!removed) throw new TRPCError({ code: 'NOT_FOUND', message: 'API key not found' });\n return { success: true };\n }),\n\n renewKey: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const renewed = await apiKeyStore.renewKey(input.id);\n if (!renewed) throw new TRPCError({ code: 'NOT_FOUND', message: 'API key not found' });\n return renewed;\n }),\n\n writeSkillFile: protectedProcedure\n .input(z.object({\n relativePath: z.string().max(256),\n content: z.string().max(32768),\n }))\n .mutation(async ({ input }) => {\n if (!ALLOWED_SKILL_PATHS.has(input.relativePath)) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Chemin non autorisé' });\n }\n const abs = join(process.cwd(), input.relativePath);\n await mkdir(dirname(abs), { recursive: true });\n await writeFile(abs, input.content, { encoding: 'utf-8', mode: 0o644 });\n return { path: input.relativePath };\n }),\n});\n","import { z } from 'zod';\nimport Anthropic from '@anthropic-ai/sdk';\nimport OpenAI from 'openai';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { fileURLToPath } from 'node:url';\nimport { buildApiDocs } from '../../services/ai-runners/runeya-api-docs.js';\nimport {\n claudeSessionExists,\n readClaudeTranscript,\n syncConversationFromClaudeTranscript,\n getLastTranscriptActivity,\n} from '../../services/claude-transcript-sync.js';\nimport { codexSessionExists } from '../../services/codex-sessions.js';\n\nimport { TRPCError } from '@trpc/server';\nimport { router, protectedProcedure } from '../trpc.js';\nimport type { AuthContext } from '../trpc.js';\nimport {\n ConversationIdSchema,\n Id128Schema,\n ShortString200Schema,\n} from '../shared-schemas.js';\nimport { serviceStore } from '../../services/service-store.js';\nimport { environmentResolver } from '../../services/environment-resolver.js';\nimport { generateLlmsTxt, generateAdminLlmsTxt } from '../../services/llms-txt-generator.js';\nimport { CHAT_TOOLS, CHAT_TOOLS_OPENAI, TOOL_SAFETY_INSTRUCTION, executeTool } from '../../services/chat-tools.js';\nimport { env } from '../../config/env.js';\nimport { resolveServiceVariables } from './service.js';\nimport { conversationStore } from '../../services/conversation-store.js';\nimport type { ConversationChangeEvent, MessagePart } from '../../services/conversation-store.js';\nimport type { ApiKey } from '@runeya/packages-shared';\nimport { getClaudeUsageEntries } from '../../services/claude-usage.js';\nimport { getCodexUsageEntries } from '../../services/codex-usage.js';\nimport { activeSessionRegistry } from '../../services/active-session-registry.js';\nimport type { ActiveSession, QueueItem } from '../../services/active-session-registry.js';\nimport { scenarioStore } from '../../services/scenario-store.js';\nimport { scenarioRunStore } from '../../services/scenario-run-store.js';\nimport {\n DEFAULT_MODELS,\n OPENAI_COMPAT_BASE_URLS,\n fetchProviderModels,\n getActiveProvider,\n} from '../../services/ai-provider-utils.js';\nimport { resolveImagesToBase64 } from '../../services/message-images.js';\nimport { imageStorageService } from '../../services/image-storage.service.js';\nimport { generateKanbanSystemPrompt, generateKanbanPopulatePrompt } from '../../services/kanban-commands.js';\nimport { kanbanStore } from '../../services/kanban-store.js';\nimport { ClaudeCodeRunner } from '../../services/ai-runners/claude-code-runner.js';\nimport { CodexRunner } from '../../services/ai-runners/codex-runner.js';\nimport { agentManager } from '../../services/agent-manager.js';\n\nconst execFileAsync = promisify(execFile);\n\nconst MessageSchema = z.object({\n role: z.enum(['user', 'assistant']),\n content: z.string().max(100_000),\n});\n\nconst ImagePartSchema = z.object({\n type: z.literal('image'),\n imageId: z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),\n url: z.string().max(500),\n mimeType: z.string().max(100),\n altText: z.string().max(500).optional(),\n});\nconst ImagePartsSchema = z.array(ImagePartSchema).max(5).optional();\n\nconst LANGUAGE_INSTRUCTION = 'Always respond in the same language the user writes in.';\n\n\nasync function buildSystemPrompt(apiKey: ApiKey | null): Promise<string> {\n const allServices = await serviceStore.list();\n const resolvedServices = await Promise.all(allServices.map(resolveServiceVariables));\n const context = apiKey\n ? generateLlmsTxt(apiKey, resolvedServices.filter(s => apiKey.scopes.services.some(p => p.serviceId === s.id)))\n : generateAdminLlmsTxt(resolvedServices);\n const runeya_ai_vars = Object.entries(process.env)\n .filter(([k]) => k.startsWith('RUNEYA_AI_'))\n .map(([k, v]) => `${k}=${v}`)\n .join('\\n');\n const envSection = runeya_ai_vars ? `\\n\\n## Environment\\n\\n${runeya_ai_vars}` : '';\n return `${LANGUAGE_INSTRUCTION}\\n\\n${context}${envSection}`;\n}\n\n// ─── Event types yielded by the subscription ─────────────────────────────────\n\ntype ChatEvent =\n | { type: 'delta'; text: string }\n | { type: 'tool_call'; id: string; name: string; input: Record<string, unknown> }\n | { type: 'tool_result'; id: string; name: string; result: unknown; isError: boolean }\n | { type: 'done'; text: '' };\n\n// ─── Anthropic tool-use loop ──────────────────────────────────────────────────\n\nasync function* runAnthropic(\n client: Anthropic,\n model: string,\n system: string,\n initialMessages: Anthropic.MessageParam[],\n apiKey: ApiKey | null,\n authToken: string,\n signal?: AbortSignal,\n): AsyncGenerator<ChatEvent> {\n const messages: Anthropic.MessageParam[] = [...initialMessages];\n const MAX_TOOL_ROUNDS = 10;\n\n for (let round = 0; round < MAX_TOOL_ROUNDS; round++) {\n // Buffer tool_use blocks; stream text deltas live\n const toolUseBlocks: Anthropic.ToolUseBlock[] = [];\n // Accumulate partial JSON for each tool use block (keyed by block index)\n const partialJson = new Map<number, string>();\n let assistantText = '';\n\n if (signal?.aborted) return;\n const stream = client.messages.stream({\n model,\n max_tokens: 16384,\n system,\n tools: CHAT_TOOLS as Anthropic.Tool[],\n messages,\n }, { signal });\n\n for await (const event of stream) {\n if (event.type === 'content_block_start' && event.content_block.type === 'tool_use') {\n toolUseBlocks.push({ ...event.content_block, input: {} } as Anthropic.ToolUseBlock);\n } else if (event.type === 'content_block_delta') {\n if (event.delta.type === 'text_delta') {\n assistantText += event.delta.text;\n yield { type: 'delta', text: event.delta.text };\n } else if (event.delta.type === 'input_json_delta') {\n const idx = toolUseBlocks.length - 1;\n if (idx >= 0) {\n partialJson.set(idx, (partialJson.get(idx) ?? '') + event.delta.partial_json);\n }\n }\n } else if (event.type === 'content_block_stop') {\n const idx = toolUseBlocks.length - 1;\n const last = toolUseBlocks[idx];\n const partial = partialJson.get(idx);\n if (last && partial !== undefined) {\n try { last.input = JSON.parse(partial); } catch { last.input = {}; }\n partialJson.delete(idx);\n }\n }\n }\n\n const finalMsg = await stream.finalMessage();\n\n // No tool calls → done\n if (finalMsg.stop_reason !== 'tool_use' || toolUseBlocks.length === 0) {\n yield { type: 'done', text: '' };\n return;\n }\n\n // Build assistant message with all content blocks\n const assistantContent: Anthropic.MessageParam['content'] = [];\n if (assistantText) assistantContent.push({ type: 'text', text: assistantText } as Anthropic.TextBlockParam);\n assistantContent.push(...toolUseBlocks);\n messages.push({ role: 'assistant', content: assistantContent });\n\n // Execute each tool and collect results\n const toolResults: Anthropic.ToolResultBlockParam[] = [];\n for (const block of toolUseBlocks) {\n yield { type: 'tool_call', id: block.id, name: block.name, input: block.input as Record<string, unknown> };\n let result: unknown;\n let isError = false;\n try {\n result = await executeTool(block.name, block.input as Record<string, unknown>, apiKey, authToken);\n } catch (err) {\n result = (err as Error).message;\n isError = true;\n }\n yield { type: 'tool_result', id: block.id, name: block.name, result, isError };\n toolResults.push({\n type: 'tool_result',\n tool_use_id: block.id,\n content: typeof result === 'string' ? result : JSON.stringify(result, null, 2),\n is_error: isError,\n });\n }\n\n messages.push({ role: 'user', content: toolResults });\n // Loop: send tool results back to AI\n }\n yield { type: 'done', text: '' };\n}\n\n// ─── OpenAI tool-use loop ─────────────────────────────────────────────────────\n\nasync function* runOpenAI(\n client: OpenAI,\n model: string,\n initialMessages: OpenAI.Chat.ChatCompletionMessageParam[],\n apiKey: ApiKey | null,\n authToken: string,\n signal?: AbortSignal,\n): AsyncGenerator<ChatEvent> {\n const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [...initialMessages];\n const MAX_TOOL_ROUNDS = 10;\n\n for (let round = 0; round < MAX_TOOL_ROUNDS; round++) {\n type ToolCallAcc = { id: string; name: string; args: string };\n const toolCallsAcc: Record<number, ToolCallAcc> = {};\n\n if (signal?.aborted) return;\n const stream = await client.chat.completions.create({\n model,\n messages,\n tools: CHAT_TOOLS_OPENAI,\n stream: true,\n max_tokens: 16384,\n temperature: 0,\n }, { signal });\n\n for await (const chunk of stream) {\n const choice = chunk.choices[0];\n if (!choice) continue;\n\n if (choice.delta?.content) {\n yield { type: 'delta', text: choice.delta.content };\n }\n\n // Accumulate tool call deltas\n for (const tc of choice.delta?.tool_calls ?? []) {\n const acc = toolCallsAcc[tc.index] ?? { id: '', name: '', args: '' };\n if (tc.id) acc.id = tc.id;\n if (tc.function?.name) acc.name = tc.function.name;\n if (tc.function?.arguments) acc.args += tc.function.arguments;\n toolCallsAcc[tc.index] = acc;\n }\n }\n\n // Some Ollama models return finish_reason 'stop' even when they made tool calls.\n // Fall back to checking if any tool calls were accumulated.\n if (Object.keys(toolCallsAcc).length === 0) {\n yield { type: 'done', text: '' };\n return;\n }\n\n // Build assistant message with tool calls\n const toolCallsList = Object.values(toolCallsAcc);\n messages.push({\n role: 'assistant',\n tool_calls: toolCallsList.map(tc => ({\n id: tc.id,\n type: 'function' as const,\n function: { name: tc.name, arguments: tc.args },\n })),\n });\n\n // Execute tools\n for (const tc of toolCallsList) {\n let input: Record<string, unknown> = {};\n try { input = JSON.parse(tc.args); } catch { /* empty */ }\n\n yield { type: 'tool_call', id: tc.id, name: tc.name, input };\n\n let result: unknown;\n let isError = false;\n try {\n result = await executeTool(tc.name, input, apiKey, authToken);\n } catch (err) {\n result = (err as Error).message;\n isError = true;\n }\n\n yield { type: 'tool_result', id: tc.id, name: tc.name, result, isError };\n messages.push({\n role: 'tool',\n tool_call_id: tc.id,\n content: typeof result === 'string' ? result : JSON.stringify(result, null, 2),\n });\n }\n // Loop\n }\n yield { type: 'done', text: '' };\n}\n\n// ─── Session drainer (shared by new-message and reconnect) ───────────────────\n\nasync function* drainSession(\n session: ActiveSession,\n signal: AbortSignal | undefined,\n isReconnect: boolean,\n): AsyncGenerator<\n | { type: 'delta'; text: string }\n | { type: 'status'; text: string }\n | { type: 'thinking'; text: string }\n | { type: 'context_usage'; inputTokens: number; contextWindow: number }\n | { type: 'tool_call'; id: string; name: string; input: Record<string, unknown> }\n | { type: 'tool_result'; id: string; name: string; result: unknown; isError: boolean }\n | { type: 'done'; text: '' }\n> {\n if(process.env.RUNEYA_DEBUG) console.log('[chat]: drainSession')\n // On reconnect, replay accumulated parts + current status\n if (isReconnect) {\n for (const part of session.parts) {\n if (part.type === 'thinking') {\n yield { type: 'thinking', text: part.text };\n } else if (part.type === 'text') {\n yield { type: 'delta', text: part.text };\n } else if (part.type === 'tool') {\n yield { type: 'tool_call', id: part.id, name: part.name, input: part.input ?? {} };\n if (!part.pending) yield { type: 'tool_result', id: part.id, name: part.name, result: part.result, isError: part.isError ?? false };\n }\n }\n if (session.lastStatus) {\n yield { type: 'status', text: session.lastStatus };\n }\n // If session already finished, yield done immediately\n if (session.status === 'done') {\n yield { type: 'done', text: '' };\n return;\n }\n }\n\n // Consumer cursor: skip buffered items, start receiving only NEW events\n // On reconnect we already replayed fullContent, so skip all existing buffer items\n let cursor = isReconnect ? session.totalProduced : (session.totalProduced - session.buffer.length);\n\n while (true) {\n // Drain any pending items\n while (cursor < session.totalProduced) {\n const idx = cursor - (session.totalProduced - session.buffer.length);\n const item: QueueItem | undefined = idx >= 0 ? session.buffer[idx] : undefined;\n cursor++;\n if (!item) continue;\n\n if (item.type === 'done') {\n yield { type: 'done', text: '' };\n return;\n }\n if (item.type === 'error') {\n yield { type: 'delta', text: `\\n\\n⚠️ ${item.message}` };\n continue;\n }\n if (item.type === 'status') {\n yield { type: 'status', text: item.text };\n continue;\n }\n if (item.type === 'thinking') {\n yield { type: 'thinking', text: item.text };\n continue;\n }\n if (item.type === 'context_usage') {\n yield { type: 'context_usage', inputTokens: item.inputTokens, contextWindow: item.contextWindow };\n continue;\n }\n if (item.type === 'tool_call') {\n yield { type: 'tool_call', id: item.id, name: item.name, input: item.input };\n continue;\n }\n if (item.type === 'tool_result') {\n yield { type: 'tool_result', id: item.id, name: item.name, result: item.result, isError: item.isError };\n continue;\n }\n yield item;\n }\n\n // If signal aborted, just stop yielding — process survives\n if (signal?.aborted) return;\n\n // Wait for next event from the registry, or signal abort\n await new Promise<void>(r => {\n if (cursor < session.totalProduced) { r(); return; }\n session.notify.add(r);\n const cleanup = () => { session.notify.delete(r); r(); };\n signal?.addEventListener('abort', cleanup, { once: true });\n });\n if (signal?.aborted) return;\n }\n}\n\n// ─── Shared CLI session starters (used by tRPC handlers + kanban queue) ──────\n\nasync function buildCliSystemContext(conv: Awaited<ReturnType<typeof conversationStore.get>>, jwt: string | undefined): Promise<string> {\n const allServices = await serviceStore.list();\n const resolvedServices = await Promise.all(allServices.map(resolveServiceVariables));\n let systemContext = generateAdminLlmsTxt(resolvedServices, jwt);\n\n if (conv?.kanbanBoardId) {\n const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);\n if (kanbanBoard) {\n systemContext += '\\n\\n' + (conv.kanbanCardId\n ? generateKanbanSystemPrompt(kanbanBoard, conv.kanbanCardId)\n : generateKanbanPopulatePrompt(kanbanBoard));\n }\n }\n return systemContext;\n}\n\n/**\n * Resolve the variables flagged `injectIntoAi` for the given active environment\n * (with inheritance) into a flat env dict. Returns undefined when nothing to inject.\n */\nasync function resolveInjectedEnv(environmentId?: string): Promise<Record<string, string> | undefined> {\n if (!environmentId) return undefined;\n try {\n const injected = await environmentResolver.resolveAiInjectedEnv(environmentId);\n return Object.keys(injected).length > 0 ? injected : undefined;\n } catch (err) {\n console.warn('[chat] resolveInjectedEnv failed:', (err as Error).message);\n return undefined;\n }\n}\n\nexport interface StartCliSessionOpts {\n model?: string;\n effort?: 'low' | 'medium' | 'high' | 'normal';\n jwt?: string;\n /** Extra metadata stored on the user message (for UI display) */\n userMessageParts?: MessagePart[];\n userMessageContextNote?: string;\n /** Active environment id: variables flagged `injectIntoAi` are injected into the process env. */\n environmentId?: string;\n}\n\n/**\n * Start a Claude Code session for a conversation.\n * Registers the session in activeSessionRegistry (so the frontend can subscribe),\n * builds the system context (services + kanban), and fires the runner.\n * Returns `{ session, done }` where `done` resolves when the runner finishes.\n * Throws if a session is already running for this conversation.\n */\nexport async function startClaudeCodeSession(\n convId: string,\n prompt: string,\n opts: StartCliSessionOpts = {},\n): Promise<{ session: ActiveSession; done: Promise<void> }> {\n const conv = await conversationStore.get(convId);\n if (!conv) throw new Error(`Conversation ${convId} not found`);\n\n const isResume = conv.messages.length > 0;\n conv.messages.push({\n role: 'user',\n content: prompt,\n parts: opts.userMessageParts,\n contextNote: opts.userMessageContextNote,\n });\n conv.messages.push({ role: 'assistant', content: '' });\n conversationStore.update(conv.id, { messages: conv.messages }, { silent: true }).catch(() => {});\n\n const systemContext = await buildCliSystemContext(conv, opts.jwt);\n\n const mcpServerPath = fileURLToPath(new URL('../mcp-server/index.js', import.meta.url));\n const mcpConfig = JSON.stringify({\n mcpServers: {\n runeya: {\n command: 'node',\n args: [mcpServerPath],\n env: { RUNEYA_BASE_URL: `http://localhost:${env.PORT}`, ...(opts.jwt ? { RUNEYA_API_TOKEN: opts.jwt } : {}) },\n },\n },\n });\n\n const ac = new AbortController();\n const session = activeSessionRegistry.registerProviderApiSession(convId, ac);\n let capturedFinalResult = '';\n\n const resolvedAgentId = agentManager.getDefaultAgentId();\n if (resolvedAgentId) {\n session.agentId = resolvedAgentId;\n }\n\n const injectedEnv = await resolveInjectedEnv(opts.environmentId);\n\n const done = new ClaudeCodeRunner().run({\n agentId: resolvedAgentId ?? undefined,\n sessionId: conv.id,\n prompt,\n isResume,\n systemContext,\n apiBaseUrl: `http://localhost:${env.PORT}`,\n apiToken: opts.jwt ?? '',\n model: opts.model ?? 'claude-opus-4-6',\n effort: opts.effort ?? 'normal',\n signal: ac.signal,\n skipTokenInstructions: true,\n mcpConfig,\n injectedEnv,\n onDelta: (text) => activeSessionRegistry.pushEvent(convId, { type: 'delta', text }),\n onStatus: (text) => activeSessionRegistry.pushEvent(convId, { type: 'status', text }),\n onThinking: (text) => activeSessionRegistry.pushEvent(convId, { type: 'thinking', text }),\n onToolCall: (id, name, input_) => activeSessionRegistry.pushEvent(convId, { type: 'tool_call', id, name, input: input_ }),\n onToolResult: (id, result, isError) => activeSessionRegistry.pushEvent(convId, { type: 'tool_result', id, name: '', result, isError }),\n onContextUsage: (inputTokens, contextWindow) => activeSessionRegistry.pushEvent(convId, { type: 'context_usage', inputTokens, contextWindow }),\n onResult: (result) => { if (result) capturedFinalResult = result; },\n }).then(() => {\n if (process.env.RUNEYA_DEBUG) console.log('[chat]: claude end...');\n if (activeSessionRegistry.get(convId) !== session) return;\n if (capturedFinalResult && capturedFinalResult.length > session.fullContent.length) {\n const missing = capturedFinalResult.slice(session.fullContent.length);\n activeSessionRegistry.pushEvent(convId, { type: 'delta', text: missing });\n }\n activeSessionRegistry.pushEvent(convId, { type: 'done', text: '' });\n activeSessionRegistry.markDone(convId);\n }).catch((err: Error) => {\n if (process.env.RUNEYA_DEBUG) console.error('[chat]: error...', err?.message, err);\n if (activeSessionRegistry.get(convId) !== session) return;\n activeSessionRegistry.pushEvent(convId, { type: 'error', message: `Claude Code error: ${err.message}` });\n activeSessionRegistry.pushEvent(convId, { type: 'done', text: '' });\n activeSessionRegistry.markDone(convId);\n });\n\n return { session, done };\n}\n\nexport interface StartCodexSessionOpts {\n model?: string;\n jwt?: string;\n images?: { imageId: string; base64: string; mimeType: string; altText?: string }[];\n userMessageParts?: MessagePart[];\n userMessageContextNote?: string;\n /** Active environment id: variables flagged `injectIntoAi` are injected into the process env. */\n environmentId?: string;\n}\n\n/**\n * Start a Codex session for a conversation.\n * Same contract as startClaudeCodeSession.\n */\nexport async function startCodexSession(\n convId: string,\n prompt: string,\n opts: StartCodexSessionOpts = {},\n): Promise<{ session: ActiveSession; done: Promise<void> }> {\n const conv = await conversationStore.get(convId);\n if (!conv) throw new Error(`Conversation ${convId} not found`);\n\n const isResume = !!conv.codexThreadId;\n conv.messages.push({\n role: 'user',\n content: prompt,\n parts: opts.userMessageParts,\n contextNote: opts.userMessageContextNote,\n });\n conv.messages.push({ role: 'assistant', content: '' });\n conversationStore.update(conv.id, { messages: conv.messages }, { silent: true }).catch(() => {});\n\n const systemContext = await buildCliSystemContext(conv, opts.jwt);\n\n const ac = new AbortController();\n const session = activeSessionRegistry.registerProviderApiSession(convId, ac);\n\n const resolvedAgentId = agentManager.getDefaultAgentId();\n if (resolvedAgentId) {\n session.agentId = resolvedAgentId;\n }\n\n const injectedEnv = await resolveInjectedEnv(opts.environmentId);\n\n const done = new CodexRunner().run({\n agentId: resolvedAgentId ?? undefined,\n sessionId: conv.codexThreadId ?? '',\n prompt,\n isResume,\n systemContext,\n apiBaseUrl: `http://localhost:${env.PORT}`,\n apiToken: opts.jwt ?? '',\n model: opts.model ?? '',\n effort: 'normal',\n signal: ac.signal,\n skipTokenInstructions: true,\n images: opts.images,\n injectedEnv,\n onThreadId: (threadId) => conversationStore.update(conv.id, { codexThreadId: threadId }).catch(() => {}),\n onDelta: (text) => activeSessionRegistry.pushEvent(convId, { type: 'delta', text }),\n onStatus: (text) => activeSessionRegistry.pushEvent(convId, { type: 'status', text }),\n onThinking: (text) => activeSessionRegistry.pushEvent(convId, { type: 'thinking', text }),\n onToolCall: (id, name, input_) => activeSessionRegistry.pushEvent(convId, { type: 'tool_call', id, name, input: input_ }),\n onToolResult: (id, result, isError) => activeSessionRegistry.pushEvent(convId, { type: 'tool_result', id, name: '', result, isError }),\n }).then(() => {\n if (activeSessionRegistry.get(convId) !== session) return;\n activeSessionRegistry.pushEvent(convId, { type: 'done', text: '' });\n activeSessionRegistry.markDone(convId);\n }).catch((err: Error) => {\n if (activeSessionRegistry.get(convId) !== session) return;\n activeSessionRegistry.pushEvent(convId, { type: 'error', message: `Codex error: ${err.message}` });\n activeSessionRegistry.pushEvent(convId, { type: 'done', text: '' });\n activeSessionRegistry.markDone(convId);\n });\n\n return { session, done };\n}\n\n// ─── Router ───────────────────────────────────────────────────────────────────\n\nconst MessagePartSchema = z.discriminatedUnion('type', [\n z.object({ type: z.literal('thinking'), text: z.string().max(100_000) }),\n z.object({ type: z.literal('text'), text: z.string().max(100_000) }),\n z.object({\n type: z.literal('tool'),\n id: Id128Schema,\n name: Id128Schema,\n input: z.record(z.string(), z.unknown()).optional(),\n rawInput: z.string().max(10_000).optional(),\n result: z.unknown().optional(),\n isError: z.boolean().optional(),\n pending: z.boolean(),\n }),\n]);\n\nconst StoredMessageSchema = z.object({\n role: z.enum(['user', 'assistant']),\n content: z.string().max(100_000),\n parts: z.array(MessagePartSchema).max(200).optional(),\n});\n\nexport const chatRouter = router({\n conversations: router({\n onChanged: protectedProcedure.subscription(async function* () {\n const initial = await conversationStore.list();\n yield { type: 'initial' as const, conversations: initial };\n\n const queue: ConversationChangeEvent[] = [];\n let resolve: (() => void) | null = null;\n\n const handler = (event: ConversationChangeEvent) => {\n if (queue.length >= 500) queue.shift();\n queue.push(event);\n if (resolve) {\n resolve();\n resolve = null;\n }\n };\n\n conversationStore.onChanged(handler);\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n conversationStore.offChanged(handler);\n }\n }),\n\n list: protectedProcedure\n .query(() => conversationStore.list()),\n\n get: protectedProcedure\n .input(z.object({ id: Id128Schema }))\n .query(async ({ input }) => {\n const conv = await conversationStore.get(input.id);\n if (!conv) throw new TRPCError({ code: 'NOT_FOUND', message: 'Conversation not found' });\n return conv;\n }),\n\n create: protectedProcedure\n .input(z.object({\n title: ShortString200Schema.optional(),\n isCli: z.boolean().optional(),\n runner: z.enum(['claude-code', 'codex']).optional(),\n providerId: Id128Schema.optional(),\n scenarioId: Id128Schema.optional(),\n scenarioInput: z.string().max(100_000).optional(),\n kanbanBoardId: Id128Schema.optional(),\n kanbanCardId: Id128Schema.optional(),\n }))\n .mutation(async ({ input }) => {\n let scenario = null;\n if (input.scenarioId) {\n scenario = await scenarioStore.get(input.scenarioId);\n if (!scenario) throw new TRPCError({ code: 'NOT_FOUND', message: 'Scenario not found' });\n }\n\n const conv = await conversationStore.create(\n input.title,\n input.isCli ?? false,\n input.scenarioId,\n input.scenarioId ? 'scenario' : undefined,\n input.runner,\n input.kanbanBoardId,\n input.kanbanCardId,\n input.providerId,\n );\n\n if (scenario) {\n await scenarioRunStore.initializeConversationWorkspace(\n conv.id,\n scenario,\n input.scenarioInput ?? '',\n );\n }\n\n return conv;\n }),\n\n update: protectedProcedure\n .input(z.object({\n id: Id128Schema,\n title: ShortString200Schema.optional(),\n messages: z.array(StoredMessageSchema).max(500).optional(),\n contextUsage: z.object({\n inputTokens: z.number().int().nonnegative(),\n contextWindow: z.number().int().positive(),\n }).optional(),\n }))\n .mutation(async ({ input }) => {\n const conv = await conversationStore.update(input.id, { title: input.title, messages: input.messages, contextUsage: input.contextUsage });\n if (!conv) throw new TRPCError({ code: 'NOT_FOUND', message: 'Conversation not found' });\n return conv;\n }),\n\n delete: protectedProcedure\n .input(z.object({ id: Id128Schema }))\n .mutation(async ({ input }) => {\n const existing = await conversationStore.get(input.id);\n if (!existing) throw new TRPCError({ code: 'NOT_FOUND', message: 'Conversation not found' });\n\n // Kill any interactive PTY still running for this conversation before we\n // drop it. PTY sessions are spawned with sessionId === conversation id and\n // never exit on their own, so without this they'd leak a concurrency slot.\n // Fire-and-forget across every connected agent (we don't track which one\n // hosts the session on the conversation record).\n for (const agent of agentManager.listAgents()) {\n const agentId = agent.config.id;\n agentManager\n .agentQuery<{ spawnId: string; status: string } | null>(\n agentId,\n 'ai.findPtyBySession',\n { sessionId: input.id },\n )\n .then((pty) => {\n if (pty?.status === 'running') {\n return agentManager.agentMutation(agentId, 'ai.kill', { spawnId: pty.spawnId });\n }\n })\n .catch(() => { /* agent unreachable or no session — best-effort */ });\n }\n\n await conversationStore.delete(input.id);\n await scenarioRunStore.deleteRunDir(input.id);\n // Fire-and-forget: delete the whole conversation images directory\n imageStorageService.deleteByContextId(input.id).catch((err) =>\n console.error('[chat.delete] Image cleanup error:', err),\n );\n }),\n\n archive: protectedProcedure\n .input(z.object({ id: Id128Schema, archived: z.boolean() }))\n .mutation(async ({ input }) => {\n const conv = await conversationStore.update(input.id, { archived: input.archived });\n if (!conv) throw new TRPCError({ code: 'NOT_FOUND', message: 'Conversation not found' });\n return conv;\n }),\n }),\n\n listModels: protectedProcedure\n .input(z.object({ providerId: Id128Schema.optional() }).optional())\n .query(async ({ input }) => {\n const active = await getActiveProvider(input?.providerId);\n if (!active) return [];\n try {\n return await fetchProviderModels(active.provider, active.plaintextKey);\n } catch {\n return [];\n }\n }),\n\n checkCliAvailability: protectedProcedure\n .input(z.object({ agentId: Id128Schema.optional() }).optional())\n .query(async ({ input }) => {\n if (input?.agentId) {\n try {\n const res = await agentManager.agentQuery<{ claudeAvailable: boolean; codexAvailable: boolean }>(\n input.agentId,\n 'health.checkCli',\n );\n return { available: res.claudeAvailable, codexAvailable: res.codexAvailable };\n } catch {\n return { available: false, codexAvailable: false };\n }\n }\n const [claudeOk, codexOk] = await Promise.all([\n execFileAsync('claude', ['--version'], { timeout: 5000, shell: false }).then(() => true).catch(() => false),\n execFileAsync('codex', ['--version'], { timeout: 5000, shell: false }).then(() => true).catch(() => false),\n ]);\n return { available: claudeOk, codexAvailable: codexOk };\n }),\n\n enhanceScenarioPrompt: protectedProcedure\n .input(z.object({\n text: z.string().max(10_000),\n providerId: Id128Schema.optional(),\n model: z.string().max(200).optional(),\n }))\n .mutation(async ({ input }) => {\n const active = await getActiveProvider(input.providerId);\n if (!active) throw new TRPCError({ code: 'BAD_REQUEST', message: 'No AI provider configured' });\n\n const systemPrompt = `You are an expert at writing clear, concise user request briefs for AI-powered workflows.\nWhen given a rough user request, rewrite it to be:\n- Clear and well-structured\n- Specific about the expected outcome\n- Written in the same language as the input\n- Concise but complete (no fluff)\nReturn ONLY the improved text, no explanation, no preamble.`;\n\n const { provider, plaintextKey } = active;\n const model = input.model || provider.model || DEFAULT_MODELS[provider.provider] || 'claude-opus-4-6';\n\n if (provider.provider === 'anthropic') {\n const client = new Anthropic({ apiKey: plaintextKey });\n const res = await client.messages.create({\n model,\n max_tokens: 2048,\n system: systemPrompt,\n messages: [{ role: 'user', content: input.text }],\n });\n const block = res.content[0];\n return { enhanced: block?.type === 'text' ? block.text : input.text };\n }\n\n if (provider.provider in OPENAI_COMPAT_BASE_URLS) {\n const baseURL = OPENAI_COMPAT_BASE_URLS[provider.provider]!;\n const client = new OpenAI({ apiKey: plaintextKey || 'ollama', baseURL });\n const res = await client.chat.completions.create({\n model,\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: input.text },\n ],\n });\n return { enhanced: res.choices[0]?.message?.content ?? input.text };\n }\n\n return { enhanced: input.text };\n }),\n\n listClaudeCodeModels: protectedProcedure\n .query(() => ['opus', 'sonnet', 'haiku']),\n\n getClaudeUsage: protectedProcedure\n .query(async () => {\n try {\n return await getClaudeUsageEntries();\n } catch {\n return null;\n }\n }),\n\n getCodexUsage: protectedProcedure\n .query(async () => {\n try {\n return await getCodexUsageEntries();\n } catch {\n return null;\n }\n }),\n\n getStreamingStatus: protectedProcedure\n .query(() => activeSessionRegistry.listActive()),\n\n stopSession: protectedProcedure\n .input(z.object({ conversationId: ConversationIdSchema }))\n .mutation(({ input }) => {\n if(process.env.RUNEYA_DEBUG) console.log('[chat]: stopSession')\n const killed = activeSessionRegistry.kill(input.conversationId);\n if (!killed) throw new TRPCError({ code: 'NOT_FOUND', message: 'No active session for this conversation' });\n return { ok: true };\n }),\n\n streamViaClaudeCode: protectedProcedure\n .input(z.object({\n conversationId: ConversationIdSchema,\n prompt: z.string().max(100_000),\n contextNote: z.string().max(200_000).optional(),\n model: ShortString200Schema.optional(),\n effort: z.enum(['low', 'medium', 'high']).optional(),\n reconnect: z.boolean().optional(),\n agentId: Id128Schema.optional(),\n environmentId: z.string().max(128).optional(),\n imageIds: z.array(z.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(),\n imageParts: ImagePartsSchema,\n }))\n .subscription(async function* ({ input, ctx, signal }) {\n // ── Reconnect path: attach to an existing session ───────────────────\n if(process.env.RUNEYA_DEBUG) console.log('[chat]: Reconnect')\n const existingSession = activeSessionRegistry.get(input.conversationId);\n if (input.reconnect && existingSession) {\n yield* drainSession(existingSession, signal, true);\n return;\n }\n\n // ── New message path ────────────────────────────────────────────────\n if (!input.prompt) throw new TRPCError({ code: 'BAD_REQUEST', message: 'Prompt is required for new messages' });\n\n const conv = await conversationStore.get(input.conversationId);\n if (!conv) throw new TRPCError({ code: 'NOT_FOUND', message: 'Conversation not found' });\n\n console.log(`[kanban-debug] streamViaClaudeCode start — convId=${conv.id} kanbanBoardId=${conv.kanbanBoardId ?? 'null'}`);\n\n const isResume = conv.messages.length > 0;\n\n const userParts = input.imageParts && input.imageParts.length > 0\n ? [...(input.prompt.trim() ? [{ type: 'text' as const, text: input.prompt }] : []), ...input.imageParts]\n : undefined;\n conv.messages.push({ role: 'user', content: input.prompt, parts: userParts, contextNote: input.contextNote });\n conv.messages.push({ role: 'assistant', content: '' });\n if(process.env.RUNEYA_DEBUG) console.log('[chat]: update')\n conversationStore.update(conv.id, { messages: conv.messages }, { silent: true }).catch(() => { });\n\n const cliPrompt = input.contextNote ? `${input.contextNote}\\n\\n${input.prompt}` : input.prompt;\n\n const allServices = await serviceStore.list();\n const resolvedServices = await Promise.all(allServices.map(resolveServiceVariables));\n const jwt = ctx.authorization?.startsWith('Bearer ') ? ctx.authorization.slice(7) : undefined;\n let systemContext = generateAdminLlmsTxt(resolvedServices, jwt);\n\n if (conv.kanbanBoardId) {\n const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);\n if (kanbanBoard) {\n systemContext += '\\n\\n' + (conv.kanbanCardId\n ? generateKanbanSystemPrompt(kanbanBoard, conv.kanbanCardId)\n : generateKanbanPopulatePrompt(kanbanBoard));\n }\n }\n\n const mcpServerPath = fileURLToPath(new URL('../mcp-server/index.js', import.meta.url));\n const mcpConfig = JSON.stringify({\n mcpServers: {\n runeya: {\n command: 'node',\n args: [mcpServerPath],\n env: { RUNEYA_BASE_URL: `http://localhost:${env.PORT}`, ...(jwt ? { RUNEYA_API_TOKEN: jwt } : {}) },\n },\n },\n });\n\n // Claude Code has filesystem access — pass image paths directly in the prompt\n const imagePaths: string[] = [];\n if (input.imageIds && input.imageIds.length > 0) {\n for (const id of input.imageIds) {\n // Scopé à la conversation : sinon un imageId d'une autre conversation\n // se glisse dans le prompt et fuit par ce chemin.\n const result = await imageStorageService.getImagePath(id, input.conversationId);\n if (result) imagePaths.push(result.filePath);\n }\n }\n const promptWithImages = imagePaths.length > 0\n ? `${cliPrompt}\\n\\n${imagePaths.map(p => `Image: ${p}`).join('\\n')}`\n : cliPrompt;\n\n const convId = input.conversationId;\n const ac = new AbortController();\n let session: ActiveSession;\n try {\n session = activeSessionRegistry.registerProviderApiSession(convId, ac);\n } catch {\n throw new TRPCError({ code: 'CONFLICT', message: 'A session is already running for this conversation. Stop it first.' });\n }\n let capturedFinalResult = '';\n\n const resolvedAgentId = input.agentId ?? agentManager.getDefaultAgentId();\n if (resolvedAgentId) {\n session.agentId = resolvedAgentId;\n }\n\n if(process.env.RUNEYA_DEBUG) console.log('[chat]: claude run...')\n const injectedEnv = await resolveInjectedEnv(input.environmentId);\n new ClaudeCodeRunner().run({\n agentId: resolvedAgentId ?? undefined,\n sessionId: conv.id,\n prompt: promptWithImages,\n isResume,\n systemContext,\n apiBaseUrl: `http://localhost:${env.PORT}`,\n apiToken: jwt ?? '',\n model: input.model ?? 'claude-opus-4-6',\n effort: input.effort ?? 'normal',\n signal: ac.signal,\n skipTokenInstructions: true,\n mcpConfig,\n injectedEnv,\n onDelta: (text) => {\n activeSessionRegistry.pushEvent(convId, { type: 'delta', text });\n },\n onStatus: (text) => activeSessionRegistry.pushEvent(convId, { type: 'status', text }),\n onThinking: (text) => activeSessionRegistry.pushEvent(convId, { type: 'thinking', text }),\n onToolCall: (id, name, input_) => activeSessionRegistry.pushEvent(convId, { type: 'tool_call', id, name, input: input_ }),\n onToolResult: (id, result, isError) => activeSessionRegistry.pushEvent(convId, { type: 'tool_result', id, name: '', result, isError }),\n onContextUsage: (inputTokens: number, contextWindow: number) => activeSessionRegistry.pushEvent(convId, { type: 'context_usage', inputTokens, contextWindow }),\n onResult: (result: string) => { if (result) capturedFinalResult = result; },\n }).then(() => {\n if (activeSessionRegistry.get(convId) !== session) return;\n\n // Reconcile: push any content captured in the result event but missed by text_delta\n if (capturedFinalResult && capturedFinalResult.length > session.fullContent.length) {\n const missing = capturedFinalResult.slice(session.fullContent.length);\n activeSessionRegistry.pushEvent(convId, { type: 'delta', text: missing });\n }\n\n activeSessionRegistry.pushEvent(convId, { type: 'done', text: '' });\n activeSessionRegistry.markDone(convId);\n }).catch((err: Error) => {\n if (activeSessionRegistry.get(convId) !== session) return;\n activeSessionRegistry.pushEvent(convId, { type: 'error', message: `Claude Code error: ${err.message}` });\n activeSessionRegistry.pushEvent(convId, { type: 'done', text: '' });\n activeSessionRegistry.markDone(convId);\n });\n\n if(process.env.RUNEYA_DEBUG) console.log('[chat]: drainSession...')\n yield* drainSession(session, signal, false);\n }),\n\n streamViaCodex: protectedProcedure\n .input(z.object({\n conversationId: ConversationIdSchema,\n prompt: z.string().max(100_000),\n contextNote: z.string().max(200_000).optional(),\n model: ShortString200Schema.optional(),\n reconnect: z.boolean().optional(),\n agentId: Id128Schema.optional(),\n environmentId: z.string().max(128).optional(),\n imageIds: z.array(z.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(),\n imageParts: ImagePartsSchema,\n }))\n .subscription(async function* ({ input, ctx, signal }) {\n // ── Reconnect path ───────────────────────────────────────────────────\n const existingSession = activeSessionRegistry.get(input.conversationId);\n if (input.reconnect && existingSession) {\n yield* drainSession(existingSession, signal, true);\n return;\n }\n\n if (!input.prompt) throw new TRPCError({ code: 'BAD_REQUEST', message: 'Prompt is required' });\n\n const conv = await conversationStore.get(input.conversationId);\n if (!conv) throw new TRPCError({ code: 'NOT_FOUND', message: 'Conversation not found' });\n\n const isResume = !!conv.codexThreadId;\n\n const codexUserParts = input.imageParts && input.imageParts.length > 0\n ? [...(input.prompt.trim() ? [{ type: 'text' as const, text: input.prompt }] : []), ...input.imageParts]\n : undefined;\n conv.messages.push({ role: 'user', content: input.prompt, parts: codexUserParts, contextNote: input.contextNote });\n conv.messages.push({ role: 'assistant', content: '' });\n conversationStore.update(conv.id, { messages: conv.messages }, { silent: true }).catch(() => {});\n\n const cliPrompt = input.contextNote ? `${input.contextNote}\\n\\n${input.prompt}` : input.prompt;\n\n const allServices = await serviceStore.list();\n const resolvedServices = await Promise.all(allServices.map(resolveServiceVariables));\n const jwt = ctx.authorization?.startsWith('Bearer ') ? ctx.authorization.slice(7) : undefined;\n let systemContext = generateAdminLlmsTxt(resolvedServices, jwt);\n\n if (conv.kanbanBoardId) {\n const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);\n if (kanbanBoard) {\n systemContext += '\\n\\n' + (conv.kanbanCardId\n ? generateKanbanSystemPrompt(kanbanBoard, conv.kanbanCardId)\n : generateKanbanPopulatePrompt(kanbanBoard));\n }\n }\n\n const resolvedImages = input.imageIds && input.imageIds.length > 0\n ? await resolveImagesToBase64(input.imageIds.map(id => ({ imageId: id, mimeType: '' })), input.conversationId)\n : [];\n\n const convId = input.conversationId;\n const ac = new AbortController();\n let session: ActiveSession;\n try {\n session = activeSessionRegistry.registerProviderApiSession(convId, ac);\n } catch {\n throw new TRPCError({ code: 'CONFLICT', message: 'A session is already running for this conversation. Stop it first.' });\n }\n\n const resolvedAgentId = input.agentId ?? agentManager.getDefaultAgentId();\n if (resolvedAgentId) {\n session.agentId = resolvedAgentId;\n }\n\n const injectedEnv = await resolveInjectedEnv(input.environmentId);\n new CodexRunner().run({\n agentId: resolvedAgentId ?? undefined,\n sessionId: conv.codexThreadId ?? '',\n prompt: cliPrompt,\n isResume,\n systemContext,\n apiBaseUrl: `http://localhost:${env.PORT}`,\n apiToken: jwt ?? '',\n model: input.model ?? '',\n effort: 'normal',\n signal: ac.signal,\n skipTokenInstructions: true,\n images: resolvedImages,\n injectedEnv,\n onThreadId: (threadId) => conversationStore.update(conv.id, { codexThreadId: threadId }).catch(() => {}),\n onDelta: (text) => activeSessionRegistry.pushEvent(convId, { type: 'delta', text }),\n onStatus: (text) => activeSessionRegistry.pushEvent(convId, { type: 'status', text }),\n onThinking: (text) => activeSessionRegistry.pushEvent(convId, { type: 'thinking', text }),\n onToolCall: (id, name, input_) => activeSessionRegistry.pushEvent(convId, { type: 'tool_call', id, name, input: input_ }),\n onToolResult: (id, result, isError) => activeSessionRegistry.pushEvent(convId, { type: 'tool_result', id, name: '', result, isError }),\n }).then(() => {\n if (activeSessionRegistry.get(convId) !== session) return;\n activeSessionRegistry.pushEvent(convId, { type: 'done', text: '' });\n activeSessionRegistry.markDone(convId);\n }).catch((err: Error) => {\n if (activeSessionRegistry.get(convId) !== session) return;\n activeSessionRegistry.pushEvent(convId, { type: 'error', message: `Codex error: ${err.message}` });\n activeSessionRegistry.pushEvent(convId, { type: 'done', text: '' });\n activeSessionRegistry.markDone(convId);\n });\n\n yield* drainSession(session, signal, false);\n }),\n\n send: protectedProcedure\n .input(z.object({\n conversationId: ConversationIdSchema,\n messages: z.array(MessageSchema).min(0).max(100),\n model: ShortString200Schema.optional(),\n contextNote: z.string().max(200_000).optional(),\n reconnect: z.boolean().optional(),\n imageIds: z.array(z.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(),\n imageParts: ImagePartsSchema,\n }))\n .subscription(async function* ({ input, ctx, signal }) {\n // ── Reconnect path: attach to an existing session ───────────────────\n const existingSession = activeSessionRegistry.get(input.conversationId);\n if (input.reconnect && existingSession) {\n yield* drainSession(existingSession, signal, true);\n return;\n }\n\n // ── New message path ────────────────────────────────────────────────\n if (input.messages.length === 0) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Messages are required for new messages' });\n }\n\n // Persist user message immediately — don't wait for the frontend\n const conv = await conversationStore.get(input.conversationId);\n\n const active = await getActiveProvider(conv?.providerId);\n\n if (!active) {\n throw new TRPCError({\n code: 'PRECONDITION_FAILED',\n message: 'No AI provider configured for this conversation. Please select one when starting a new chat.',\n });\n }\n if (conv) {\n const lastUserMsg = input.messages[input.messages.length - 1];\n if (lastUserMsg) {\n const sendUserParts = input.imageParts && input.imageParts.length > 0\n ? [...(lastUserMsg.content.trim() ? [{ type: 'text' as const, text: lastUserMsg.content }] : []), ...input.imageParts]\n : undefined;\n conv.messages.push({ role: lastUserMsg.role, content: lastUserMsg.content, parts: sendUserParts, contextNote: input.contextNote });\n conv.messages.push({ role: 'assistant', content: '' });\n await conversationStore.update(conv.id, { messages: conv.messages }, { silent: true });\n }\n }\n\n const { provider, plaintextKey } = active;\n const model = input.model ?? provider.model ?? DEFAULT_MODELS[provider.provider] ?? 'gpt-4o';\n const apiKey = (ctx as AuthContext).apiKey ?? null;\n const authToken = ctx.authorization?.replace(/^Bearer\\s+/i, '') ?? '';\n let system = await buildSystemPrompt(apiKey);\n system += '\\n\\n' + TOOL_SAFETY_INSTRUCTION;\n\n // Append kanban context if this conversation is linked to a kanban board/card\n if (conv && conv.kanbanBoardId) {\n const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);\n if (kanbanBoard) {\n system += '\\n\\n' + (conv.kanbanCardId\n ? generateKanbanSystemPrompt(kanbanBoard, conv.kanbanCardId)\n : generateKanbanPopulatePrompt(kanbanBoard));\n }\n }\n\n // Resolve images if any imageIds provided\n const resolvedImages = input.imageIds && input.imageIds.length > 0\n ? await resolveImagesToBase64(input.imageIds.map(id => ({ imageId: id, mimeType: '' })), input.conversationId)\n : [];\n\n // Register in the session registry — stream survives WS disconnection\n let session: ActiveSession;\n try {\n session = activeSessionRegistry.registerDirectProviderApiSession(input.conversationId);\n } catch {\n throw new TRPCError({ code: 'CONFLICT', message: 'A session is already running for this conversation. Stop it first.' });\n }\n const apiSignal = session.abortController!.signal;\n\n // Fire-and-forget: run the API stream, pushing events into the registry\n const runStream = async () => {\n try {\n let gen: AsyncGenerator<ChatEvent>;\n\n if (provider.provider === 'anthropic') {\n const client = new Anthropic({ apiKey: plaintextKey });\n const msgs: Anthropic.MessageParam[] = input.messages.map((m, i) => {\n const isLast = i === input.messages.length - 1;\n if (isLast && resolvedImages.length > 0) {\n const content: Anthropic.ContentBlockParam[] = resolvedImages.map(img => ({\n type: 'image' as const,\n source: { type: 'base64' as const, media_type: img.mimeType as Anthropic.Base64ImageSource['media_type'], data: img.base64 },\n }));\n content.push({ type: 'text', text: m.content });\n return { role: m.role, content };\n }\n return { role: m.role, content: m.content };\n });\n gen = runAnthropic(client, model, system, msgs, apiKey, authToken, apiSignal);\n } else if (provider.provider in OPENAI_COMPAT_BASE_URLS) {\n const baseURL = OPENAI_COMPAT_BASE_URLS[provider.provider]!;\n const client = new OpenAI({ apiKey: plaintextKey || 'ollama', baseURL });\n const msgs: OpenAI.Chat.ChatCompletionMessageParam[] = [\n { role: 'system', content: system },\n ...input.messages.map((m, i) => {\n const isLast = i === input.messages.length - 1;\n if (isLast && resolvedImages.length > 0) {\n const content: OpenAI.Chat.ChatCompletionContentPart[] = resolvedImages.map(img => ({\n type: 'image_url' as const,\n image_url: { url: `data:${img.mimeType};base64,${img.base64}` },\n }));\n content.push({ type: 'text', text: m.content });\n return { role: m.role, content } as OpenAI.Chat.ChatCompletionMessageParam;\n }\n return { role: m.role, content: m.content } as OpenAI.Chat.ChatCompletionMessageParam;\n }),\n ];\n gen = runOpenAI(client, model, msgs, apiKey, authToken, apiSignal);\n } else {\n activeSessionRegistry.pushEvent(input.conversationId, { type: 'error', message: `Provider \"${provider.provider}\" is not supported.` });\n activeSessionRegistry.pushEvent(input.conversationId, { type: 'done', text: '' });\n activeSessionRegistry.markDone(input.conversationId);\n return;\n }\n\n for await (const event of gen) {\n if (event.type === 'delta') {\n activeSessionRegistry.pushEvent(input.conversationId, { type: 'delta', text: event.text });\n } else if (event.type === 'tool_call') {\n activeSessionRegistry.pushEvent(input.conversationId, { type: 'tool_call', id: event.id, name: event.name, input: event.input });\n } else if (event.type === 'tool_result') {\n activeSessionRegistry.pushEvent(input.conversationId, { type: 'tool_result', id: event.id, name: event.name, result: event.result, isError: event.isError });\n } else if (event.type === 'done') {\n activeSessionRegistry.pushEvent(input.conversationId, { type: 'done', text: '' });\n }\n }\n } catch (err) {\n if (!apiSignal.aborted) {\n activeSessionRegistry.pushEvent(input.conversationId, { type: 'error', message: (err as Error).message });\n activeSessionRegistry.pushEvent(input.conversationId, { type: 'done', text: '' });\n }\n } finally {\n activeSessionRegistry.markDone(input.conversationId);\n }\n };\n\n // Start the stream in the background — it won't be cancelled by tRPC signal\n void runStream();\n\n // Drain from registry (WS disconnection stops yielding but stream continues)\n yield* drainSession(session, signal, false);\n }),\n\n // ── PTY passthrough (interactive Claude Code session) ────────────────────\n pty: router({\n /** Start a PTY session running `claude --resume <sessionId>` (or fresh). */\n start: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128).optional(),\n sessionId: z.string().max(128).optional(),\n runner: z.enum(['claude-code', 'codex']).default('claude-code'),\n resume: z.boolean().default(false),\n model: z.string().max(128).optional(),\n cwd: z.string().max(4096).optional(),\n cols: z.number().int().min(1).max(1000).default(120),\n rows: z.number().int().min(1).max(1000).default(30),\n enableMcp: z.boolean().default(false),\n apiBaseUrl: z.string().max(512).optional(),\n environmentId: z.string().max(128).optional(),\n attachedContexts: z.array(z.object({\n label: z.string().max(200),\n text: z.string().max(1_000_000),\n })).max(20).optional(),\n }))\n .mutation(async ({ input, ctx }) => {\n const agentId = input.agentId ?? agentManager.getDefaultAgentId();\n if (!agentId) throw new TRPCError({ code: 'PRECONDITION_FAILED', message: 'No agent available' });\n\n // If a PTY is already alive for this sessionId, re-attach to it instead\n // of spawning a fresh `claude` (so the process survives navigation).\n if (input.sessionId) {\n try {\n const existing = await agentManager.agentQuery<{ spawnId: string; status: string } | null>(\n agentId,\n 'ai.findPtyBySession',\n { sessionId: input.sessionId },\n );\n if (existing && existing.status === 'running') {\n // Resize to current viewport so the reattached terminal looks right.\n await agentManager.agentMutation(agentId, 'ai.resizePty', {\n spawnId: existing.spawnId,\n cols: input.cols,\n rows: input.rows,\n }).catch(() => {});\n return { spawnId: existing.spawnId, agentId, reattached: true };\n }\n } catch {\n // best-effort — fall back to spawning a fresh PTY\n }\n }\n\n const isCodex = input.runner === 'codex';\n const cli = isCodex ? 'codex' : 'claude';\n const args: string[] = [];\n if (isCodex) {\n // Codex resume is a positional subcommand: `codex resume <id>`. Only\n // attempt it when the rollout file actually exists on disk, otherwise\n // the CLI errors out instead of starting fresh. The app-server reuses\n // the rollout id as the threadId, so an existing conversation usually\n // resumes — but a session born purely in the app-server may not have a\n // matching rollout, in which case we start a clean session.\n if (input.sessionId && await codexSessionExists(input.sessionId)) {\n args.push('resume', input.sessionId);\n }\n if (input.model) args.push('--model', input.model);\n args.push('--dangerously-bypass-approvals-and-sandbox');\n } else {\n if (input.sessionId) {\n // Auto-detect whether the session already exists on disk: Claude refuses\n // `--session-id <id>` when the ID is already known. Override the caller's\n // hint so a returning conversation always resumes cleanly.\n const sessionExists = await claudeSessionExists(input.sessionId);\n if (input.resume || sessionExists) {\n args.push('--resume', input.sessionId);\n } else {\n args.push('--session-id', input.sessionId);\n }\n }\n if (input.model) args.push('--model', input.model);\n args.push('--dangerously-skip-permissions');\n }\n\n // Build the system prompt (services llms.txt + kanban + API docs) and\n // inject it via `--append-system-prompt` so Claude treats it as a real\n // system prompt instead of a user message. Codex has no equivalent\n // append-system-prompt flag, so this is skipped for the codex runner\n // (only the attached-context bracketed paste below applies to it).\n const jwt = ctx.authorization?.startsWith('Bearer ') ? ctx.authorization.slice(7) : undefined;\n if (!isCodex && input.sessionId) {\n try {\n const conv = await conversationStore.get(input.sessionId);\n if (conv) {\n const systemContext = await buildCliSystemContext(conv, jwt);\n const apiBase = input.apiBaseUrl ?? `http://localhost:${env.PORT}`;\n const apiDocs = buildApiDocs(apiBase, jwt ?? '');\n const fullSystemPrompt = apiDocs ? `${systemContext}\\n\\n${apiDocs}` : systemContext;\n if (fullSystemPrompt.trim().length > 0) {\n args.push('--append-system-prompt', fullSystemPrompt);\n }\n }\n } catch (err) {\n console.warn('[chat.pty.start] buildCliSystemContext failed:', (err as Error).message);\n }\n }\n\n // Inject flagged variables from the active environment into the AI\n // process env (opt-in per variable via `injectIntoAi`).\n const injectedEnv = await resolveInjectedEnv(input.environmentId);\n\n const res = await agentManager.agentMutation<{ spawnId: string }>(\n agentId,\n 'ai.spawnPty',\n {\n cli,\n args,\n env: injectedEnv,\n cwd: input.cwd,\n cols: input.cols,\n rows: input.rows,\n sessionId: input.sessionId,\n enableMcp: input.enableMcp,\n mcpApiBaseUrl: input.apiBaseUrl ?? `http://localhost:${env.PORT}`,\n mcpApiToken: jwt,\n },\n );\n\n const contexts = input.attachedContexts ?? [];\n if (contexts.length > 0) {\n const body = contexts\n .map((c) => `### ${c.label}\\n${c.text}`)\n .join('\\n\\n');\n // Bracketed paste: Claude's TUI collapses this to \"[Pasted text #N +X lines]\"\n // but keeps the full content in the message it sends.\n const injection = `\\x1b[200~---------\\nContext:\\n\\x1b[201~\\x1b[200~${body}\\x1b[201~\\x1b[200~\\n---------\\n\\x1b[201~`;\n\n const doInject = (): void => {\n agentManager\n .agentMutation(agentId, 'ai.writePty', { spawnId: res.spawnId, data: injection })\n .catch((err) => {\n console.warn('[chat.pty.start] deferred context writePty failed:', (err as Error).message);\n });\n };\n\n // There is no explicit \"ready for input\" signal from Claude Code or\n // Codex, so we combine a floor with output-quiescence detection:\n // - MIN_MS: never inject before this — the known-good fixed delay that\n // guarantees the TUI has reached its input prompt (a plain quiescence\n // check alone can fire during an early boot pause and drop the paste,\n // which is what broke larger contexts like logs).\n // - then wait for a quiet gap (no new bytes) so a slow boot pushes the\n // injection later rather than earlier.\n // - MAX_MS: hard safety net if output never settles (blinking cursor).\n const startedAt = Date.now();\n const MIN_MS = input.runner === 'codex' ? 500 : 1200;\n const QUIET_MS = 400;\n const MAX_MS = 8000;\n let injected = false;\n let quietTimer: ReturnType<typeof setTimeout> | null = null;\n let maxTimer: ReturnType<typeof setTimeout> | null = null;\n let unsub: (() => void) | null = null;\n const cleanup = (): void => {\n if (quietTimer) clearTimeout(quietTimer);\n if (maxTimer) clearTimeout(maxTimer);\n unsub?.();\n };\n const inject = (): void => {\n if (injected) return;\n injected = true;\n cleanup();\n doInject();\n };\n const scheduleQuiet = (): void => {\n if (quietTimer) clearTimeout(quietTimer);\n const wait = Math.max(QUIET_MS, MIN_MS - (Date.now() - startedAt));\n quietTimer = setTimeout(inject, wait);\n };\n maxTimer = setTimeout(inject, MAX_MS);\n unsub = agentManager.agentSubscribe(\n agentId,\n 'ai.stream',\n { spawnId: res.spawnId, fromOffset: 0 },\n (data: unknown) => {\n const chunk = (data as { chunk?: { type?: string } }).chunk;\n if (chunk?.type === 'exit') { injected = true; cleanup(); return; } // process gone\n scheduleQuiet();\n },\n () => { /* stream ended before ready — nothing to inject into */ },\n );\n }\n\n return { spawnId: res.spawnId, agentId, reattached: false };\n }),\n\n /** Subscribe to PTY output stream (raw text with ANSI). */\n stream: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128).optional(),\n spawnId: z.string().max(128),\n fromOffset: z.number().int().min(0).default(0),\n }))\n .subscription(async function* ({ input, signal }) {\n const agentId = input.agentId ?? agentManager.getDefaultAgentId();\n if (!agentId) throw new TRPCError({ code: 'PRECONDITION_FAILED', message: 'No agent available' });\n\n const queue: Array<{ offset: number; chunk: { type: string; data: string; code?: number } }> = [];\n let resolve: (() => void) | null = null;\n let stopped = false;\n\n const unsub = agentManager.agentSubscribe(\n agentId,\n 'ai.stream',\n { spawnId: input.spawnId, fromOffset: input.fromOffset },\n (data: unknown) => {\n queue.push(data as { offset: number; chunk: { type: string; data: string; code?: number } });\n if (resolve) { resolve(); resolve = null; }\n },\n () => { stopped = true; if (resolve) { resolve(); resolve = null; } },\n );\n\n try {\n while (!signal?.aborted && !stopped) {\n while (queue.length > 0) {\n const item = queue.shift()!;\n yield item;\n if (item.chunk.type === 'exit') { stopped = true; break; }\n }\n if (stopped) break;\n await new Promise<void>((r) => { resolve = r; });\n }\n } finally {\n unsub();\n }\n }),\n\n /** Write input to a PTY session (keystrokes from xterm). */\n write: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128).optional(),\n spawnId: z.string().max(128),\n data: z.string().max(1_000_000),\n }))\n .mutation(async ({ input }) => {\n const agentId = input.agentId ?? agentManager.getDefaultAgentId();\n if (!agentId) throw new TRPCError({ code: 'PRECONDITION_FAILED', message: 'No agent available' });\n return agentManager.agentMutation<{ ok: boolean }>(agentId, 'ai.writePty', {\n spawnId: input.spawnId,\n data: input.data,\n });\n }),\n\n /** Resize a PTY session. */\n resize: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128).optional(),\n spawnId: z.string().max(128),\n cols: z.number().int().min(1).max(1000),\n rows: z.number().int().min(1).max(1000),\n }))\n .mutation(async ({ input }) => {\n const agentId = input.agentId ?? agentManager.getDefaultAgentId();\n if (!agentId) throw new TRPCError({ code: 'PRECONDITION_FAILED', message: 'No agent available' });\n return agentManager.agentMutation<{ ok: boolean }>(agentId, 'ai.resizePty', {\n spawnId: input.spawnId,\n cols: input.cols,\n rows: input.rows,\n });\n }),\n\n /**\n * Upload a pasted image to the agent. The agent saves it to a tmp file and\n * tries to populate its system clipboard so Claude's native paste detection\n * picks it up. Returns the tmp path and which clipboard method succeeded\n * (null if none — caller should inject `@<path>` instead of Ctrl+V).\n */\n pasteImage: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128).optional(),\n sessionId: z.string().max(128).optional(),\n mimeType: z.string().max(64),\n base64: z.string().max(15_000_000),\n }))\n .mutation(async ({ input }) => {\n const agentId = input.agentId ?? agentManager.getDefaultAgentId();\n if (!agentId) throw new TRPCError({ code: 'PRECONDITION_FAILED', message: 'No agent available' });\n const res = await agentManager.agentMutation<{\n tmpPath: string;\n clipboardMethod: 'xclip' | 'wl-copy' | 'pbcopy' | 'powershell' | null;\n clipboardError?: string;\n }>(agentId, 'ai.pasteImage', {\n sessionId: input.sessionId,\n mimeType: input.mimeType,\n base64: input.base64,\n });\n if (!res.clipboardMethod) {\n console.warn('[chat.pty.pasteImage] clipboard spoof failed, using @path fallback:', res.clipboardError);\n }\n return res;\n }),\n\n /**\n * Read the transcript Claude Code stores on disk for a given session.\n * Returns parsed JSONL entries (user / assistant messages, tool uses, etc.).\n */\n transcript: protectedProcedure\n .input(z.object({ sessionId: z.string().max(128) }))\n .query(async ({ input }) => {\n return readClaudeTranscript(input.sessionId);\n }),\n\n /**\n * Lightweight liveness probe: is a PTY running for this session, and\n * when was the transcript JSONL last touched? Used by the non-PTY view\n * to show a \"Claude is thinking…\" indicator while output streams.\n */\n activity: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128).optional(),\n sessionId: z.string().max(128),\n }))\n .query(async ({ input }) => {\n const agentId = input.agentId ?? agentManager.getDefaultAgentId();\n let running = false;\n let lastChunkAt: number | null = null;\n if (agentId) {\n try {\n const existing = await agentManager.agentQuery<{ spawnId: string; status: string; lastChunkAt: number | null } | null>(\n agentId,\n 'ai.findPtyBySession',\n { sessionId: input.sessionId },\n );\n running = existing?.status === 'running';\n lastChunkAt = existing?.lastChunkAt ?? null;\n } catch {\n // agent unreachable — treat as not running\n }\n }\n // PTY data (every byte streamed by the agent) is the most accurate\n // signal; JSONL writes are a coarser fallback if the agent didn't\n // surface a chunk timestamp yet.\n const transcriptActivityAt = getLastTranscriptActivity(input.sessionId);\n const lastActivityAt = lastChunkAt && transcriptActivityAt\n ? Math.max(lastChunkAt, transcriptActivityAt)\n : (lastChunkAt ?? transcriptActivityAt);\n return { running, lastActivityAt };\n }),\n\n /**\n * Convert the on-disk Claude transcript into Runeya Message[] and persist\n * them on the conversation, so the non-PTY chat view stays in sync.\n * Uses the conversation id as session id (PTY sessions are spawned that way).\n */\n syncTranscript: protectedProcedure\n .input(z.object({ conversationId: ConversationIdSchema }))\n .mutation(async ({ input }) => {\n const conv = await conversationStore.get(input.conversationId);\n if (!conv) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Conversation ${input.conversationId} not found` });\n }\n const synced = await syncConversationFromClaudeTranscript(conv.id);\n const after = await conversationStore.get(conv.id);\n return { synced, messageCount: after?.messages.length ?? 0 };\n }),\n\n /**\n * Debug-only: spawn a PTY that emits random data at a chosen rate, tagged\n * with the given sessionId. Used to benchmark the PTY → tRPC → xterm.js\n * pipeline. Open the conversation in PTY mode to attach to it.\n */\n debugStress: protectedProcedure\n .input(z.object({\n sessionId: z.string().max(128),\n agentId: z.string().max(128).optional(),\n bytesPerSec: z.number().int().min(100).max(10_000_000).default(50_000),\n chunkSize: z.number().int().min(1).max(65_536).default(256),\n durationMs: z.number().int().min(0).max(3_600_000).default(0),\n cols: z.number().int().min(1).max(1000).default(120),\n rows: z.number().int().min(1).max(1000).default(30),\n }))\n .mutation(async ({ input }) => {\n const agentId = input.agentId ?? agentManager.getDefaultAgentId();\n if (!agentId) throw new TRPCError({ code: 'PRECONDITION_FAILED', message: 'No agent available' });\n\n // Use a synthetic sessionId so we don't collide with the conversation's\n // real Claude PTY — that would make the overlay re-attach to Claude\n // instead of the stress generator.\n const stressSessionId = `${input.sessionId}-stress-${Date.now().toString(36)}`;\n\n // Resolve the script. Try a few likely locations because import.meta.url\n // depth depends on whether the server runs from src (dev) or dist (prod\n // bundle) and tsup can split into chunks.\n const { existsSync } = await import('node:fs');\n const candidates = [\n new URL('../../../../scripts/pty-stress-gen.mjs', import.meta.url),\n new URL('../../../../../scripts/pty-stress-gen.mjs', import.meta.url),\n new URL('../../../scripts/pty-stress-gen.mjs', import.meta.url),\n ];\n let scriptPath: string | null = null;\n for (const c of candidates) {\n const p = fileURLToPath(c);\n if (existsSync(p)) { scriptPath = p; break; }\n }\n if (!scriptPath) {\n throw new TRPCError({\n code: 'INTERNAL_SERVER_ERROR',\n message: `pty-stress-gen.mjs not found near ${fileURLToPath(import.meta.url)}`,\n });\n }\n const res = await agentManager.agentMutation<{ spawnId: string }>(\n agentId,\n 'ai.spawnPty',\n {\n cli: 'node',\n args: [scriptPath],\n cwd: process.cwd(),\n cols: input.cols,\n rows: input.rows,\n sessionId: stressSessionId,\n env: {\n BYTES_PER_SEC: String(input.bytesPerSec),\n CHUNK_SIZE: String(input.chunkSize),\n DURATION_MS: String(input.durationMs),\n },\n },\n );\n return { spawnId: res.spawnId, agentId, stressSessionId };\n }),\n\n /** Kill a PTY session. */\n kill: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128).optional(),\n spawnId: z.string().max(128),\n }))\n .mutation(async ({ input }) => {\n const agentId = input.agentId ?? agentManager.getDefaultAgentId();\n if (!agentId) throw new TRPCError({ code: 'PRECONDITION_FAILED', message: 'No agent available' });\n return agentManager.agentMutation<{ ok: boolean }>(agentId, 'ai.kill', {\n spawnId: input.spawnId,\n });\n }),\n }),\n});\n","// ─── Runeya AI Capabilities — Single Source of Truth ─────────────────────────\n//\n// Adding a new capability:\n// 1. Add an entry to RUNEYA_CAPABILITIES below.\n// 2. Done. Anthropic tools, OpenAI tools, runner prompt docs, and MCP routes\n// are all generated automatically from this list.\n\nexport interface CapabilityParam {\n name: string;\n description: string;\n required: boolean;\n}\n\nexport interface RuneyaCapability {\n /** Tool name (snake_case, used as function name by LLMs). */\n name: string;\n /** Human-readable description shown to the LLM. */\n description: string;\n /** tRPC route segment, e.g. \"service.list\" or \"process.start\". */\n route: string;\n /** HTTP method for the tRPC call. */\n method: 'GET' | 'POST';\n /** Input parameters exposed to the LLM. */\n params: CapabilityParam[];\n /** Build the tRPC input object from raw LLM params. */\n buildInput: (params: Record<string, string | undefined>) => Record<string, unknown> | undefined;\n /** If true, safety instructions will warn the LLM to require explicit user intent. */\n destructive?: boolean;\n /**\n * Optional usage hint injected into the system prompt so the LLM knows when to use this tool.\n * Example: '\"wait 5s\" or \"pause for 10 seconds\" → call wait'\n */\n usageHint?: string;\n}\n\nexport const RUNEYA_CAPABILITIES: RuneyaCapability[] = [\n {\n name: 'list_services',\n description: 'List all available services. Returns serviceId and agentId for each — use these exact fields in other calls.',\n route: 'service.list',\n method: 'GET',\n params: [],\n buildInput: () => undefined,\n },\n {\n name: 'get_service_status',\n description: 'Get the current status (running, stopped, etc.) of a service.',\n route: 'process.get',\n method: 'GET',\n params: [\n { name: 'serviceId', description: 'The service ID', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, id: p.serviceId }),\n },\n {\n name: 'get_logs',\n description: 'Get the recent buffered logs for a service.',\n route: 'process.logs',\n method: 'GET',\n params: [\n { name: 'serviceId', description: 'The service ID', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),\n },\n {\n name: 'start_service',\n description: 'Start a service on an agent.',\n route: 'process.start',\n method: 'POST',\n params: [\n { name: 'serviceId', description: 'The service ID to start', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),\n destructive: true,\n },\n {\n name: 'stop_service',\n description: 'Stop a running service on an agent.',\n route: 'process.stop',\n method: 'POST',\n params: [\n { name: 'serviceId', description: 'The service ID to stop', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),\n destructive: true,\n },\n {\n name: 'restart_service',\n description: 'Restart a service on an agent (stop → redeploy → start).',\n route: 'process.restart',\n method: 'POST',\n params: [\n { name: 'serviceId', description: 'The service ID to restart', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),\n destructive: true,\n },\n\n // ─── Utility ─────────────────────────────────────────────────────────────\n\n {\n name: 'wait',\n description: 'Wait for a given number of milliseconds before continuing.',\n route: 'utility.wait',\n method: 'POST',\n params: [\n { name: 'ms', description: 'Number of MILLISECONDS to wait. Convert from seconds: 1s=1000, 10s=10000, 1min=60000. Max 300000.', required: true },\n ],\n buildInput: (p) => ({ ms: Number(p.ms) }),\n usageHint: '\"wait 5s\" → wait(ms=5000), \"pause 10 seconds\" → wait(ms=10000), \"attends 3 secondes\" → wait(ms=3000). Always convert to milliseconds.',\n },\n\n // ─── Kanban ───────────────────────────────────────────────────────────────\n\n {\n name: 'kanban_move_card',\n description: 'Move a kanban card to another column. Use the exact column name.',\n route: 'kanban.moveCard',\n method: 'POST',\n params: [\n { name: 'boardId', description: 'The kanban board ID', required: true },\n { name: 'cardId', description: 'The card ID to move', required: true },\n { name: 'targetColumn', description: 'Exact name of the target column', required: true },\n ],\n buildInput: (p) => ({ boardId: p.boardId, cardId: p.cardId, targetColumn: p.targetColumn }),\n },\n {\n name: 'kanban_add_comment',\n description: 'Add a comment to a kanban card.',\n route: 'kanban.addComment',\n method: 'POST',\n params: [\n { name: 'boardId', description: 'The kanban board ID', required: true },\n { name: 'cardId', description: 'The card ID', required: true },\n { name: 'comment', description: 'The comment text (markdown supported)', required: true },\n ],\n buildInput: (p) => ({ boardId: p.boardId, cardId: p.cardId, comment: p.comment }),\n },\n {\n name: 'kanban_add_card',\n description: 'Add a new card to a kanban column.',\n route: 'kanban.addCard',\n method: 'POST',\n params: [\n { name: 'boardId', description: 'The kanban board ID', required: true },\n { name: 'column', description: 'Exact name of the target column', required: true },\n { name: 'title', description: 'Card title', required: true },\n { name: 'content', description: 'Card content in markdown', required: false },\n ],\n buildInput: (p) => ({ boardId: p.boardId, column: p.column, title: p.title, content: p.content }),\n },\n];\n","import type { RuneyaCapability } from '../capabilities.js';\n\nexport interface AnthropicTool {\n name: string;\n description: string;\n input_schema: {\n type: 'object';\n properties: Record<string, { type: string; description: string }>;\n required: string[];\n [k: string]: unknown;\n };\n}\n\nexport function buildAnthropicTools(capabilities: RuneyaCapability[]): AnthropicTool[] {\n return capabilities.map(cap => ({\n name: cap.name,\n description: cap.description,\n input_schema: {\n type: 'object' as const,\n properties: Object.fromEntries(\n cap.params.map(p => [p.name, { type: 'string', description: p.description }]),\n ),\n required: cap.params.filter(p => p.required).map(p => p.name),\n },\n }));\n}\n","import type { RuneyaCapability } from '../capabilities.js';\n\nexport interface OpenAITool {\n type: 'function';\n function: {\n name: string;\n description: string;\n parameters: {\n type: 'object';\n properties: Record<string, { type: string; description: string }>;\n required: string[];\n };\n };\n}\n\nexport function buildOpenAITools(capabilities: RuneyaCapability[]): OpenAITool[] {\n return capabilities.map(cap => ({\n type: 'function' as const,\n function: {\n name: cap.name,\n description: cap.description,\n parameters: {\n type: 'object' as const,\n properties: Object.fromEntries(\n cap.params.map(p => [p.name, { type: 'string', description: p.description }]),\n ),\n required: cap.params.filter(p => p.required).map(p => p.name),\n },\n },\n }));\n}\n","import type { RuneyaCapability } from '../capabilities.js';\nexport type { RuneyaCapability };\n\n/**\n * Build the tool safety instruction block injected into cloud provider system prompts.\n * Generated from capabilities so it stays in sync automatically.\n */\nexport function buildToolSafetyInstruction(capabilities: RuneyaCapability[]): string {\n const destructive = capabilities.filter(c => c.destructive).map(c => c.name);\n const withHints = capabilities.filter(c => c.usageHint);\n\n const lines = ['## Tool use safety rules'];\n\n if (destructive.length > 0) {\n lines.push(`CRITICAL: Never call ${destructive.join(', ')} unless the user has EXPLICITLY and UNAMBIGUOUSLY requested it.`);\n lines.push(`- Only call destructive tools (${destructive.join(', ')}) when the user explicitly uses action words for a specific service.`);\n }\n\n if (withHints.length > 0) {\n lines.push('');\n lines.push('## Tool usage hints');\n for (const cap of withHints) {\n lines.push(`- ${cap.usageHint}`);\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Build a markdown documentation block injected into runner system prompts.\n * Runners (ClaudeCodeRunner, CodexRunner) use this to know how to call the Runeya API.\n *\n * The generated doc is the single source of truth for all runner-facing API docs —\n * no need to maintain a separate runeya-api-docs.ts.\n */\nexport function buildPromptDocs(baseUrl: string, token: string, capabilities: RuneyaCapability[]): string {\n if (!token) return '';\n\n const lines: string[] = [\n '## Runeya API',\n '',\n `Tu peux interagir avec Runeya via l'API HTTP tRPC ci-dessous.`,\n `Base URL : ${baseUrl}/api/trpc`,\n 'Auth header : Authorization: Bearer $RUNEYA_API_TOKEN',\n '',\n ];\n\n const gets = capabilities.filter(c => c.method === 'GET');\n const posts = capabilities.filter(c => c.method === 'POST');\n\n if (gets.length > 0) {\n lines.push('### GET routes (paramètres en query string ?input=<JSON encodé>)', '');\n for (const cap of gets) {\n const example = cap.params.length > 0\n ? `?input=${JSON.stringify(Object.fromEntries(cap.params.map(p => [p.name === 'serviceId' ? 'id' : p.name, '...'])))}`\n : '';\n lines.push(`- \\`${cap.route}${example}\\` — ${cap.description}`);\n }\n lines.push('');\n }\n\n if (posts.length > 0) {\n lines.push('### POST routes (body JSON)', '');\n for (const cap of posts) {\n const bodyExample = cap.params.length > 0\n ? JSON.stringify(Object.fromEntries(cap.params.map(p => [p.name === 'serviceId' ? 'processId' : p.name, '...'])))\n : '{}';\n lines.push(`- \\`${cap.route}\\` — \\`${bodyExample}\\``);\n }\n lines.push('');\n }\n\n const hints = capabilities.filter(c => c.usageHint);\n if (hints.length > 0) {\n lines.push('### Usage hints', '');\n for (const cap of hints) {\n lines.push(`- ${cap.usageHint}`);\n }\n lines.push('');\n }\n\n lines.push(\n '### Exemple curl',\n '',\n '```bash',\n `curl -H \"Authorization: Bearer $RUNEYA_API_TOKEN\" \\\\`,\n ` \"${baseUrl}/api/trpc/service.list\"`,\n '',\n `curl -X POST -H \"Authorization: Bearer $RUNEYA_API_TOKEN\" \\\\`,\n ' -H \"Content-Type: application/json\" \\\\',\n ` -d '{\"agentId\":\"local\",\"processId\":\"my-service\"}' \\\\`,\n ` \"${baseUrl}/api/trpc/process.start\"`,\n '```',\n '',\n 'La réponse est de la forme `{\"result\":{\"data\":<résultat>}}`.',\n );\n\n return lines.join('\\n');\n}\n","/**\n * Shared tRPC HTTP caller used by:\n * - Server-side cloud tool executor (proxies cloud LLM tool calls to local tRPC)\n * - MCP server (calls tRPC on behalf of CLI runners)\n */\nexport async function callTrpc(\n baseUrl: string,\n route: string,\n method: 'GET' | 'POST',\n input: Record<string, unknown> | undefined,\n authToken: string,\n): Promise<unknown> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${authToken}`,\n };\n\n const url = method === 'GET' && input\n ? `${baseUrl}/api/trpc/${route}?input=${encodeURIComponent(JSON.stringify(input))}`\n : `${baseUrl}/api/trpc/${route}`;\n\n const res = await fetch(url, {\n method,\n headers,\n ...(method === 'POST' ? { body: JSON.stringify(input ?? {}) } : {}),\n signal: AbortSignal.timeout(15_000),\n });\n\n const json = await res.json() as Record<string, unknown>;\n if (json['error']) throw new Error(JSON.stringify(json['error']));\n const result = json['result'] as Record<string, unknown> | undefined;\n return result?.['data'] ?? result ?? json;\n}\n","import { RUNEYA_CAPABILITIES, buildPromptDocs } from '@runeya/packages-ai-capabilities';\n\nexport function buildApiDocs(apiBaseUrl: string, apiToken: string): string {\n return buildPromptDocs(apiBaseUrl, apiToken, RUNEYA_CAPABILITIES);\n}\n","import { readdir, access, readFile } from 'node:fs/promises';\nimport { watch, type FSWatcher } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { conversationStore, type Message, type MessagePart } from './conversation-store.js';\n\nexport interface ClaudeTranscriptEntry {\n type: string;\n uuid?: string;\n timestamp?: string;\n message?: {\n role?: string;\n content?: unknown;\n usage?: unknown;\n model?: string;\n };\n toolUseResult?: unknown;\n}\n\nconst PROJECTS_DIR = join(homedir(), '.claude', 'projects');\nconst DEFAULT_TITLES = new Set(['', 'New conversation', 'Nouvelle conversation']);\n\nexport async function findClaudeSessionFile(sessionId: string): Promise<string | null> {\n let entries: string[];\n try {\n entries = await readdir(PROJECTS_DIR);\n } catch {\n return null;\n }\n const filename = `${sessionId}.jsonl`;\n for (const dir of entries) {\n const candidate = join(PROJECTS_DIR, dir, filename);\n try {\n await access(candidate);\n return candidate;\n } catch {\n // try next\n }\n }\n return null;\n}\n\nexport async function claudeSessionExists(sessionId: string): Promise<boolean> {\n return (await findClaudeSessionFile(sessionId)) !== null;\n}\n\nexport async function readClaudeTranscript(sessionId: string): Promise<{\n found: boolean;\n path: string | null;\n entries: ClaudeTranscriptEntry[];\n}> {\n const path = await findClaudeSessionFile(sessionId);\n if (!path) return { found: false, path: null, entries: [] };\n const raw = await readFile(path, 'utf-8');\n const entries: ClaudeTranscriptEntry[] = [];\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue;\n try {\n entries.push(JSON.parse(line) as ClaudeTranscriptEntry);\n } catch {\n // skip malformed line\n }\n }\n return { found: true, path, entries };\n}\n\nfunction claudeEntriesToMessages(entries: ClaudeTranscriptEntry[]): Message[] {\n const messages: Message[] = [];\n const toolPartById = new Map<string, MessagePart & { type: 'tool' }>();\n\n for (const entry of entries) {\n if (entry.type !== 'user' && entry.type !== 'assistant') continue;\n const msg = entry.message;\n if (!msg) continue;\n const role: 'user' | 'assistant' =\n msg.role === 'user' || msg.role === 'assistant'\n ? msg.role\n : (entry.type as 'user' | 'assistant');\n const content = msg.content;\n\n const texts: string[] = [];\n const parts: MessagePart[] = [];\n let consumedByToolResult = false;\n\n if (typeof content === 'string') {\n texts.push(content);\n } else if (Array.isArray(content)) {\n for (const block of content) {\n if (typeof block === 'string') {\n texts.push(block);\n continue;\n }\n if (!block || typeof block !== 'object') continue;\n const b = block as {\n type?: string;\n text?: string;\n id?: string;\n name?: string;\n input?: Record<string, unknown>;\n tool_use_id?: string;\n content?: unknown;\n is_error?: boolean;\n };\n if (b.type === 'text' && typeof b.text === 'string') {\n texts.push(b.text);\n parts.push({ type: 'text', text: b.text });\n } else if (b.type === 'tool_use' && b.id) {\n const part: MessagePart & { type: 'tool' } = {\n type: 'tool',\n id: b.id,\n name: b.name ?? 'tool',\n input: b.input,\n pending: true,\n };\n parts.push(part);\n toolPartById.set(b.id, part);\n } else if (b.type === 'tool_result' && b.tool_use_id) {\n const target = toolPartById.get(b.tool_use_id);\n if (target) {\n target.result = b.content;\n target.isError = b.is_error;\n target.pending = false;\n }\n consumedByToolResult = true;\n }\n }\n }\n\n if (role === 'user' && consumedByToolResult && texts.length === 0) continue;\n\n // Merge into the previous message when it has the same role — Claude\n // emits one transcript entry per assistant turn (text / tool_use /\n // tool_result), so consecutive assistant entries are part of the same\n // logical reply and should render as one bubble.\n const last = messages[messages.length - 1];\n if (last && last.role === role) {\n const joinedText = [last.content, texts.join('\\n').trim()]\n .filter(Boolean)\n .join('\\n');\n last.content = joinedText;\n if (parts.length > 0) {\n last.parts = [...(last.parts ?? []), ...parts];\n }\n continue;\n }\n\n messages.push({\n role,\n content: texts.join('\\n').trim(),\n parts: parts.length > 0 ? parts : undefined,\n });\n }\n\n return messages;\n}\n\n/**\n * Sync a Runeya conversation with its on-disk Claude JSONL transcript.\n * Skips if nothing changed; derives title from first user message on first sync.\n * Returns true when the conversation was actually updated.\n */\nexport async function syncConversationFromClaudeTranscript(conversationId: string): Promise<boolean> {\n const conv = await conversationStore.get(conversationId);\n if (!conv) return false;\n const transcript = await readClaudeTranscript(conversationId);\n if (!transcript.found) return false;\n\n const messages = claudeEntriesToMessages(transcript.entries);\n const isDefaultTitle = !conv.title || DEFAULT_TITLES.has(conv.title);\n\n const sameLength = messages.length === conv.messages.length;\n const sameLastContent =\n sameLength && (messages.at(-1)?.content ?? '') === (conv.messages.at(-1)?.content ?? '');\n if (sameLength && sameLastContent && !isDefaultTitle) {\n return false;\n }\n\n const patch: { messages: Message[]; title?: string } = { messages };\n if (isDefaultTitle) {\n const firstUserMsg = messages.find((m) => m.role === 'user' && m.content.trim().length > 0);\n if (firstUserMsg) {\n const firstLine = firstUserMsg.content.split('\\n')[0].trim();\n patch.title = firstLine.length > 80 ? firstLine.slice(0, 80) + '…' : firstLine;\n }\n }\n\n await conversationStore.update(conversationId, patch, { touch: false });\n return true;\n}\n\n// ─── Activity tracking ─────────────────────────────────────────────────────\n\n/** Last time we observed a write to a given session's JSONL. */\nconst lastTranscriptActivity = new Map<string, number>();\n\nexport function getLastTranscriptActivity(sessionId: string): number | null {\n return lastTranscriptActivity.get(sessionId) ?? null;\n}\n\n// ─── Realtime watcher ──────────────────────────────────────────────────────\n\nlet started = false;\nconst watchers: FSWatcher[] = [];\nconst pendingResyncs = new Map<string, NodeJS.Timeout>();\nconst RESYNC_DEBOUNCE_MS = 250;\n\nfunction scheduleResync(sessionId: string): void {\n const existing = pendingResyncs.get(sessionId);\n if (existing) clearTimeout(existing);\n pendingResyncs.set(\n sessionId,\n setTimeout(() => {\n pendingResyncs.delete(sessionId);\n syncConversationFromClaudeTranscript(sessionId).catch((err) => {\n console.warn('[claude-transcript-sync] resync failed for', sessionId, err);\n });\n }, RESYNC_DEBOUNCE_MS),\n );\n}\n\nfunction handleFsEvent(filename: string | null): void {\n if (!filename) return;\n if (!filename.endsWith('.jsonl')) return;\n // filename may be \"<projectDir>/<sessionId>.jsonl\" or just \"<sessionId>.jsonl\"\n const base = filename.split('/').pop()!;\n const sessionId = base.slice(0, -'.jsonl'.length);\n if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(sessionId)) return;\n lastTranscriptActivity.set(sessionId, Date.now());\n scheduleResync(sessionId);\n}\n\n/**\n * Watch ~/.claude/projects/ recursively. Whenever a `<sessionId>.jsonl` file\n * is touched, re-sync the matching Runeya conversation (if any) so the\n * non-PTY message view stays live.\n */\nexport async function startClaudeTranscriptWatcher(): Promise<void> {\n if (started) return;\n started = true;\n\n let topLevel: string[];\n try {\n topLevel = await readdir(PROJECTS_DIR);\n } catch {\n // ~/.claude/projects doesn't exist yet — watch parent for creation.\n return;\n }\n\n // Prefer a single recursive watcher when supported, otherwise watch each\n // project dir individually.\n try {\n const w = watch(PROJECTS_DIR, { recursive: true }, (_event, filename) => {\n handleFsEvent(filename ? filename.toString() : null);\n });\n w.on('error', (err) => console.warn('[claude-transcript-sync] watcher error:', err));\n watchers.push(w);\n return;\n } catch {\n // Fallback below.\n }\n\n for (const dir of topLevel) {\n try {\n const w = watch(join(PROJECTS_DIR, dir), (_event, filename) => {\n handleFsEvent(filename ? filename.toString() : null);\n });\n w.on('error', () => {});\n watchers.push(w);\n } catch {\n // ignore\n }\n }\n}\n\nexport function stopClaudeTranscriptWatcher(): void {\n for (const w of watchers) {\n try {\n w.close();\n } catch {\n // ignore\n }\n }\n watchers.length = 0;\n for (const t of pendingResyncs.values()) clearTimeout(t);\n pendingResyncs.clear();\n started = false;\n}\n","import { randomUUID } from 'node:crypto';\nimport { readFile, writeFile, rename, mkdir, chmod } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { EventEmitter } from 'node:events';\nimport { env } from '../config/env.js';\nimport { getEncryptionKey } from '../utils/encryption-key.js';\nimport { encryptValue, decryptValue } from './crypto-helpers.js';\n\nconst FILENAME = 'conversations.private.json';\n\n// ─── Types ─────────────────────────────────────────────────────────────────\n\nexport type MessagePart =\n | { type: 'thinking'; text: string }\n | { type: 'text'; text: string }\n | { type: 'tool'; id: string; name: string; input?: Record<string, unknown>; rawInput?: string; result?: unknown; isError?: boolean; pending: boolean }\n | { type: 'image'; imageId: string; url: string; mimeType: string; altText?: string };\n\nexport interface Message {\n role: 'user' | 'assistant';\n content: string;\n parts?: MessagePart[];\n contextNote?: string;\n}\n\ninterface ContextUsage {\n inputTokens: number;\n contextWindow: number;\n}\n\ntype WorkflowType = 'scenario';\n\nexport interface Conversation {\n id: string;\n title: string;\n messages: Message[];\n isCli: boolean;\n runner?: 'claude-code' | 'codex';\n providerId?: string;\n codexThreadId?: string;\n contextUsage?: ContextUsage;\n workflowId?: string;\n workflowType?: WorkflowType;\n kanbanBoardId?: string;\n kanbanCardId?: string;\n archived?: boolean;\n createdAt: number;\n updatedAt: number;\n}\n\n\nexport type ConversationChangeEvent =\n | { type: 'created'; conversation: Conversation }\n | { type: 'updated'; conversation: Conversation }\n | { type: 'deleted'; id: string };\n\ninterface ConversationOnDisk {\n id: string;\n title: string;\n encryptedMessages: string;\n isCli?: boolean;\n isClaudeCode?: boolean;\n runner?: 'claude-code' | 'codex';\n providerId?: string;\n codexThreadId?: string;\n contextUsage?: ContextUsage;\n workflowId?: string;\n workflowType?: WorkflowType;\n kanbanBoardId?: string;\n kanbanCardId?: string;\n // Legacy field from before workflowType was introduced — used only for migration in fromDisk\n scenarioId?: string;\n archived?: boolean;\n createdAt: number;\n updatedAt: number;\n}\n\n// ─── Store ─────────────────────────────────────────────────────────────────\n\nclass ConversationStore {\n private conversations: Map<string, Conversation> = new Map();\n private loaded = false;\n private readonly events = new EventEmitter();\n private saveQueue: Promise<void> = Promise.resolve();\n\n private snapshotConversation(conv: Conversation): Conversation {\n return structuredClone(conv);\n }\n\n private getFilePath(): string {\n return join(env.DATA_DIR, FILENAME);\n }\n\n private async ensureDir(): Promise<void> {\n await mkdir(env.DATA_DIR, { recursive: true });\n }\n\n private encryptMessages(messages: Message[]): string {\n return encryptValue(JSON.stringify(messages));\n }\n\n private decryptMessages(encrypted: string): Message[] {\n const json = decryptValue(encrypted);\n return JSON.parse(json) as Message[];\n }\n\n private toDisk(conv: Conversation): ConversationOnDisk {\n return {\n id: conv.id,\n title: conv.title,\n encryptedMessages: this.encryptMessages(conv.messages),\n isCli: conv.isCli,\n runner: conv.runner,\n providerId: conv.providerId,\n codexThreadId: conv.codexThreadId,\n contextUsage: conv.contextUsage,\n workflowId: conv.workflowId,\n workflowType: conv.workflowType,\n kanbanBoardId: conv.kanbanBoardId,\n kanbanCardId: conv.kanbanCardId,\n archived: conv.archived,\n createdAt: conv.createdAt,\n updatedAt: conv.updatedAt,\n };\n }\n\n private fromDisk(disk: ConversationOnDisk): Conversation {\n // Derive workflowType from legacy fields for conversations created before this field existed\n const workflowType: WorkflowType | undefined =\n (disk.workflowType === 'scenario' ? 'scenario' : undefined)\n ?? (disk.scenarioId ? 'scenario' : undefined);\n\n return {\n id: disk.id,\n title: disk.title,\n messages: this.decryptMessages(disk.encryptedMessages),\n isCli: disk.isCli ?? disk.isClaudeCode ?? false,\n runner: disk.runner,\n providerId: disk.providerId,\n codexThreadId: disk.codexThreadId,\n contextUsage: disk.contextUsage,\n workflowId: disk.workflowId ?? disk.scenarioId,\n workflowType,\n kanbanBoardId: disk.kanbanBoardId,\n kanbanCardId: disk.kanbanCardId,\n archived: disk.archived,\n createdAt: disk.createdAt,\n updatedAt: disk.updatedAt,\n };\n }\n\n private async load(): Promise<void> {\n if (this.loaded) return;\n if (!getEncryptionKey()) {\n return;\n }\n try {\n const raw = await readFile(this.getFilePath(), 'utf-8');\n const data: ConversationOnDisk[] = JSON.parse(raw);\n for (const item of data) {\n try {\n this.conversations.set(item.id, this.fromDisk(item));\n } catch {\n // Skip corrupted entries\n }\n }\n } catch {\n // File doesn't exist yet — start empty\n }\n this.loaded = true;\n }\n\n private async saveInternal(): Promise<void> {\n await this.ensureDir();\n if (!getEncryptionKey()) return;\n const data: ConversationOnDisk[] = Array.from(this.conversations.values()).map(c => this.toDisk(c));\n const filePath = this.getFilePath();\n const tmpPath = `${filePath}.tmp`;\n await writeFile(tmpPath, JSON.stringify(data, null, 2), 'utf-8');\n await rename(tmpPath, filePath);\n await chmod(filePath, 0o600);\n }\n\n private async save(): Promise<void> {\n const write = this.saveQueue.then(() => this.saveInternal());\n this.saveQueue = write.catch(() => {});\n return write;\n }\n\n async list(): Promise<Conversation[]> {\n await this.load();\n return Array.from(this.conversations.values())\n .sort((a, b) => b.updatedAt - a.updatedAt);\n }\n\n async get(id: string): Promise<Conversation | null> {\n await this.load();\n return this.conversations.get(id) ?? null;\n }\n\n async create(title?: string, isCli = false, workflowId?: string, workflowType?: WorkflowType, runner?: 'claude-code' | 'codex', kanbanBoardId?: string, kanbanCardId?: string, providerId?: string): Promise<Conversation> {\n await this.load();\n const now = Date.now();\n const conv: Conversation = {\n id: randomUUID(),\n title: title ?? 'New conversation',\n messages: [],\n isCli,\n runner,\n providerId,\n workflowId,\n workflowType,\n kanbanBoardId,\n kanbanCardId,\n createdAt: now,\n updatedAt: now,\n };\n this.conversations.set(conv.id, conv);\n await this.save();\n this.events.emit('changed', { type: 'created', conversation: this.snapshotConversation(conv) } as ConversationChangeEvent);\n return conv;\n }\n\n async update(id: string, patch: { title?: string; messages?: Message[]; contextUsage?: ContextUsage; workflowId?: string; archived?: boolean; codexThreadId?: string }, options?: { silent?: boolean; touch?: boolean }): Promise<Conversation | null> {\n await this.load();\n const conv = this.conversations.get(id);\n if (!conv) return null;\n if (patch.title !== undefined) conv.title = patch.title;\n if (patch.messages !== undefined) conv.messages = patch.messages;\n if (patch.contextUsage !== undefined) conv.contextUsage = patch.contextUsage;\n if (patch.workflowId !== undefined) conv.workflowId = patch.workflowId;\n if (patch.archived !== undefined) conv.archived = patch.archived;\n if (patch.codexThreadId !== undefined) conv.codexThreadId = patch.codexThreadId;\n if (options?.touch !== false) conv.updatedAt = Date.now();\n await this.save();\n if (!options?.silent) {\n this.events.emit('changed', { type: 'updated', conversation: this.snapshotConversation(conv) } as ConversationChangeEvent);\n }\n return conv;\n }\n\n /**\n * Synchronously update the last assistant message content in memory, then schedule a save.\n * Used by activeSessionRegistry.persistNow() to avoid the async get() → .then() race.\n */\n updateLastAssistantContent(id: string, content: string, parts?: MessagePart[]): void {\n const conv = this.conversations.get(id);\n if (!conv) return;\n const lastMsg = conv.messages[conv.messages.length - 1];\n if (!lastMsg || lastMsg.role !== 'assistant') return;\n lastMsg.content = content;\n if (parts !== undefined) lastMsg.parts = parts;\n conv.updatedAt = Date.now();\n this.save().catch(() => {});\n }\n\n async listByKanbanBoardId(boardId: string): Promise<Conversation[]> {\n await this.load();\n return Array.from(this.conversations.values()).filter(c => c.kanbanBoardId === boardId);\n }\n\n async listByKanbanCardId(cardId: string): Promise<Conversation[]> {\n await this.load();\n return Array.from(this.conversations.values()).filter(c => c.kanbanCardId === cardId);\n }\n\n async delete(id: string): Promise<void> {\n await this.load();\n const existed = this.conversations.delete(id);\n await this.save();\n if (existed) {\n this.events.emit('changed', { type: 'deleted', id } as ConversationChangeEvent);\n }\n }\n\n onChanged(handler: (event: ConversationChangeEvent) => void): void {\n this.events.on('changed', handler);\n }\n\n offChanged(handler: (event: ConversationChangeEvent) => void): void {\n this.events.off('changed', handler);\n }\n}\n\nexport const conversationStore = new ConversationStore();\n","import { readdir } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nconst SESSIONS_DIR = join(homedir(), '.codex', 'sessions');\n\n/**\n * Codex persists each interactive session as a rollout file:\n * ~/.codex/sessions/<YYYY>/<MM>/<DD>/rollout-<ISO>-<sessionId>.jsonl\n *\n * The app-server reuses the same session id as the rollout file, so a\n * conversation's `codexThreadId` can be passed to `codex resume <id>` — but\n * only if the rollout actually exists on disk, otherwise the CLI errors out.\n */\nasync function findCodexSessionFile(sessionId: string): Promise<string | null> {\n // Filenames end with `-<sessionId>.jsonl`; scan the date-bucketed tree.\n const suffix = `-${sessionId}.jsonl`;\n async function walk(dir: string): Promise<string | null> {\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return null;\n }\n for (const entry of entries) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n const found = await walk(full);\n if (found) return found;\n } else if (entry.name.endsWith(suffix)) {\n return full;\n }\n }\n return null;\n }\n return walk(SESSIONS_DIR);\n}\n\nexport async function codexSessionExists(sessionId: string): Promise<boolean> {\n return (await findCodexSessionFile(sessionId)) !== null;\n}\n","import { z } from 'zod';\n\nexport const Id128Schema = z.string().max(128);\nexport const ConversationIdSchema = z.string().max(128);\nexport const NameSchema = z.string().min(1).max(200);\nexport const ShortString200Schema = z.string().max(200);\nexport const DescriptionSchema = z.string().max(2000);\nexport const OptionalProviderIdSchema = Id128Schema.optional();\n","import { env } from '../config/env.js';\nimport type { ApiKey, ApiServicePerm, ServiceConfig } from '@runeya/packages-shared';\n\n/**\n * Generate a llms.txt for a JWT-authenticated admin caller (full access, all services).\n * Pass a JWT so Claude Code can authenticate its HTTP calls against the Runeya API.\n */\nexport function generateAdminLlmsTxt(services: ServiceConfig[], jwt?: string): string {\n const baseUrl = `http://localhost:${env.PORT}`;\n const trpcBase = `${baseUrl}/api/trpc`;\n\n const lines: string[] = [];\n\n lines.push('# Runeya — Service Management API');\n lines.push('');\n lines.push('> You are operating as an authenticated admin with full access to all services.');\n lines.push(`> Base URL: ${trpcBase}`);\n if (jwt) {\n // Token is injected via RUNEYA_API_TOKEN env var — do not embed raw value in CLI args.\n lines.push('> Authentication: pass `Authorization: Bearer $RUNEYA_API_TOKEN` on all tRPC requests.');\n }\n lines.push('');\n\n if (services.length === 0) {\n lines.push('No services configured.');\n return lines.join('\\n');\n }\n\n lines.push('## Services');\n lines.push('');\n\n for (const svc of services) {\n lines.push(`### ${svc.name}`);\n lines.push(`- **ID**: \\`${svc.id}\\``);\n if (svc.agentId) lines.push(`- **Agent ID**: \\`${svc.agentId}\\``);\n if (svc.description) lines.push(`- **Description**: ${svc.description}`);\n if (svc.cwd) lines.push(`- **Working directory**: \\`${svc.cwd}\\``);\n lines.push('- **Permitted actions**: all');\n lines.push('');\n }\n\n lines.push('## MCP Tools');\n lines.push('');\n lines.push('You have access to Runeya MCP tools to manage services. **Always prefer MCP tools** over raw HTTP calls.');\n lines.push('Available tools: `list_services`, `get_service_status`, `start_service`, `stop_service`, `restart_service`, `get_logs`.');\n lines.push('');\n if (jwt) {\n lines.push('**Important**: Pass the `authToken` parameter with value `$RUNEYA_API_TOKEN` (from environment) on every MCP tool call for authentication.');\n lines.push('');\n }\n lines.push('Use the service IDs and agent IDs listed above when calling these tools.');\n lines.push('');\n\n lines.push('## API Reference (fallback)');\n lines.push('');\n lines.push('Only use raw HTTP calls if MCP tools are unavailable.');\n lines.push('All endpoints use tRPC v11 over HTTP (`Content-Type: application/json`).');\n lines.push('');\n lines.push('**tRPC v11 request format:**');\n lines.push('- **GET queries**: `?input={\"id\":\"abc\"}`');\n lines.push('- **POST mutations**: JSON body `{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}`');\n lines.push('');\n lines.push(`### List services\\n\\`GET ${trpcBase}/service.list\\``);\n lines.push('');\n lines.push(`### Get service\\n\\`GET ${trpcBase}/service.get?input={\"agentId\":\"<agentId>\",\"id\":\"<serviceId>\"}\\``);\n lines.push('');\n lines.push(`### Read logs\\n\\`GET ${trpcBase}/process.logs?input={\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}\\``);\n lines.push('');\n lines.push(`### Start service\\n\\`POST ${trpcBase}/process.start\\`\\nBody: \\`{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}\\``);\n lines.push('');\n lines.push(`### Stop service\\n\\`POST ${trpcBase}/process.stop\\`\\nBody: \\`{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}\\``);\n lines.push('');\n lines.push(`### Restart service\\n\\`POST ${trpcBase}/process.restart\\`\\nBody: \\`{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}\\``);\n lines.push('');\n lines.push(`### Get service status\\n\\`GET ${trpcBase}/process.status?input={\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}\\``);\n lines.push('');\n\n return lines.join('\\n');\n}\n\n/**\n * Generate a llms.txt document describing the available API endpoints\n * for this key's scopes. Services are pre-filtered by the caller.\n */\nexport function generateLlmsTxt(\n apiKey: ApiKey,\n services: ServiceConfig[],\n): string {\n const { scopes } = apiKey;\n const baseUrl = `http://localhost:${env.PORT}`;\n const trpcBase = `${baseUrl}/api/trpc`;\n\n const lines: string[] = [];\n\n lines.push('# Runeya — Service Management API');\n lines.push('');\n lines.push('> This file describes the API surface available for this key.');\n lines.push(`> Base URL: ${trpcBase}`);\n lines.push(`> Authentication: pass this key as \\`Authorization: Bearer ${apiKey.key}\\` on all tRPC requests.`);\n lines.push('');\n\n if (services.length === 0) {\n lines.push('No services accessible with this key.');\n return lines.join('\\n');\n }\n\n // Build a quick lookup: serviceId → permission\n const permByServiceId = new Map<string, ApiServicePerm>(\n scopes.services.map(p => [p.serviceId, p]),\n );\n\n // --- Services ---\n lines.push('## Services');\n lines.push('');\n\n for (const svc of services) {\n const perm = permByServiceId.get(svc.id);\n const actions = perm?.actions ?? [];\n\n lines.push(`### ${svc.name}`);\n lines.push(`- **ID**: \\`${svc.id}\\``);\n if (svc.agentId) lines.push(`- **Agent ID**: \\`${svc.agentId}\\``);\n if (svc.description) lines.push(`- **Description**: ${svc.description}`);\n if (svc.cwd) lines.push(`- **Working directory**: \\`${svc.cwd}\\``);\n\n lines.push('- **Permitted actions**:');\n if (actions.length === 0) {\n lines.push(' - _(none)_');\n } else {\n for (const a of actions) lines.push(` - \\`${a}\\``);\n }\n\n const envPerms = perm?.environments ?? [];\n if (envPerms.length > 0) {\n lines.push('- **Environment access**:');\n for (const ep of envPerms) {\n const envActions = ep.actions.join(', ');\n const secrets = ep.includeSecrets ? ' _(includes secrets)_' : '';\n lines.push(` - \\`${ep.environmentId}\\`: ${envActions}${secrets}`);\n }\n }\n\n lines.push('');\n }\n\n // --- API Reference ---\n lines.push('## API Reference');\n lines.push('');\n lines.push('All endpoints use tRPC v11 over HTTP (`Content-Type: application/json`).');\n lines.push('');\n lines.push('**Important — tRPC v11 request format:**');\n lines.push('- **GET queries**: pass input as a plain JSON-encoded string in the `input` query param (no `{\"json\":...}` wrapper).');\n lines.push(' Example: `?input={\"id\":\"abc\"}`');\n lines.push('- **POST mutations**: send the input object as a plain JSON body (no `{\"json\":...}` wrapper).');\n lines.push(' Example body: `{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}`');\n lines.push('- The `agentId` is listed per service above.');\n lines.push('- The `processId` is the same as the service `ID` listed above.');\n lines.push('');\n\n // Collect union of actions across all services for the reference section\n const allActions = new Set(scopes.services.flatMap(p => p.actions));\n const hasEnvRead = scopes.services.some(p => p.environments.some(e => e.actions.includes('env:read')));\n const hasEnvWrite = scopes.services.some(p => p.environments.some(e => e.actions.includes('env:write')));\n\n if (allActions.has('service:read')) {\n lines.push('### List services');\n lines.push(`\\`GET ${trpcBase}/service.list\\``);\n lines.push('');\n lines.push('### Get service');\n lines.push(`\\`GET ${trpcBase}/service.get?input={\"agentId\":\"<agentId>\",\"id\":\"<serviceId>\"}\\``);\n lines.push('');\n }\n\n if (allActions.has('logs:read')) {\n lines.push('### Read logs');\n lines.push(`\\`GET ${trpcBase}/process.logs?input={\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}\\``);\n lines.push('');\n }\n\n if (allActions.has('service:start')) {\n lines.push('### Start service');\n lines.push(`\\`POST ${trpcBase}/process.start\\``);\n lines.push('Body: `{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}`');\n lines.push('');\n }\n\n if (allActions.has('service:stop')) {\n lines.push('### Stop service');\n lines.push(`\\`POST ${trpcBase}/process.stop\\``);\n lines.push('Body: `{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}`');\n lines.push('');\n }\n\n if (allActions.has('service:restart')) {\n lines.push('### Restart service');\n lines.push(`\\`POST ${trpcBase}/process.restart\\``);\n lines.push('Body: `{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}`');\n lines.push('');\n }\n\n if (allActions.has('service:status')) {\n lines.push('### Get service status');\n lines.push(`\\`GET ${trpcBase}/process.status?input={\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}\\``);\n lines.push('');\n }\n\n if (allActions.has('service:healthcheck')) {\n lines.push('### Get service health');\n lines.push(`\\`GET ${trpcBase}/process.health?input={\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}\\``);\n lines.push('');\n }\n\n if (hasEnvRead) {\n lines.push('### Read environment variables (flat KEY=VALUE — secrets shown as *****)');\n lines.push(`\\`GET ${trpcBase}/environment.resolveFlat?input={\"environmentId\":\"<environmentId>\"}\\``);\n lines.push('Returns a flat `Record<string, string>`. Secret variables you are not authorized to see are shown as `*****`.');\n lines.push('');\n }\n\n if (hasEnvWrite) {\n lines.push('### Write environment variable');\n lines.push(`\\`POST ${trpcBase}/environment.upsertVariable\\``);\n lines.push('Body: `{\"environmentId\":\"<environmentId>\",\"key\":\"<key>\",\"value\":\"<value>\"}`');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n","import {\n RUNEYA_CAPABILITIES,\n buildAnthropicTools,\n buildOpenAITools,\n buildToolSafetyInstruction,\n callTrpc,\n} from '@runeya/packages-ai-capabilities';\nimport type { ApiKey, ApiServiceAction } from '@runeya/packages-shared';\nimport { env } from '../config/env.js';\n\n// ─── Tool definitions (generated from capabilities) ───────────────────────────\n\nexport const CHAT_TOOLS = buildAnthropicTools(RUNEYA_CAPABILITIES);\nexport const CHAT_TOOLS_OPENAI = buildOpenAITools(RUNEYA_CAPABILITIES);\nexport const TOOL_SAFETY_INSTRUCTION = buildToolSafetyInstruction(RUNEYA_CAPABILITIES);\n\n// ─── Scope check ──────────────────────────────────────────────────────────────\n\nfunction hasServiceAction(apiKey: ApiKey | null, serviceId: string, action: ApiServiceAction): boolean {\n if (!apiKey) return true; // JWT = full access\n const perm = apiKey.scopes.services.find(p => p.serviceId === serviceId);\n return perm?.actions.includes(action) ?? false;\n}\n\n// ─── Tool name normalization ─────────────────────────────────────────────────\n// Some models (Groq, Ollama, …) hallucinate suffixes like `<|channel|>commentary`\n// after the real tool name. Match against known names to recover gracefully.\n\nconst KNOWN_TOOL_NAMES = RUNEYA_CAPABILITIES.map(c => c.name);\n\nfunction normalizeToolName(raw: string): string {\n if (KNOWN_TOOL_NAMES.includes(raw)) return raw;\n const match = KNOWN_TOOL_NAMES.find(t => raw.startsWith(t));\n return match ?? raw;\n}\n\n// ─── Tool executor — proxies to local tRPC API ────────────────────────────────\n//\n// Cloud LLMs cannot reach localhost directly, so the server acts as a proxy:\n// cloud tool_call → executeTool() → HTTP → /api/trpc/...\n//\n// This keeps the execution path identical to what runners (ClaudeCode, Codex)\n// do when they call the API themselves.\n\nexport async function executeTool(\n rawName: string,\n input: Record<string, unknown>,\n apiKey: ApiKey | null,\n authToken: string,\n): Promise<unknown> {\n const name = normalizeToolName(rawName);\n const cap = RUNEYA_CAPABILITIES.find(c => c.name === name);\n if (!cap) throw new Error(`Unknown tool: ${name}`);\n\n // Scope check for service-level actions\n const serviceId = (input['serviceId'] ?? input['id'] ?? input['processId']) as string | undefined;\n if (serviceId) {\n const actionMap: Record<string, ApiServiceAction> = {\n get_service_status: 'service:status',\n get_logs: 'logs:read',\n start_service: 'service:start',\n stop_service: 'service:stop',\n restart_service: 'service:restart',\n };\n const action = actionMap[name];\n if (action && !hasServiceAction(apiKey, serviceId, action)) {\n throw new Error(`No '${action}' permission for service ${serviceId}`);\n }\n }\n\n const params = Object.fromEntries(\n Object.entries(input).map(([k, v]) => [\n k,\n v != null ? (typeof v === 'object' ? JSON.stringify(v) : String(v as string | number | boolean | bigint)) : undefined,\n ]),\n ) as Record<string, string | undefined>;\n\n const baseUrl = `http://localhost:${env.PORT}`;\n return callTrpc(baseUrl, cap.route, cap.method, cap.buildInput(params), authToken);\n}\n","import pty from 'node-pty';\nimport { execSync } from 'child_process';\n\nexport interface CliUsageEntry {\n label: string;\n percentage: number | null;\n next_reset: string | null;\n}\n\ninterface UsageEntry {\n percent: number | null;\n resetsAt: string | null;\n}\n\ninterface ExtraUsage extends UsageEntry {\n spent: number | null;\n limit: number | null;\n}\n\ninterface ClaudeUsage {\n current_session?: UsageEntry;\n current_week_all?: UsageEntry;\n current_week_sonnet?: UsageEntry;\n extra_usage?: ExtraUsage;\n}\n\nconst MONTHS: Record<string, number> = {\n jan: 0, feb: 1, mar: 2, apr: 3, may: 4, jun: 5,\n jul: 6, aug: 7, sep: 8, oct: 9, nov: 10, dec: 11,\n};\n\nfunction parseResetsAt(str: string): string {\n const tzMatch = str.match(/\\(([^)]+)\\)/);\n const tz = tzMatch?.[1] ?? 'UTC';\n const dateStr = str.replace(/\\([^)]+\\)/, '').replaceAll('·', '').trim();\n\n const withTime = dateStr.match(/^([A-Za-z]{3})(\\d+),(\\d+)(am|pm)$/i);\n const withoutTime = dateStr.match(/^([A-Za-z]{3})(\\d+)$/i);\n // Time-only format: \"7:59am\" or \"10am\" — means today/tomorrow in the given tz\n const timeOnly = dateStr.match(/^(\\d+)(?::(\\d+))?(am|pm)$/i);\n\n let month: number, day: number, hour = 0, minute = 0; // minute used for timeOnly format\n\n const year = new Date().getFullYear();\n\n if (withTime) {\n month = MONTHS[withTime[1].toLowerCase()] ?? 0;\n day = Number.parseInt(withTime[2]);\n hour = Number.parseInt(withTime[3]);\n if (withTime[4].toLowerCase() === 'pm' && hour !== 12) hour += 12;\n if (withTime[4].toLowerCase() === 'am' && hour === 12) hour = 0;\n } else if (withoutTime) {\n month = MONTHS[withoutTime[1].toLowerCase()] ?? 0;\n day = Number.parseInt(withoutTime[2]);\n } else if (timeOnly) {\n hour = Number.parseInt(timeOnly[1]);\n minute = timeOnly[2] ? Number.parseInt(timeOnly[2]) : 0;\n if (timeOnly[3].toLowerCase() === 'pm' && hour !== 12) hour += 12;\n if (timeOnly[3].toLowerCase() === 'am' && hour === 12) hour = 0;\n // Use today's local date in the target timezone\n const now = new Date();\n const parts = new Intl.DateTimeFormat('en', { timeZone: tz, year: 'numeric', month: '2-digit', day: '2-digit' }).formatToParts(now);\n month = Number.parseInt(parts.find(p => p.type === 'month')!.value) - 1;\n day = Number.parseInt(parts.find(p => p.type === 'day')!.value);\n } else {\n return str;\n }\n const approxUtc = new Date(Date.UTC(year, month, day, hour, 0));\n const offsetStr = new Intl.DateTimeFormat('en', {\n timeZone: tz,\n timeZoneName: 'shortOffset',\n }).formatToParts(approxUtc).find(p => p.type === 'timeZoneName')?.value ?? 'GMT+0';\n\n const offsetMatch = offsetStr.match(/GMT([+-])(\\d+)(?::(\\d+))?/);\n const sign = offsetMatch?.[1] === '-' ? -1 : 1;\n const offsetMinutes = sign * (Number.parseInt(offsetMatch?.[2] ?? '0') * 60 + Number.parseInt(offsetMatch?.[3] ?? '0'));\n\n const utc = new Date(Date.UTC(year, month, day, hour, minute) - offsetMinutes * 60000);\n return utc.toISOString();\n}\n\nfunction extractSection(text: string, startPattern: RegExp, endPattern: RegExp | null): string | null {\n const start = text.search(startPattern);\n if (start === -1) return null;\n const after = text.slice(start);\n const end = endPattern ? after.search(endPattern) : after.length;\n return end === -1 ? after : after.slice(0, end);\n}\n\nfunction extractPercent(section: string | null): number | null {\n const m = section?.match(/(\\d+)%\\s*used/i);\n return m ? Number.parseInt(m[1]) : null;\n}\n\nfunction extractResets(section: string | null): string | null {\n const m = section?.match(/Rese[ts]+\\s*(.+?)(?=Current|Extra|$)/is);\n return m ? m[1].replaceAll(/\\s+/g, ' ').trim() : null;\n}\n\nfunction parse(text: string): ClaudeUsage {\n // Flatten to single line for cross-line regex matching (handles Windows ConPTY output)\n const flat = text.replaceAll('\\n', ' ').replaceAll(/\\s+/g, ' ');\n const result: ClaudeUsage = {};\n\n const sessionSec = extractSection(flat, /Current\\s*session/i, /Current\\s*week|Extra\\s*usage/i);\n if (sessionSec) {\n const resets = extractResets(sessionSec);\n result.current_session = {\n percent: extractPercent(sessionSec),\n resetsAt: resets ? parseResetsAt(resets) : null,\n };\n }\n\n const weekAllSec = extractSection(flat, /Current\\s*week\\s*\\(all\\s*models?\\)/i, /Current\\s*week\\s*\\(Sonnet/i);\n if (weekAllSec) {\n const resets = extractResets(weekAllSec);\n result.current_week_all = {\n percent: extractPercent(weekAllSec),\n resetsAt: resets ? parseResetsAt(resets) : null,\n };\n }\n\n const weekSonnetSec = extractSection(flat, /Current\\s*week\\s*\\(Sonnet\\s*only\\)/i, /Extra\\s*usage/i);\n if (weekSonnetSec) {\n const resets = extractResets(weekSonnetSec);\n result.current_week_sonnet = {\n percent: extractPercent(weekSonnetSec),\n resetsAt: resets ? parseResetsAt(resets) : null,\n };\n }\n\n const extraSec = extractSection(flat, /Extra\\s*usage(?!\\s*not)/i, null);\n if (extraSec && !/not\\s*enabled/i.test(extraSec.slice(0, 40))) {\n const spent = extraSec.match(/\\$([\\d.]+)\\s*\\/\\s*\\$([\\d.]+)\\s*spent/i);\n const resets = extractResets(extraSec);\n result.extra_usage = {\n percent: extractPercent(extraSec),\n spent: spent ? Number.parseFloat(spent[1]) : null,\n limit: spent ? Number.parseFloat(spent[2]) : null,\n resetsAt: resets ? parseResetsAt(resets) : null,\n };\n }\n\n return result;\n}\n\nfunction getClaudeUsage(): Promise<ClaudeUsage> {\n return new Promise((resolve, reject) => {\n const env = { ...process.env };\n delete env['CLAUDECODE'];\n\n let claudeBin = 'claude';\n try {\n const cmd = process.platform === 'win32' ? 'where claude' : 'which claude';\n claudeBin = execSync(cmd, { encoding: 'utf8' }).trim().split('\\n')[0].trim();\n } catch { /* fallback to 'claude' */ }\n\n let term: ReturnType<typeof pty.spawn> | null = null;\n try {\n term = pty.spawn(claudeBin, ['/usage'], {\n name: 'xterm-256color',\n cols: 200,\n rows: 40,\n env,\n });\n } catch (err) {\n reject(err);\n return;\n }\n\n let buffer = '';\n let done = false;\n let debounce: ReturnType<typeof setTimeout> | null = null;\n\n function finish() {\n if (done) return;\n done = true;\n if (debounce) clearTimeout(debounce);\n clearTimeout(hardTimeout);\n term?.kill();\n const clean = buffer\n .replaceAll(/\\x1b\\[[0-9;]*X/g, '\\n') // ECH separators on Windows ConPTY\n .replaceAll(/\\x1b\\[[0-9;]*[mGKHFABCDJsu]/g, '')\n .replaceAll(/\\x1b[^a-zA-Z]*[a-zA-Z]/g, '')\n .replaceAll('\\r', '');\n resolve(parse(clean));\n }\n\n const hardTimeout = setTimeout(() => {\n if (!done) finish();\n }, 15_000);\n\n term.onData((data: string) => {\n buffer += data;\n // Start debounce only after actual usage data has arrived\n if (buffer.includes('%')) {\n if (debounce) clearTimeout(debounce);\n debounce = setTimeout(finish, 800);\n }\n });\n\n term.onExit(() => {\n finish();\n });\n });\n}\n\nexport async function getClaudeUsageEntries(): Promise<CliUsageEntry[]> {\n const usage = await getClaudeUsage();\n const entries: CliUsageEntry[] = [];\n\n if (usage.current_session) {\n entries.push({\n label: 'Session',\n percentage: usage.current_session.percent,\n next_reset: usage.current_session.resetsAt,\n });\n }\n\n if (usage.current_week_all) {\n entries.push({\n label: 'Week',\n percentage: usage.current_week_all.percent,\n next_reset: usage.current_week_all.resetsAt,\n });\n }\n\n if (usage.current_week_sonnet) {\n entries.push({\n label: 'Sonnet',\n percentage: usage.current_week_sonnet.percent,\n next_reset: usage.current_week_sonnet.resetsAt,\n });\n }\n\n if (usage.extra_usage) {\n entries.push({\n label: 'Extra',\n percentage: usage.extra_usage.percent,\n next_reset: usage.extra_usage.resetsAt,\n });\n }\n\n return entries;\n}\n","import pty from 'node-pty';\nimport type { CliUsageEntry } from './claude-usage.js';\n\nconst MONTHS: Record<string, number> = {\n jan: 0, feb: 1, mar: 2, apr: 3, may: 4, jun: 5,\n jul: 6, aug: 7, sep: 8, oct: 9, nov: 10, dec: 11,\n};\n\nfunction parseResetToIso(raw: string): string | null {\n const value = raw\n .replace(/^\\(*/, '')\n .replace(/\\)*$/, '')\n .replace(/^resets?\\s*/i, '')\n .trim();\n\n const now = new Date();\n\n const timeOnly = value.match(/^(\\d{1,2}):(\\d{2})$/);\n if (timeOnly) {\n const hour = Number.parseInt(timeOnly[1], 10);\n const minute = Number.parseInt(timeOnly[2], 10);\n const date = new Date(now);\n date.setHours(hour, minute, 0, 0);\n if (date.getTime() <= now.getTime()) {\n date.setDate(date.getDate() + 1);\n }\n return date.toISOString();\n }\n\n const withDate = value.match(/^(\\d{1,2}):(\\d{2})\\s+on\\s+(\\d{1,2})\\s+([A-Za-z]{3})$/i);\n if (withDate) {\n const hour = Number.parseInt(withDate[1], 10);\n const minute = Number.parseInt(withDate[2], 10);\n const day = Number.parseInt(withDate[3], 10);\n const month = MONTHS[withDate[4].toLowerCase()];\n if (month === undefined) return null;\n\n let year = now.getFullYear();\n let date = new Date(year, month, day, hour, minute, 0, 0);\n if (date.getTime() <= now.getTime()) {\n year += 1;\n date = new Date(year, month, day, hour, minute, 0, 0);\n }\n return date.toISOString();\n }\n\n return null;\n}\n\nfunction stripAnsi(text: string): string {\n return text\n .replace(/[\\u001b\\u009b][[\\]()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '')\n .replaceAll('\\r', '');\n}\n\nexport function parseCodexStatusText(text: string): CliUsageEntry[] {\n const clean = stripAnsi(text);\n const normalizedLines = clean\n .replace(/[│╭╰╮╯─]/g, ' ')\n .split('\\n')\n .map((line) => line.replace(/\\s+/g, ' ').trim())\n .filter(Boolean);\n\n const entries: CliUsageEntry[] = [];\n let pendingIndex: number | null = null;\n\n for (const line of normalizedLines) {\n const sameLine = line.match(/^(.+?limit)\\s*:\\s*(?:\\[[^\\]]*\\]\\s*)?(\\d+)%\\s*left(?:\\s*\\((?:resets?\\s+)?([^)]+)\\))?$/i);\n if (sameLine) {\n const label = sameLine[1].trim();\n const left = Number.parseInt(sameLine[2], 10);\n const used = Number.isNaN(left) ? null : Math.max(0, Math.min(100, 100 - left));\n const nextReset = sameLine[3] ? (parseResetToIso(sameLine[3]) ?? null) : null;\n entries.push({ label, percentage: used, next_reset: nextReset });\n pendingIndex = nextReset ? null : entries.length - 1;\n continue;\n }\n\n const splitReset = line.match(/^\\(?\\s*resets?\\s+([^)]+)\\)?$/i);\n if (splitReset && pendingIndex !== null) {\n entries[pendingIndex].next_reset = parseResetToIso(splitReset[1]) ?? null;\n pendingIndex = null;\n }\n }\n\n if (entries.length === 0) {\n // Fallback: parse statusline format \"· X% left\" emitted by codex bottom bar\n // e.g. \"gpt-5.4 default · 43% left · ~/Projects/runeya-rust\"\n const statuslineMatch = clean.match(/·\\s*(\\d+)%\\s*left/i);\n if (statuslineMatch) {\n const left = Number.parseInt(statuslineMatch[1], 10);\n const used = Number.isNaN(left) ? null : Math.max(0, Math.min(100, 100 - left));\n entries.push({ label: 'Usage', percentage: used, next_reset: null });\n }\n }\n\n return entries;\n}\n\nexport function getCodexUsageEntries(): Promise<CliUsageEntry[]> {\n return new Promise((resolve, reject) => {\n let term: ReturnType<typeof pty.spawn> | null = null;\n try {\n term = pty.spawn('codex', [], {\n name: 'xterm-256color',\n cols: 220,\n rows: 40,\n env: process.env,\n });\n } catch (err) {\n reject(err);\n return;\n }\n\n let buffer = '';\n let done = false;\n const queuedInputs = ['/status', '/status', '/status', '/exit'];\n let queuedIndex = 0;\n let inputDrainDebounce: ReturnType<typeof setTimeout> | null = null;\n let promptSeen = false;\n\n const finish = () => {\n if (done) return;\n done = true;\n if (inputDrainDebounce) clearTimeout(inputDrainDebounce);\n clearTimeout(initialTrigger);\n clearTimeout(hardTimeout);\n term?.kill();\n if (process.env['CODEX_USAGE_DEBUG'] === '1') {\n const debugClean = stripAnsi(buffer).slice(-6000);\n process.stdout.write('[codex-usage] raw tail:\\n' + debugClean + '\\n');\n }\n resolve(parseCodexStatusText(buffer));\n };\n\n const hardTimeout = setTimeout(() => {\n finish();\n }, 25_000);\n\n const sendNextInputIfReady = () => {\n if (done) return;\n if (!promptSeen) return;\n if (queuedIndex >= queuedInputs.length) return;\n const value = queuedInputs[queuedIndex];\n queuedIndex += 1;\n promptSeen = false;\n term?.write(`${value}\\r`);\n };\n\n const initialTrigger = setTimeout(() => {\n promptSeen = true;\n sendNextInputIfReady();\n }, 6_000);\n\n term.onData((data: string) => {\n buffer += data;\n if (data.includes('\\x1b[6n')) {\n // Answer DSR (cursor position report), matching pty-runner behavior.\n term?.write('\\x1b[25;1R');\n }\n\n if (data.includes('›')) {\n promptSeen = true;\n }\n\n if (inputDrainDebounce) clearTimeout(inputDrainDebounce);\n inputDrainDebounce = setTimeout(sendNextInputIfReady, 120);\n\n if (/(\\d+)\\s*h\\s+limit\\s*:/i.test(buffer) && /weekly\\s+limit\\s*:/i.test(buffer)) {\n setTimeout(finish, 800);\n }\n\n // Codex hasn't loaded limits yet — no point waiting the full 25s\n if (/data not available yet/i.test(buffer) && queuedIndex >= queuedInputs.length - 1) {\n setTimeout(finish, 400);\n }\n });\n\n term.onExit(() => {\n clearTimeout(initialTrigger);\n finish();\n });\n });\n}\n","import type { ChildProcess } from 'node:child_process';\nimport { conversationStore } from './conversation-store.js';\nimport { agentManager } from './agent-manager.js';\n\ntype SessionPart =\n | { type: 'thinking'; text: string }\n | { type: 'text'; text: string }\n | { type: 'tool'; id: string; name: string; input?: Record<string, unknown>; rawInput?: string; result?: unknown; isError?: boolean; pending: boolean };\n\n// ─── Types ─────────────────────────────────────────────────────────────────\n\nexport type QueueItem =\n | { type: 'delta'; text: string }\n | { type: 'status'; text: string }\n | { type: 'thinking'; text: string }\n | { type: 'context_usage'; inputTokens: number; contextWindow: number }\n | { type: 'tool_call'; id: string; name: string; input: Record<string, unknown>; rawInput?: string }\n | { type: 'tool_result'; id: string; name: string; result: unknown; isError: boolean }\n | { type: 'done'; text: '' }\n | { type: 'error'; message: string };\n\ntype AiRunnerType = 'claude-code' | 'provider-api';\n\nexport interface ActiveSession {\n proc: ChildProcess | null;\n abortController: AbortController | null;\n sessionType: AiRunnerType;\n conversationId: string;\n buffer: QueueItem[];\n totalProduced: number;\n fullContent: string;\n parts: SessionPart[];\n lastStatus: string;\n status: 'running' | 'done';\n persistTimer: ReturnType<typeof setTimeout> | null;\n cleanupTimer: ReturnType<typeof setTimeout> | null;\n notify: Set<() => void>;\n /** Agent ID when the AI CLI runs on a remote agent. */\n agentId?: string;\n /** Spawn ID on the remote agent (for kill / reconnect). */\n agentSpawnId?: string;\n}\n\n// ─── Constants ─────────────────────────────────────────────────────────────\n\nconst MAX_BUFFER = 5_000;\nconst PERSIST_DEBOUNCE_MS = 100;\n\n// ─── Registry ──────────────────────────────────────────────────────────────\n\nclass ActiveSessionRegistry {\n private sessions = new Map<string, ActiveSession>();\n\n registerClaudeCodeSession(conversationId: string, proc: ChildProcess): ActiveSession {\n this.assertNoActiveSession(conversationId);\n\n const session: ActiveSession = {\n proc,\n abortController: null,\n sessionType: 'claude-code',\n conversationId,\n buffer: [],\n totalProduced: 0,\n fullContent: '',\n parts: [],\n lastStatus: '',\n status: 'running',\n persistTimer: null,\n cleanupTimer: null,\n notify: new Set(),\n };\n\n this.sessions.set(conversationId, session);\n return session;\n }\n\n registerProviderApiSession(conversationId: string, ac: AbortController): ActiveSession {\n this.assertNoActiveSession(conversationId);\n\n const session: ActiveSession = {\n proc: null,\n abortController: ac,\n sessionType: 'provider-api',\n conversationId,\n buffer: [],\n totalProduced: 0,\n fullContent: '',\n parts: [],\n lastStatus: '',\n status: 'running',\n persistTimer: null,\n cleanupTimer: null,\n notify: new Set(),\n };\n\n this.sessions.set(conversationId, session);\n return session;\n }\n\n registerDirectProviderApiSession(conversationId: string): ActiveSession {\n this.assertNoActiveSession(conversationId);\n\n const session: ActiveSession = {\n proc: null,\n abortController: new AbortController(),\n sessionType: 'provider-api',\n conversationId,\n buffer: [],\n totalProduced: 0,\n fullContent: '',\n parts: [],\n lastStatus: '',\n status: 'running',\n persistTimer: null,\n cleanupTimer: null,\n notify: new Set(),\n };\n\n this.sessions.set(conversationId, session);\n return session;\n }\n\n private assertNoActiveSession(conversationId: string): void {\n const existing = this.sessions.get(conversationId);\n if (existing && existing.status === 'running') {\n throw new Error(`A session is already running for conversation ${conversationId}. Stop it first.`);\n }\n }\n\n pushEvent(conversationId: string, event: QueueItem): void {\n if(process.env.RUNEYA_DEBUG) console.log('[chat]: event - ', event.type)\n const session = this.sessions.get(conversationId);\n if (!session) return;\n if(process.env.RUNEYA_DEBUG) console.log('[chat]: event - ', event.type, 'session', session.conversationId)\n\n // Accumulate parts for replay/persist\n if (event.type === 'delta') {\n session.fullContent += event.text;\n const last = session.parts[session.parts.length - 1];\n if (last?.type === 'text') last.text += event.text;\n else session.parts.push({ type: 'text', text: event.text });\n this.schedulePersist(session);\n }\n if (event.type === 'tool_call') {\n const existing = session.parts.find(p => p.type === 'tool' && p.id === event.id) as Extract<SessionPart, { type: 'tool' }> | undefined;\n if (existing) { existing.name = event.name; existing.input = event.input; }\n else session.parts.push({ type: 'tool', id: event.id, name: event.name, input: event.input, rawInput: event.rawInput, pending: true });\n this.schedulePersist(session);\n }\n if (event.type === 'tool_result') {\n const te = session.parts.find(p => p.type === 'tool' && p.id === event.id) as Extract<SessionPart, { type: 'tool' }> | undefined;\n if (te) {\n te.result = event.result;\n te.isError = event.isError;\n te.pending = false;\n } else {\n session.parts.push({ type: 'tool', id: event.id, name: event.name, result: event.result, isError: event.isError, pending: false });\n }\n this.schedulePersist(session);\n }\n if (event.type === 'thinking') {\n const last = session.parts[session.parts.length - 1];\n if (last?.type === 'thinking') last.text += event.text;\n else session.parts.push({ type: 'thinking', text: event.text });\n }\n if (event.type === 'status') {\n session.lastStatus = event.text;\n }\n\n // Cap buffer size — drop oldest if full\n if (session.buffer.length >= MAX_BUFFER) {\n session.buffer.shift();\n }\n if(process.env.RUNEYA_DEBUG) console.log('[chat]: event - ', event.type, 'push buffer')\n session.buffer.push(event);\n session.totalProduced++;\n\n // Wake all consumers (multiple tabs/windows)\n if(process.env.RUNEYA_DEBUG) console.log('[chat]: event - ', event.type, 'notify', session.notify.size)\n for (const cb of session.notify) cb();\n session.notify.clear();\n }\n\n markDone(conversationId: string): void {\n if(process.env.RUNEYA_DEBUG) console.log('[chat]: markdone....', conversationId)\n const session = this.sessions.get(conversationId);\n if (!session) return;\n\n session.status = 'done';\n\n // Persist final content immediately\n this.persistNow(session);\n }\n\n get(conversationId: string): ActiveSession | undefined {\n return this.sessions.get(conversationId);\n }\n\n listActive(): { conversationId: string; status: 'running' | 'done'; sessionType: AiRunnerType }[] {\n const result: { conversationId: string; status: 'running' | 'done'; sessionType: AiRunnerType }[] = [];\n for (const session of this.sessions.values()) {\n result.push({ conversationId: session.conversationId, status: session.status, sessionType: session.sessionType });\n }\n return result;\n }\n\n kill(conversationId: string): boolean {\n const session = this.sessions.get(conversationId);\n if (!session) return false;\n\n if (session.status === 'running') {\n // Remote agent kill\n if (session.agentId && session.agentSpawnId) {\n agentManager.agentMutation(session.agentId, 'ai.kill', { spawnId: session.agentSpawnId }).catch(() => { /* best-effort */ });\n }\n if (session.proc) {\n try { session.proc.kill(); } catch { /* already dead */ }\n }\n if (session.abortController) {\n session.abortController.abort();\n }\n }\n return true;\n }\n\n // ── Internal helpers ────────────────────────────────────────────────────\n\n private schedulePersist(session: ActiveSession): void {\n if (session.persistTimer) return;\n session.persistTimer = setTimeout(() => {\n session.persistTimer = null;\n this.persistNow(session);\n }, PERSIST_DEBOUNCE_MS);\n }\n\n private persistNow(session: ActiveSession): void {\n if (session.persistTimer) {\n clearTimeout(session.persistTimer);\n session.persistTimer = null;\n }\n\n const fullContent = session.fullContent;\n const parts = session.parts.length > 0 ? [...session.parts] : undefined;\n // Synchronous mutation + async save — avoids the async get()→.then() race where a\n // debounced partial-persist .then() could run after a markDone full-persist .then()\n // and overwrite the complete content with stale partial content.\n conversationStore.updateLastAssistantContent(session.conversationId, fullContent, parts);\n }\n\n private cleanupTimers(session: ActiveSession): void {\n if (session.persistTimer) {\n clearTimeout(session.persistTimer);\n session.persistTimer = null;\n }\n if (session.cleanupTimer) {\n clearTimeout(session.cleanupTimer);\n session.cleanupTimer = null;\n }\n }\n}\n\nexport const activeSessionRegistry = new ActiveSessionRegistry();\n","import { settingsManager } from './settings-manager.js';\nimport { ScenarioSchema } from '@runeya/packages-shared';\nimport type { Scenario, ScenarioNode } from '@runeya/packages-shared';\n\nfunction normalizeNode(raw: ScenarioNode & { parentId?: string | null }): ScenarioNode {\n const aiCli = raw.aiCli ?? 'claude-code';\n const defaultModel = aiCli === 'codex' ? '' : 'sonnet';\n // Migrate legacy parentId → parentIds\n let parentIds = raw.parentIds ?? [];\n if (raw.parentId && !parentIds.includes(raw.parentId)) {\n parentIds = [raw.parentId, ...parentIds];\n }\n return {\n ...raw,\n parentIds,\n groupId: raw.groupId ?? null,\n label: raw.label?.trim() ?? '',\n prompt: raw.prompt ?? '',\n autoGenerated: raw.autoGenerated ?? true,\n canAddNode: raw.canAddNode ?? false,\n aiCli,\n model: raw.model?.trim() || defaultModel,\n };\n}\n\nclass ScenarioStore {\n async list(): Promise<Scenario[]> {\n const [settings, priv] = await Promise.all([\n settingsManager.getSettings(),\n settingsManager.getPrivateSettings(),\n ]);\n return [...(settings.scenarios ?? []), ...(priv.scenarios ?? [])];\n }\n\n async get(id: string): Promise<Scenario | null> {\n const list = await this.list();\n return list.find((e) => e.id === id) ?? null;\n }\n\n async create(scenario: Scenario): Promise<Scenario> {\n const normalized = this.normalizeScenario(scenario);\n const parsed = ScenarioSchema.parse(normalized);\n this.validateHierarchy(parsed);\n\n if (parsed.isPublished) {\n const settings = await settingsManager.getSettings();\n await settingsManager.saveSettings({ ...settings, scenarios: [...(settings.scenarios ?? []), parsed] });\n } else {\n const priv = await settingsManager.getPrivateSettings();\n await settingsManager.savePrivateSettings({ ...priv, scenarios: [...(priv.scenarios ?? []), parsed] });\n }\n\n return parsed;\n }\n\n async update(id: string, patch: Partial<Scenario>): Promise<Scenario | null> {\n const [settings, priv] = await Promise.all([\n settingsManager.getSettings(),\n settingsManager.getPrivateSettings(),\n ]);\n\n const publicScenarios = [...(settings.scenarios ?? [])];\n const privateScenarios = [...(priv.scenarios ?? [])];\n\n const publicIdx = publicScenarios.findIndex((e) => e.id === id);\n const privateIdx = privateScenarios.findIndex((e) => e.id === id);\n\n const existing = publicIdx !== -1 ? publicScenarios[publicIdx] : privateIdx !== -1 ? privateScenarios[privateIdx] : null;\n if (!existing) return null;\n\n const merged = { ...existing, ...patch, id, updatedAt: Date.now() } as Scenario;\n const normalized = this.normalizeScenario(merged);\n const parsed = ScenarioSchema.parse(normalized);\n this.validateHierarchy(parsed);\n\n const wasPublic = publicIdx !== -1;\n const isNowPublic = parsed.isPublished;\n\n if (wasPublic && isNowPublic) {\n publicScenarios[publicIdx] = parsed;\n await settingsManager.saveSettings({ ...settings, scenarios: publicScenarios });\n } else if (!wasPublic && !isNowPublic) {\n privateScenarios[privateIdx] = parsed;\n await settingsManager.savePrivateSettings({ ...priv, scenarios: privateScenarios });\n } else if (wasPublic && !isNowPublic) {\n // moved public → private\n publicScenarios.splice(publicIdx, 1);\n await Promise.all([\n settingsManager.saveSettings({ ...settings, scenarios: publicScenarios }),\n settingsManager.savePrivateSettings({ ...priv, scenarios: [...privateScenarios, parsed] }),\n ]);\n } else {\n // moved private → public\n privateScenarios.splice(privateIdx, 1);\n await Promise.all([\n settingsManager.savePrivateSettings({ ...priv, scenarios: privateScenarios }),\n settingsManager.saveSettings({ ...settings, scenarios: [...publicScenarios, parsed] }),\n ]);\n }\n\n return parsed;\n }\n\n async delete(id: string): Promise<boolean> {\n const [settings, priv] = await Promise.all([\n settingsManager.getSettings(),\n settingsManager.getPrivateSettings(),\n ]);\n\n const publicFiltered = (settings.scenarios ?? []).filter((e) => e.id !== id);\n const privateFiltered = (priv.scenarios ?? []).filter((e) => e.id !== id);\n\n const removedFromPublic = publicFiltered.length < (settings.scenarios ?? []).length;\n const removedFromPrivate = privateFiltered.length < (priv.scenarios ?? []).length;\n\n if (!removedFromPublic && !removedFromPrivate) return false;\n\n await Promise.all([\n removedFromPublic ? settingsManager.saveSettings({ ...settings, scenarios: publicFiltered }) : Promise.resolve(),\n removedFromPrivate ? settingsManager.savePrivateSettings({ ...priv, scenarios: privateFiltered }) : Promise.resolve(),\n ]);\n\n return true;\n }\n\n private normalizeScenario(scenario: Scenario): Scenario {\n const nodes = scenario.nodes.map((p) => normalizeNode(p));\n let leaderId = scenario.leaderId;\n if (!nodes.some((p) => p.id === leaderId)) {\n leaderId = nodes[0]?.id ?? leaderId;\n }\n\n return {\n ...scenario,\n leaderId,\n groups: scenario.groups ?? [],\n nodes,\n };\n }\n\n private validateHierarchy(scenario: Scenario): void {\n const groupIds = new Set<string>();\n for (const group of scenario.groups) {\n if (groupIds.has(group.id)) {\n throw new Error(`Duplicate group id: ${group.id}`);\n }\n groupIds.add(group.id);\n }\n\n const nodeIds = new Set<string>();\n for (const node of scenario.nodes) {\n if (nodeIds.has(node.id)) {\n throw new Error(`Duplicate node id: ${node.id}`);\n }\n nodeIds.add(node.id);\n }\n\n const nodesById = new Map(scenario.nodes.map((p) => [p.id, p]));\n if (!nodesById.has(scenario.leaderId)) {\n throw new Error('Leader must be a valid node in the scenario');\n }\n\n for (const node of scenario.nodes) {\n for (const pid of (node.parentIds ?? [])) {\n if (!nodesById.has(pid)) {\n throw new Error(`Node ${node.id} references unknown parent ${pid}`);\n }\n if (node.id === pid) {\n throw new Error(`Node ${node.id} cannot be their own parent`);\n }\n }\n if (node.groupId && !groupIds.has(node.groupId)) {\n throw new Error(`Node ${node.id} references unknown group ${node.groupId}`);\n }\n }\n\n const visited = new Set<string>();\n const inPath = new Set<string>();\n\n const walk = (nodeId: string): void => {\n if (inPath.has(nodeId)) throw new Error('Scenario hierarchy contains a cycle');\n if (visited.has(nodeId)) return;\n inPath.add(nodeId);\n const node = nodesById.get(nodeId);\n for (const pid of (node?.parentIds ?? [])) walk(pid);\n inPath.delete(nodeId);\n visited.add(nodeId);\n };\n\n for (const p of scenario.nodes) walk(p.id);\n }\n}\n\nexport const scenarioStore = new ScenarioStore();\n","import { mkdir, rm, readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { Scenario } from '@runeya/packages-shared';\nimport {\n atomicWriteJsonSecure,\n atomicWriteSecure,\n readJsonFileSafe,\n resolveConversationRunDir,\n} from './run-store-utils.js';\n\nfunction sanitizeSlug(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 60) || 'member';\n}\n\nfunction sanitizeFilePart(value: string, fallback: string): string {\n const sanitized = value\n .toLowerCase()\n .replace(/[^a-z0-9_-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 80);\n return sanitized || fallback;\n}\n\nexport type NodeState = 'idle' | 'running' | 'waiting' | 'waiting_input' | 'done' | 'synthesized' | 'error';\n\nexport interface RunState {\n nodeStates: Record<string, NodeState>;\n nodeOutputs: Record<string, string>;\n /** Claude Code session ID per node — used by the debug PTY drawer (--resume). */\n nodeSessionIds: Record<string, string>;\n /** Agent that ran each node (needed to spawn the resume PTY on the right host). */\n nodeAgentIds: Record<string, string>;\n activeNodeId?: string;\n waitingInputs: Record<string, string>;\n}\n\nexport interface PersistedRunState {\n nodeStates: Record<string, NodeState>;\n nodeOutputs: Record<string, string>;\n nodeSessionIds?: Record<string, string>;\n nodeAgentIds?: Record<string, string>;\n waitingInputs?: Record<string, string>;\n}\n\nclass ScenarioRunStore {\n private static readonly SCENARIO_SNAPSHOT_FILE = 'SCENARIO.json';\n private activeRuns = new Map<string, RunState>();\n\n private getRunDir(conversationId: string): string {\n return resolveConversationRunDir('scenario-runs', conversationId);\n }\n\n async initializeConversationWorkspace(conversationId: string, scenario: Scenario, userInput: string): Promise<void> {\n const dir = this.getRunDir(conversationId);\n await mkdir(dir, { recursive: true });\n await this.saveScenarioSnapshot(conversationId, scenario);\n\n const nodesById = new Map(scenario.nodes.map((p) => [p.id, p]));\n\n const teamMap = new Map(scenario.groups.map((t) => [t.id, t.name]));\n const leader = nodesById.get(scenario.leaderId) ?? scenario.nodes[0];\n\n const overview = [\n `# Scenario Conversation Workspace`,\n '',\n `- Scenario: ${scenario.name}`,\n `- Conversation ID: ${conversationId}`,\n `- Leader: ${leader?.label ?? ''}`,\n '',\n '## Members',\n ...scenario.nodes.map((p) => {\n const parent = p.parentIds[0] ? nodesById.get(p.parentIds[0]) : null;\n const group = p.groupId ? (teamMap.get(p.groupId) ?? p.groupId) : 'No group';\n return `- ${p.label} (${p.id}) | Group: ${group} | Reports to: ${parent ? parent.label : 'None'}`;\n }),\n '',\n '## Rules',\n '- Every node writes in their own markdown file.',\n '- Responses should be sent back to the requester.',\n '- Use read-only references from linked upstream files as context.',\n '',\n ].join('\\n');\n\n await atomicWriteSecure(join(dir, 'README.md'), overview);\n await atomicWriteSecure(join(dir, 'USER_REQUEST.md'), `# User request\\n\\n${userInput.trim() || '(empty)'}\\n`);\n\n for (const node of scenario.nodes) {\n const nodeName = node.label.trim();\n const safeNodeId = sanitizeFilePart(node.id, 'node');\n const fileName = `${sanitizeSlug(nodeName || node.id)}_${safeNodeId}.md`;\n const parent = node.parentIds[0] ? nodesById.get(node.parentIds[0]) : null;\n const reports = scenario.nodes.filter((p) => p.parentIds[0] === node.id);\n const teamName = node.groupId ? (teamMap.get(node.groupId) ?? node.groupId) : 'No group';\n const content = [\n `# ${nodeName || node.id}`,\n '',\n `- ID: ${node.id}`,\n `- Group: ${teamName}`,\n `- Reports to: ${parent ? parent.label : 'None'}`,\n `- Manages: ${reports.length ? reports.map((r) => r.label).join(', ') : 'No direct reports'}`,\n '',\n '## Prompt',\n node.prompt || '(No prompt defined)',\n '',\n '## Work Log',\n '- Waiting for assignment.',\n '',\n ].join('\\n');\n await atomicWriteSecure(join(dir, fileName), content);\n }\n }\n\n async deleteRunDir(conversationId: string): Promise<void> {\n await rm(this.getRunDir(conversationId), { recursive: true, force: true });\n this.activeRuns.delete(conversationId);\n }\n\n private ensureRunState(conversationId: string): RunState {\n let runState = this.activeRuns.get(conversationId);\n if (!runState) {\n runState = { nodeStates: {}, nodeOutputs: {}, nodeSessionIds: {}, nodeAgentIds: {}, waitingInputs: {} };\n this.activeRuns.set(conversationId, runState);\n }\n return runState;\n }\n\n setNodeSession(conversationId: string, nodeId: string, sessionId: string, agentId: string): void {\n const rs = this.ensureRunState(conversationId);\n rs.nodeSessionIds[nodeId] = sessionId;\n rs.nodeAgentIds[nodeId] = agentId;\n }\n\n getNodeSession(conversationId: string, nodeId: string): { sessionId: string; agentId: string } | null {\n const rs = this.activeRuns.get(conversationId);\n const sessionId = rs?.nodeSessionIds[nodeId];\n const agentId = rs?.nodeAgentIds[nodeId];\n if (sessionId && agentId) return { sessionId, agentId };\n return null;\n }\n\n async getNodeSessionPersistent(conversationId: string, nodeId: string): Promise<{ sessionId: string; agentId: string } | null> {\n const live = this.getNodeSession(conversationId, nodeId);\n if (live) return live;\n const persisted = await this.loadPersistedRunState(conversationId);\n const sessionId = persisted?.nodeSessionIds?.[nodeId];\n const agentId = persisted?.nodeAgentIds?.[nodeId];\n if (sessionId && agentId) return { sessionId, agentId };\n return null;\n }\n\n setNodeState(conversationId: string, nodeId: string, state: NodeState): void {\n this.ensureRunState(conversationId).nodeStates[nodeId] = state;\n }\n\n setNodeOutput(conversationId: string, nodeId: string, output: string): void {\n this.ensureRunState(conversationId).nodeOutputs[nodeId] = output;\n }\n\n setActiveNodeId(conversationId: string, nodeId?: string): void {\n this.ensureRunState(conversationId).activeNodeId = nodeId;\n }\n\n setWaitingInput(conversationId: string, nodeId: string, question: string): void {\n this.ensureRunState(conversationId).waitingInputs[nodeId] = question;\n }\n\n clearWaitingInput(conversationId: string, nodeId: string): void {\n const runState = this.activeRuns.get(conversationId);\n if (runState?.waitingInputs) delete runState.waitingInputs[nodeId];\n }\n\n getRunState(conversationId: string): RunState | null {\n return this.activeRuns.get(conversationId) ?? null;\n }\n\n async persistRunState(conversationId: string): Promise<void> {\n const runState = this.activeRuns.get(conversationId);\n if (!runState) return;\n try {\n const dir = this.getRunDir(conversationId);\n await mkdir(dir, { recursive: true });\n const data: PersistedRunState = {\n nodeStates: { ...runState.nodeStates },\n nodeOutputs: { ...runState.nodeOutputs },\n ...(Object.keys(runState.nodeSessionIds).length > 0 ? { nodeSessionIds: { ...runState.nodeSessionIds } } : {}),\n ...(Object.keys(runState.nodeAgentIds).length > 0 ? { nodeAgentIds: { ...runState.nodeAgentIds } } : {}),\n ...(Object.keys(runState.waitingInputs).length > 0 ? { waitingInputs: { ...runState.waitingInputs } } : {}),\n };\n await atomicWriteJsonSecure(join(dir, 'run-state.json'), data);\n } catch {\n // Non-fatal\n }\n }\n\n async loadPersistedRunState(conversationId: string): Promise<PersistedRunState | null> {\n const dir = this.getRunDir(conversationId);\n return readJsonFileSafe<PersistedRunState>(join(dir, 'run-state.json'));\n }\n\n async readUserRequest(conversationId: string): Promise<string | null> {\n try {\n const dir = this.getRunDir(conversationId);\n const content = await readFile(join(dir, 'USER_REQUEST.md'), 'utf-8');\n return content.replace(/^#\\s*User request\\s*\\n+/, '').trim() || null;\n } catch {\n return null;\n }\n }\n\n async readReadme(conversationId: string): Promise<string | null> {\n try {\n const dir = this.getRunDir(conversationId);\n return await readFile(join(dir, 'README.md'), 'utf-8');\n } catch {\n return null;\n }\n }\n\n async saveScenarioSnapshot(conversationId: string, scenario: Scenario): Promise<void> {\n const dir = this.getRunDir(conversationId);\n await mkdir(dir, { recursive: true });\n await atomicWriteJsonSecure(\n join(dir, ScenarioRunStore.SCENARIO_SNAPSHOT_FILE),\n scenario,\n true,\n );\n }\n\n async loadScenarioSnapshot(conversationId: string): Promise<Scenario | null> {\n const dir = this.getRunDir(conversationId);\n return readJsonFileSafe<Scenario>(join(dir, ScenarioRunStore.SCENARIO_SNAPSHOT_FILE));\n }\n}\n\nexport const scenarioRunStore = new ScenarioRunStore();\n","import { chmod, mkdir, rename, writeFile } from 'node:fs/promises';\nimport { dirname, resolve, sep } from 'node:path';\nimport { env } from '../config/env.js';\nimport { readFile } from 'node:fs/promises';\n\nconst SAFE_PATH_SEGMENT_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/;\n\nexport function resolveConversationRunDir(rootDirName: string, conversationId: string): string {\n if (!SAFE_PATH_SEGMENT_RE.test(conversationId)) {\n throw new Error('Invalid conversationId');\n }\n const base = resolve(env.DATA_DIR, rootDirName);\n const dir = resolve(base, conversationId);\n if (!dir.startsWith(base + sep)) {\n throw new Error('Invalid conversationId');\n }\n return dir;\n}\n\nexport async function atomicWriteSecure(filePath: string, content: string): Promise<void> {\n await mkdir(dirname(filePath), { recursive: true });\n const tmpPath = `${filePath}.tmp`;\n await writeFile(tmpPath, content, 'utf-8');\n await rename(tmpPath, filePath);\n await chmod(filePath, 0o600);\n}\n\nexport async function atomicWriteJsonSecure(filePath: string, data: unknown, pretty = false): Promise<void> {\n await atomicWriteSecure(filePath, JSON.stringify(data, null, pretty ? 2 : 0));\n}\n\nexport async function readJsonFileSafe<T>(filePath: string): Promise<T | null> {\n try {\n const raw = await readFile(filePath, 'utf-8');\n return JSON.parse(raw) as T;\n } catch {\n return null;\n }\n}\n","import Anthropic from '@anthropic-ai/sdk';\nimport OpenAI from 'openai';\nimport type { AIProvider } from '@runeya/packages-shared';\nimport { settingsManager } from './settings-manager.js';\nimport { decryptValue } from './crypto-helpers.js';\n\nexport const OPENAI_COMPAT_BASE_URLS: Record<string, string> = {\n openai: 'https://api.openai.com/v1',\n groq: 'https://api.groq.com/openai/v1',\n mistral: 'https://api.mistral.ai/v1',\n ollama: 'http://localhost:11434/v1',\n};\n\nexport const DEFAULT_MODELS: Record<string, string> = {\n anthropic: 'claude-opus-4-6',\n openai: 'gpt-4o',\n groq: 'llama-3.3-70b-versatile',\n mistral: 'mistral-large-latest',\n ollama: 'llama3',\n};\n\nexport async function getActiveProvider(providerId?: string): Promise<{ provider: AIProvider; plaintextKey: string } | null> {\n const priv = await settingsManager.getPrivateSettings();\n const providers = priv.aiProviders ?? [];\n const selected = providerId\n ? providers.find((p: AIProvider) => p.id === providerId)\n : providers.find((p: AIProvider) => p.active);\n if (!selected) return null;\n const plaintextKey = selected.encryptedApiKey ? decryptValue(selected.encryptedApiKey) : '';\n return { provider: selected, plaintextKey };\n}\n\nexport async function fetchProviderModels(provider: AIProvider, plaintextKey: string): Promise<string[]> {\n if (provider.provider === 'anthropic') {\n const client = new Anthropic({ apiKey: plaintextKey });\n const res = await client.models.list();\n return res.data.map(m => m.id).sort((a, b) => a.localeCompare(b));\n }\n\n if (provider.provider in OPENAI_COMPAT_BASE_URLS) {\n const baseURL = OPENAI_COMPAT_BASE_URLS[provider.provider]!;\n const client = new OpenAI({ apiKey: plaintextKey || 'ollama', baseURL });\n const res = await client.models.list();\n return res.data.map(m => m.id).sort((a, b) => a.localeCompare(b));\n }\n\n return [];\n}\n","import { randomUUID } from 'node:crypto';\nimport { mkdir, writeFile, readFile, unlink, readdir } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { join, extname, resolve, sep } from 'node:path';\n\nexport const ALLOWED_MIME_TYPES = new Set([\n 'image/png',\n 'image/jpeg',\n 'image/webp',\n 'image/gif',\n]);\n\nconst ALLOWED_EXTENSIONS = new Set(['.png', '.jpg', '.jpeg', '.webp', '.gif']);\nexport const MAX_IMAGE_SIZE_BYTES = 5 * 1024 * 1024; // 5 MB\nexport const IMAGE_TTL_MS = 24 * 60 * 60 * 1000; // 24h\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nexport interface StoredImage {\n imageId: string;\n filePath: string;\n mimeType: string;\n originalName: string;\n createdAt: number;\n /** Optional tag for grouping (e.g. conversationId, kanban cardId) */\n contextId?: string;\n}\n\nexport class ImageStorageService {\n private dir: string;\n\n constructor(dir: string) {\n this.dir = dir;\n }\n\n async ensureTmpDir(): Promise<void> {\n await mkdir(this.dir, { recursive: true, mode: 0o700 });\n }\n\n async saveImage(buffer: Buffer, originalName: string, mimeType: string, contextId?: string): Promise<StoredImage> {\n if (!ALLOWED_MIME_TYPES.has(mimeType)) {\n throw new Error(`Unsupported MIME type: ${mimeType}. Allowed: ${[...ALLOWED_MIME_TYPES].join(', ')}`);\n }\n if (buffer.length > MAX_IMAGE_SIZE_BYTES) {\n throw new Error(`Image too large: ${buffer.length} bytes (max ${MAX_IMAGE_SIZE_BYTES})`);\n }\n if (!checkMagicBytes(buffer, mimeType)) {\n throw new Error('File content does not match declared MIME type');\n }\n\n const ext = extname(originalName).toLowerCase() || mimeToExt(mimeType);\n if (!ALLOWED_EXTENSIONS.has(ext)) {\n throw new Error(`Unsupported extension: ${ext}`);\n }\n\n await this.ensureTmpDir();\n\n const imageId = randomUUID();\n const safeExt = ext.replace(/[^a-z.]/g, '');\n const fileName = `${imageId}${safeExt}`;\n const filePath = join(this.dir, fileName);\n const resolvedPath = resolve(filePath);\n const resolvedDir = resolve(this.dir);\n if (resolvedPath !== resolvedDir && !resolvedPath.startsWith(resolvedDir + sep)) {\n throw new Error('Invalid file path');\n }\n\n await writeFile(filePath, buffer, { mode: 0o600 });\n const meta: StoredImage = { imageId, filePath, mimeType, originalName, createdAt: Date.now(), contextId };\n await writeFile(`${filePath}.meta.json`, JSON.stringify(meta), { encoding: 'utf-8', mode: 0o600 });\n return meta;\n }\n\n /**\n * Resolve an image on disk.\n *\n * `expectedContextId` scopes the lookup: when given, an image stored under a\n * different context (or under none at all) is reported as missing. Callers\n * that serve an image through a context-scoped URL MUST pass it — the id\n * alone is not an authorization, and without the check any imageId could be\n * fetched under any conversation.\n */\n async getImagePath(\n imageId: string,\n expectedContextId?: string,\n ): Promise<{ filePath: string; mimeType: string; contextId?: string } | null> {\n if (!UUID_RE.test(imageId)) return null;\n try {\n const files = await readdir(this.dir);\n const metaFile = files.find(f => f.startsWith(imageId) && f.endsWith('.meta.json'));\n if (!metaFile) return null;\n const raw = JSON.parse(await readFile(join(this.dir, metaFile), 'utf-8')) as StoredImage;\n if (expectedContextId !== undefined && raw.contextId !== expectedContextId) return null;\n if (!existsSync(raw.filePath)) return null;\n return { filePath: raw.filePath, mimeType: raw.mimeType, contextId: raw.contextId };\n } catch {\n return null;\n }\n }\n\n async deleteImage(imageId: string): Promise<void> {\n const result = await this.getImagePath(imageId);\n if (!result) return;\n await unlink(result.filePath).catch(() => {});\n await unlink(`${result.filePath}.meta.json`).catch(() => {});\n }\n\n async deleteByContextId(contextId: string): Promise<void> {\n let files: string[];\n try {\n files = await readdir(this.dir);\n } catch {\n return;\n }\n await Promise.all(\n files\n .filter(f => f.endsWith('.meta.json'))\n .map(async (file) => {\n try {\n const raw = JSON.parse(await readFile(join(this.dir, file), 'utf-8')) as StoredImage;\n if (raw.contextId === contextId) {\n await unlink(raw.filePath).catch(() => {});\n await unlink(`${raw.filePath}.meta.json`).catch(() => {});\n }\n } catch {\n // skip malformed\n }\n }),\n );\n }\n\n async readImageAsBase64(imageId: string, expectedContextId?: string): Promise<{ base64: string; mimeType: string } | null> {\n const result = await this.getImagePath(imageId, expectedContextId);\n if (!result) return null;\n const buffer = await readFile(result.filePath);\n return { base64: buffer.toString('base64'), mimeType: result.mimeType };\n }\n\n async listExpiredImages(ttlMs = IMAGE_TTL_MS): Promise<StoredImage[]> {\n const expired: StoredImage[] = [];\n let files: string[];\n try {\n files = await readdir(this.dir);\n } catch {\n return [];\n }\n const now = Date.now();\n for (const file of files) {\n if (!file.endsWith('.meta.json')) continue;\n try {\n const raw = JSON.parse(await readFile(join(this.dir, file), 'utf-8')) as StoredImage;\n if (now - raw.createdAt > ttlMs) expired.push(raw);\n } catch {\n // skip malformed\n }\n }\n return expired;\n }\n}\n\nlet _singleton: ImageStorageService | undefined;\nfunction getSingleton(): ImageStorageService {\n if (!_singleton) {\n const dataDir = process.env['RUNEYA_DATA_DIR'] ?? '.runeya';\n _singleton = new ImageStorageService(resolve(dataDir, 'images'));\n }\n return _singleton;\n}\nexport const imageStorageService = new Proxy({} as ImageStorageService, {\n get(_target, prop: string | symbol) {\n const svc = getSingleton();\n const val = (svc as unknown as Record<string | symbol, unknown>)[prop];\n return typeof val === 'function' ? (val as (...args: unknown[]) => unknown).bind(svc) : val;\n },\n});\n\nfunction checkMagicBytes(buf: Buffer, mime: string): boolean {\n if (buf.length < 12) return false;\n switch (mime) {\n case 'image/png':\n return buf[0] === 0x89 && buf[1] === 0x50 && buf[2] === 0x4E && buf[3] === 0x47;\n case 'image/jpeg':\n return buf[0] === 0xFF && buf[1] === 0xD8 && buf[2] === 0xFF;\n case 'image/gif':\n return buf.slice(0, 6).toString('ascii') === 'GIF87a' || buf.slice(0, 6).toString('ascii') === 'GIF89a';\n case 'image/webp':\n return buf.slice(0, 4).toString('ascii') === 'RIFF' && buf.slice(8, 12).toString('ascii') === 'WEBP';\n default:\n return false;\n }\n}\n\nfunction mimeToExt(mime: string): string {\n const map: Record<string, string> = {\n 'image/png': '.png',\n 'image/jpeg': '.jpg',\n 'image/webp': '.webp',\n 'image/gif': '.gif',\n };\n return map[mime] ?? '.bin';\n}\n","import { imageStorageService } from './image-storage.service.js';\n\nexport interface MessageImageRef {\n imageId: string;\n mimeType: string;\n altText?: string;\n}\n\n/**\n * Extracts all image parts from a message's parts array.\n * Parts come from the stored conversation messages.\n */\nexport function extractImagesFromMessage(parts: Array<{ type: string; [key: string]: unknown }>): MessageImageRef[] {\n const images: MessageImageRef[] = [];\n for (const part of parts) {\n if (\n part['type'] === 'image' &&\n typeof part['imageId'] === 'string' &&\n typeof part['mimeType'] === 'string'\n ) {\n images.push({\n imageId: part['imageId'] as string,\n mimeType: part['mimeType'] as string,\n altText: typeof part['altText'] === 'string' ? part['altText'] : undefined,\n });\n }\n }\n return images;\n}\n\n/**\n * Resolves a single image ref to base64, returning null if not found.\n *\n * `contextId` scopes the lookup to the conversation the image was uploaded\n * under; ids that belong elsewhere resolve to null.\n */\nexport async function resolveImageToBase64(\n imageId: string,\n contextId?: string,\n): Promise<{ base64: string; mimeType: string } | null> {\n return imageStorageService.readImageAsBase64(imageId, contextId);\n}\n\n/**\n * Resolves all image refs to base64, skipping missing ones (with a warning).\n *\n * `contextId` scopes the lookup — see `resolveImageToBase64`.\n */\nexport async function resolveImagesToBase64(\n images: MessageImageRef[],\n contextId?: string,\n): Promise<Array<{ imageId: string; base64: string; mimeType: string; altText?: string }>> {\n const results = await Promise.all(\n images.map(async (img) => {\n const resolved = await imageStorageService.readImageAsBase64(img.imageId, contextId);\n if (!resolved) {\n console.warn('[message-images] Image not found (imageId redacted from log)');\n return null;\n }\n return { imageId: img.imageId, base64: resolved.base64, mimeType: resolved.mimeType, altText: img.altText };\n }),\n );\n return results.filter((r): r is NonNullable<typeof r> => r !== null);\n}\n","import { randomUUID } from 'node:crypto';\nimport { kanbanStore } from './kanban-store.js';\nimport type { KanbanBoard, KanbanCard } from '@runeya/packages-shared';\n\n// ─── Command parsing ────────────────────────────────────────────────────────\n\nexport interface KanbanCommand {\n type: 'move_card' | 'add_comment' | 'add_card';\n /** Target column title (for move_card, add_card) */\n columnTitle?: string;\n /** Comment text (for add_comment) */\n comment?: string;\n /** Card title (for add_card) */\n cardTitle?: string;\n /** Card content / markdown (for add_card) */\n cardContent?: string;\n}\n\n// ─── Command execution ──────────────────────────────────────────────────────\n\nexport async function executeKanbanCommands(\n boardId: string,\n cardId: string,\n commands: KanbanCommand[],\n conversationId?: string,\n): Promise<void> {\n if (commands.length === 0) return;\n\n // Retry loading the board a few times — the card may not have been persisted yet\n // when the conversation was launched before the card was fully saved.\n let board = await kanbanStore.get(boardId);\n if (!board) {\n console.warn(`[kanban-commands] Board ${boardId} not found, skipping ${commands.length} command(s)`);\n return;\n }\n\n // Check if card exists in the board; if not, retry a few times with a short delay\n const cardExistsInBoard = () => board!.columns.some(col => col.cards.some(c => c.id === cardId));\n if (!cardExistsInBoard()) {\n for (let attempt = 1; attempt <= 5; attempt++) {\n console.warn(`[kanban-commands] Card ${cardId} not found in board, retry ${attempt}/5...`);\n await new Promise(r => setTimeout(r, 500 * attempt));\n board = await kanbanStore.get(boardId);\n if (!board) return;\n if (cardExistsInBoard()) break;\n }\n if (!cardExistsInBoard()) {\n console.error(`[kanban-commands] Card ${cardId} still not found after retries, skipping ${commands.length} command(s)`);\n return;\n }\n }\n\n for (const cmd of commands) {\n if (cmd.type === 'move_card' && cmd.columnTitle) {\n const moved = moveCard(board, cardId, cmd.columnTitle);\n if (!moved) console.warn(`[kanban-commands] move_card failed: card=${cardId} target=\"${cmd.columnTitle}\"`);\n } else if (cmd.type === 'add_comment' && cmd.comment) {\n addComment(board, cardId, cmd.comment, conversationId);\n } else if (cmd.type === 'add_card' && cmd.columnTitle && cmd.cardTitle) {\n addCardToColumn(board, cmd.columnTitle, cmd.cardTitle, cmd.cardContent);\n }\n }\n\n await kanbanStore.update({ id: board.id, columns: board.columns });\n}\n\n/**\n * Execute board-level commands (no card context needed).\n * Used by the AI populate feature.\n */\nexport async function executeKanbanBoardCommands(\n boardId: string,\n commands: KanbanCommand[],\n): Promise<void> {\n if (commands.length === 0) return;\n\n const board = await kanbanStore.get(boardId);\n if (!board) return;\n\n for (const cmd of commands) {\n if (cmd.type === 'add_card' && cmd.columnTitle && cmd.cardTitle) {\n addCardToColumn(board, cmd.columnTitle, cmd.cardTitle, cmd.cardContent);\n }\n }\n\n await kanbanStore.update({ id: board.id, columns: board.columns });\n}\n\nfunction moveCard(board: KanbanBoard, cardId: string, targetColTitle: string): boolean {\n let sourceCol = '';\n let card = null;\n let sourceColIdx = -1;\n let cardIdx = -1;\n\n for (let ci = 0; ci < board.columns.length; ci++) {\n const col = board.columns[ci];\n const idx = col.cards.findIndex(c => c.id === cardId);\n if (idx !== -1) {\n sourceCol = col.title;\n card = col.cards[idx];\n sourceColIdx = ci;\n cardIdx = idx;\n break;\n }\n }\n if (!card || sourceColIdx === -1) return false;\n\n const targetCol = board.columns.find(\n c => c.title.toLowerCase() === targetColTitle.toLowerCase(),\n );\n if (!targetCol) {\n console.warn(`[kanban-commands] Target column \"${targetColTitle}\" not found. Available: ${board.columns.map(c => c.title).join(', ')}`);\n return false;\n }\n if (targetCol.id === board.columns[sourceColIdx].id) return true; // already there\n\n board.columns[sourceColIdx].cards.splice(cardIdx, 1);\n\n card.order = targetCol.cards.length;\n card.updatedAt = new Date().toISOString();\n card.history = [...(card.history ?? []), {\n type: 'moved',\n timestamp: new Date().toISOString(),\n detail: `\"${sourceCol}\" → \"${targetCol.title}\"`,\n author: 'ai',\n }];\n\n targetCol.cards.push(card);\n return true;\n}\n\nfunction addCardToColumn(board: KanbanBoard, columnTitle: string, cardTitle: string, cardContent?: string): void {\n const col = board.columns.find(c => c.title.toLowerCase() === columnTitle.toLowerCase());\n // Ignore if column doesn't exist — AI must use existing columns\n if (!col) return;\n const now = new Date().toISOString();\n const card: KanbanCard = {\n id: randomUUID(),\n title: cardTitle,\n markdown: cardContent ?? '',\n images: [],\n order: col.cards.length,\n history: [{ type: 'created', timestamp: now, detail: `AI — In column \"${col.title}\"` }],\n createdAt: now,\n updatedAt: now,\n };\n col.cards.push(card);\n}\n\nfunction addComment(board: KanbanBoard, cardId: string, comment: string, conversationId?: string): void {\n for (const col of board.columns) {\n const card = col.cards.find(c => c.id === cardId);\n if (card) {\n card.history = [...(card.history ?? []), {\n type: 'comment',\n timestamp: new Date().toISOString(),\n detail: comment,\n author: 'ai',\n ...(conversationId ? { conversationId } : {}),\n }];\n card.updatedAt = new Date().toISOString();\n return;\n }\n }\n}\n\n// ─── System prompt for kanban context ───────────────────────────────────────\n\nexport function generateKanbanSystemPrompt(board: KanbanBoard, cardId: string): string {\n let currentColTitle = '';\n let card = null;\n for (const col of board.columns) {\n const found = col.cards.find(c => c.id === cardId);\n if (found) {\n currentColTitle = col.title;\n card = found;\n break;\n }\n }\n\n const sortedColumns = [...board.columns].sort((a, b) => a.order - b.order);\n\n const lines: string[] = [];\n lines.push('## Kanban Board Context');\n lines.push('');\n lines.push(`Tu travailles dans le contexte d'une carte Kanban.`);\n lines.push(`- **Board** : ${board.name}`);\n if (card) {\n lines.push(`- **Carte** : ${card.title}`);\n lines.push(`- **Colonne actuelle** : \\`${currentColTitle}\\``);\n }\n lines.push('');\n\n // List columns explicitly so the AI knows the exact names to use\n lines.push('### Colonnes disponibles (noms exacts à utiliser) :');\n for (const col of sortedColumns) {\n const cardCount = col.cards.length;\n const isCurrent = card && col.cards.some(c => c.id === cardId);\n lines.push(`- \\`${col.title}\\` (${cardCount} carte${cardCount !== 1 ? 's' : ''})${isCurrent ? ' ← **colonne actuelle**' : ''}`);\n }\n lines.push('');\n\n // Inject existing comments\n if (card) {\n const comments = (card.history ?? []).filter(e => e.type === 'comment');\n if (comments.length > 0) {\n lines.push('### Commentaires existants sur cette carte :');\n lines.push('');\n for (const c of comments.slice(-20)) { // Last 20 comments max\n const who = c.author === 'ai' ? 'AI' : 'Utilisateur';\n const date = new Date(c.timestamp).toLocaleString('fr-FR', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' });\n lines.push(`- **${who}** (${date}) : ${c.detail}`);\n }\n lines.push('');\n }\n }\n\n lines.push('### Outils Kanban disponibles');\n lines.push('');\n lines.push(`- **boardId** (à passer dans tous les outils) : \\`${board.id}\\``);\n if (card) lines.push(`- **cardId** (carte actuelle) : \\`${card.id}\\``);\n lines.push('');\n lines.push('Tu disposes des outils suivants pour interagir avec le board :');\n lines.push('- `kanban_move_card(boardId, cardId, targetColumn)` — Déplacer la carte vers une autre colonne');\n lines.push('- `kanban_add_comment(boardId, cardId, comment)` — Ajouter un commentaire sur la carte');\n lines.push('');\n lines.push('### OBLIGATOIRE — Décision Kanban');\n lines.push('');\n lines.push('À chaque réponse, tu DOIS obligatoirement faire les deux actions suivantes :');\n lines.push('');\n lines.push('**1. Évaluer et déplacer la carte si nécessaire** via `kanban_move_card` :');\n lines.push(' - **Au début** si tu sais déjà que tu vas travailler activement (ex. tu passes en `In progress`).');\n lines.push(' - **À la fin** pour une décision forte après analyse complète (ex. tu conclus que c\\'est `Done`).');\n lines.push(' - Si tu ne fais qu\\'analyser ou poser des questions → **ne pas déplacer**.');\n lines.push('');\n lines.push(' > ⚠️ **CRITIQUE** : En fin de réponse, tu DOIS TOUJOURS évaluer si la colonne actuelle est encore correcte.');\n lines.push('');\n lines.push('**2. Appeler `kanban_add_comment`** résumant ce que tu as fait ou constaté (**à la fin** de ta réponse).');\n lines.push('');\n lines.push('> 🚫 **INTERDIT** : Terminer une réponse sans appeler `kanban_add_comment`. C\\'est non négociable.');\n lines.push('');\n\n return lines.join('\\n');\n}\n\n// ─── Board-level populate prompt ─────────────────────────────────────────────\n\nexport function generateKanbanPopulatePrompt(board: KanbanBoard): string {\n const lines: string[] = [];\n lines.push('## Kanban Board — Mode Populate');\n lines.push('');\n lines.push(`Tu es en mode **populate** sur le tableau Kanban **\"${board.name}\"**.`);\n lines.push('Tu es un outil de gestion de projet. Quand l\\'utilisateur dit \"créer une card\", \"ajouter une tâche\", \"créer une carte\", ou toute demande similaire, il parle EXCLUSIVEMENT d\\'une carte Kanban à ajouter au tableau — PAS d\\'un composant UI, PAS de code HTML ou CSS, PAS d\\'un composant React/Vue/Angular.');\n lines.push('');\n lines.push('Ton UNIQUE rôle est de créer des cartes Kanban pertinentes en réponse à la demande de l\\'utilisateur.');\n lines.push('Tu ne dois PAS répondre à la question, ni donner d\\'explication, ni écrire du code, ni montrer de composant.');\n lines.push('Tu dois UNIQUEMENT produire des tags XML `<kanban_add_card>` pour créer des cartes dans le tableau.');\n if (board.description) {\n lines.push('');\n lines.push(`Description du board : ${board.description}`);\n }\n lines.push('');\n\n const sortedCols = [...board.columns].sort((a, b) => a.order - b.order);\n\n lines.push('### Colonnes existantes (noms exacts à utiliser) :');\n for (const col of sortedCols) {\n const cardCount = col.cards.length;\n lines.push(`- \\`${col.title}\\` (${cardCount} carte${cardCount !== 1 ? 's' : ''})`);\n for (const card of col.cards) {\n lines.push(` - ${card.title}`);\n }\n }\n lines.push('');\n\n lines.push('### Outil disponible');\n lines.push('');\n lines.push(`- **boardId** (à passer dans tous les outils) : \\`${board.id}\\``);\n lines.push('');\n lines.push('Pour chaque carte à créer, appelle l\\'outil `kanban_add_card(boardId, column, title, content)` :');\n lines.push('- `column` : nom exact de la colonne cible');\n lines.push('- `title` : titre concis de la carte');\n lines.push('- `content` : contenu markdown détaillé et actionnable');\n lines.push('');\n lines.push('### Règles STRICTES');\n lines.push('');\n lines.push('1. **NE RÉPONDS PAS** à la question de l\\'utilisateur. Ne donne aucune explication, aucun texte libre.');\n lines.push('2. **Appelle uniquement** `kanban_add_card`, rien d\\'autre.');\n lines.push('3. Tu ne peux PAS créer de nouvelles colonnes. Dispatch les cartes dans les colonnes existantes listées ci-dessus.');\n lines.push('4. Utilise les noms **exacts** des colonnes.');\n lines.push('5. Chaque carte doit avoir un titre concis et un contenu markdown détaillé et actionnable.');\n lines.push('6. Décompose la demande de l\\'utilisateur en tâches concrètes, chacune étant une carte.');\n lines.push('7. Dispatch chaque carte dans la colonne la plus appropriée selon sa nature.');\n lines.push('');\n\n return lines.join('\\n');\n}\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { cloudSessionStore } from '../../services/cloud-session-store.js';\nimport { env } from '../../config/env.js';\n\nconst DEFAULT_CLOUD_API_URL = 'https://api.runeya.dev';\nconst DEFAULT_CLOUD_APP_URL = 'https://runeya.dev';\n\nexport function getCloudApiUrl(): string {\n return (env.CLOUD_URL ?? DEFAULT_CLOUD_API_URL).replace(/\\/+$/, '');\n}\nfunction getCloudAppUrl(): string {\n return (env.CLOUD_APP_URL ?? DEFAULT_CLOUD_APP_URL).replace(/\\/+$/, '');\n}\n\n/**\n * Only ever send the browser back to a local origin. `returnTo` comes from the\n * web UI, and the callback redirects to it — an unvalidated value would turn\n * this route into an open redirect.\n */\nfunction isLocalOrigin(url: string): boolean {\n try {\n const { protocol, hostname } = new URL(url);\n return (protocol === 'http:' || protocol === 'https:')\n && (hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]');\n } catch {\n return false;\n }\n}\n\n/**\n * Calls the cloud API on behalf of this machine's stored session token.\n *\n * This is the only place a cloud call is authenticated: the token never leaves\n * the server, so the browser holds no cloud credential at all.\n */\nexport async function cloudFetch(\n path: string,\n init: { method?: string; body?: unknown } = {},\n): Promise<Response> {\n const token = await cloudSessionStore.getToken();\n if (!token) {\n throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Not linked to the Runeya cloud.' });\n }\n return fetch(`${getCloudApiUrl()}${path}`, {\n method: init.method ?? 'GET',\n headers: {\n Authorization: `Bearer ${token}`,\n ...(init.body !== undefined ? { 'Content-Type': 'application/json' } : {}),\n },\n ...(init.body !== undefined ? { body: JSON.stringify(init.body) } : {}),\n signal: AbortSignal.timeout(15_000),\n });\n}\n\n/**\n * Cloud endpoints the web UI may reach through this proxy.\n *\n * An allowlist, not a passthrough: the proxy speaks with this machine's cloud\n * token, so an unconstrained `path` would let any caller drive the whole cloud\n * API (including sign-out or account changes) with our credential.\n */\nconst PROXY_PREFIXES = ['/organization/', '/project/', '/chat/', '/kanban/', '/user/prefs'];\n\nfunction isAllowedProxyPath(path: string): boolean {\n if (!path.startsWith('/') || path.includes('..')) return false;\n const [pathname] = path.split('?');\n return PROXY_PREFIXES.some((p) => pathname === p || pathname.startsWith(p));\n}\n\n/**\n * Cloud account link for this machine.\n *\n * The browser authorizes on the cloud origin (its session cookie is same-site\n * there, so it just works), and hands back a single-use token that this server\n * exchanges for a session token. Nothing cloud-related is ever authenticated\n * from the browser, which is why the cloud can refuse localhost origins.\n */\nexport const cloudAuthRouter = router({\n /** Build the cloud authorization URL to open in the browser. */\n startLogin: protectedProcedure\n .input(z.object({ returnTo: z.string().url().max(2048) }))\n .mutation(async ({ input }) => {\n if (!isLocalOrigin(input.returnTo)) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'returnTo must be a local origin.' });\n }\n const state = cloudSessionStore.createState(input.returnTo);\n // The cloud page redirects to this exact callback. RFC 8252 §7.3 only\n // ignores the port for IP literals, never for the DNS name \"localhost\".\n const callback = `http://127.0.0.1:${env.PORT}/api/cloud/callback`;\n const url = `${getCloudAppUrl()}/link-local`\n + `?callback=${encodeURIComponent(callback)}`\n + `&state=${encodeURIComponent(state)}`;\n return { url };\n }),\n\n /** Whether this machine holds a cloud session. */\n status: protectedProcedure.query(async () => {\n return { linked: await cloudSessionStore.isLinked() };\n }),\n\n /** The cloud session (user + org), fetched with the stored token. */\n session: protectedProcedure.query(async () => {\n if (!(await cloudSessionStore.isLinked())) return null;\n const res = await cloudFetch('/api/auth/get-session');\n if (!res.ok) return null;\n return (await res.json()) as unknown;\n }),\n\n /**\n * Forward a cloud API call, authenticated with this machine's token.\n *\n * This is what replaces the browser's direct, cookie-authenticated calls to\n * the cloud: the web UI asks its own server, which holds the credential.\n */\n proxy: protectedProcedure\n .input(\n z.object({\n path: z.string().min(1).max(512),\n method: z.enum(['GET', 'POST']).default('GET'),\n query: z.record(z.string().max(128), z.string().max(2048)).optional(),\n body: z.unknown().optional(),\n }),\n )\n .mutation(async ({ input }) => {\n if (!isAllowedProxyPath(input.path)) {\n throw new TRPCError({ code: 'FORBIDDEN', message: `Path not allowed: ${input.path}` });\n }\n const qs = input.query ? `?${new URLSearchParams(input.query).toString()}` : '';\n const res = await cloudFetch(`/api/auth${input.path}${qs}`, {\n method: input.method,\n ...(input.method === 'POST' ? { body: input.body ?? {} } : {}),\n });\n const text = await res.text();\n let data: unknown = null;\n try {\n data = text ? JSON.parse(text) : null;\n } catch {\n data = text;\n }\n // Mirrors Better Auth's client shape ({ data } / { error }) so callers can\n // keep the same handling they had when they talked to the cloud directly.\n if (!res.ok) return { data: null, error: { status: res.status, ...(data as object) } };\n return { data, error: null };\n }),\n\n /** Drop the cloud session, both here and on the cloud. */\n signOut: protectedProcedure.mutation(async () => {\n if (await cloudSessionStore.isLinked()) {\n try {\n await cloudFetch('/api/auth/sign-out', { method: 'POST', body: {} });\n } catch {\n // Revoking server-side is best-effort — forget the token regardless.\n }\n }\n await cloudSessionStore.clear();\n return { success: true as const };\n }),\n});\n","import { readFile, writeFile, rename, mkdir, chmod, unlink } from 'node:fs/promises';\nimport { randomBytes, timingSafeEqual } from 'node:crypto';\nimport { join } from 'node:path';\nimport { env } from '../config/env.js';\nimport { encryptValue, decryptValue } from './crypto-helpers.js';\n\nconst FILENAME = 'cloud-session.json';\n\n/** How long a pending login may sit between `start` and the browser callback. */\nconst STATE_TTL_MS = 5 * 60 * 1000;\n\ninterface StoredSession {\n cloudUrl: string;\n encryptedToken: string;\n}\n\n/**\n * Holds this machine's cloud session token.\n *\n * The token is obtained through the local-login flow: the browser authorizes on\n * the cloud origin (where its session cookie is same-site and works), receives a\n * single-use token, and hands it to this server, which exchanges it for a\n * session token. The token then lives here — never in the browser — and every\n * cloud call is proxied through this server with `Authorization: Bearer`.\n *\n * That is what lets the cloud refuse localhost origins entirely: no page served\n * on any local port can act on the cloud session, and an XSS in the web UI has\n * no token to steal.\n *\n * Encrypted at rest with the data-dir key, same mechanism as agents.json.\n */\nclass CloudSessionStore {\n private session: StoredSession | null = null;\n private loaded = false;\n /** Pending login states (CSRF binding between `start` and the callback). */\n private pending = new Map<string, { expiresAt: number; returnTo: string }>();\n\n private getFilePath(): string {\n return join(env.DATA_DIR, FILENAME);\n }\n\n private async load(): Promise<void> {\n if (this.loaded) return;\n try {\n const raw = await readFile(this.getFilePath(), 'utf-8');\n this.session = JSON.parse(raw) as StoredSession;\n } catch {\n // No file yet — not logged in.\n }\n this.loaded = true;\n }\n\n /**\n * Mint a state value binding a login attempt to this server. Returned to the\n * cloud page and echoed back on the callback, so a redirect we never\n * initiated cannot install a token.\n */\n createState(returnTo: string): string {\n this.sweepStates();\n const state = randomBytes(32).toString('hex');\n this.pending.set(state, { expiresAt: Date.now() + STATE_TTL_MS, returnTo });\n return state;\n }\n\n /**\n * Consume a state — single use, constant-time compare, TTL enforced. Returns\n * the URL to send the browser back to, or null when the state is unknown or\n * expired (i.e. a callback this server never initiated).\n */\n consumeState(candidate: string): string | null {\n this.sweepStates();\n for (const [state, entry] of this.pending) {\n const a = Buffer.from(state);\n const b = Buffer.from(candidate);\n if (a.length === b.length && timingSafeEqual(a, b)) {\n this.pending.delete(state);\n return entry.expiresAt > Date.now() ? entry.returnTo : null;\n }\n }\n return null;\n }\n\n private sweepStates(): void {\n const now = Date.now();\n for (const [state, entry] of this.pending) {\n if (entry.expiresAt <= now) this.pending.delete(state);\n }\n }\n\n private async save(): Promise<void> {\n await mkdir(env.DATA_DIR, { recursive: true });\n const filePath = this.getFilePath();\n const tmpPath = filePath + '.tmp';\n await writeFile(tmpPath, JSON.stringify(this.session, null, 2), 'utf-8');\n await rename(tmpPath, filePath);\n await chmod(filePath, 0o600);\n }\n\n /** Store the session token obtained from the one-time-token exchange. */\n async set(cloudUrl: string, token: string): Promise<void> {\n await this.load();\n this.session = { cloudUrl, encryptedToken: encryptValue(token) };\n await this.save();\n }\n\n /** The decrypted session token, or null when not logged in. */\n async getToken(): Promise<string | null> {\n await this.load();\n if (!this.session) return null;\n try {\n return decryptValue(this.session.encryptedToken);\n } catch {\n // Key rotated or file tampered with — treat as logged out.\n return null;\n }\n }\n\n async isLinked(): Promise<boolean> {\n return (await this.getToken()) !== null;\n }\n\n /** Forget the session (sign-out). */\n async clear(): Promise<void> {\n await this.load();\n this.session = null;\n this.pending.clear();\n try {\n await unlink(this.getFilePath());\n } catch {\n // Already gone.\n }\n }\n}\n\nexport const cloudSessionStore = new CloudSessionStore();\n","import type { KanbanBoard, CreateKanbanBoardInput, UpdateKanbanBoardInput } from '@runeya/packages-shared';\nimport { cloudFetch } from '../trpc/routers/cloud-auth.js';\n\n/**\n * Kanban boards, read and written on the Runeya cloud.\n *\n * Boards belong to an organization, not to a machine: they are shared with the\n * team and gated on a paid plan, so there is no local copy and no local file.\n * This module keeps the store-shaped API its callers (the MCP kanban commands,\n * the AI queue, the chat router) were already written against — only the\n * backing store moved.\n *\n * Every call goes through `cloudFetch`, which attaches this machine's cloud\n * token. A machine that is not linked to the cloud therefore has no boards at\n * all: reads come back empty and writes report failure, rather than silently\n * accumulating work nobody else will ever see.\n */\n\n/** A cloud board, as the API serializes it. */\ninterface CloudBoard extends KanbanBoard {\n organizationId: string;\n}\n\ninterface CloudCall<T> {\n ok: boolean;\n data: T | null;\n}\n\nasync function callCloud<T>(path: string, init: { method?: string; body?: unknown } = {}): Promise<CloudCall<T>> {\n try {\n const res = await cloudFetch(`/api/auth${path}`, init);\n if (!res.ok) {\n // 402/403 here is the plan gate (Solo is read-only) — worth surfacing,\n // since the caller is usually an AI agent whose write just vanished.\n console.error('[kanban-store] cloud call failed: %s %s', res.status, path);\n return { ok: false, data: null };\n }\n return { ok: true, data: (await res.json()) as T };\n } catch (err) {\n console.error('[kanban-store] cloud call errored:', err);\n return { ok: false, data: null };\n }\n}\n\n/**\n * The organization whose boards this machine works with: the active one on the\n * cloud session, falling back to the only/first membership. Resolved per call\n * rather than cached, so switching org in the web app takes effect at once.\n */\nasync function resolveOrganizationId(): Promise<string | null> {\n const session = await callCloud<{ session?: { activeOrganizationId?: string | null } }>('/get-session');\n const active = session.data?.session?.activeOrganizationId;\n if (active) return active;\n const orgs = await callCloud<{ id: string }[]>('/organization/list');\n return orgs.data?.[0]?.id ?? null;\n}\n\nclass KanbanStore {\n async list(includeArchived = false): Promise<KanbanBoard[]> {\n const organizationId = await resolveOrganizationId();\n if (!organizationId) return [];\n const query = `?organizationId=${encodeURIComponent(organizationId)}`\n + (includeArchived ? '&includeArchived=true' : '');\n const res = await callCloud<{ boards: KanbanBoard[] }>(`/kanban/board/list${query}`);\n return res.data?.boards ?? [];\n }\n\n async get(id: string): Promise<KanbanBoard | null> {\n const res = await callCloud<{ board: CloudBoard }>(`/kanban/board/get?id=${encodeURIComponent(id)}`);\n return res.data?.board ?? null;\n }\n\n async create(input: CreateKanbanBoardInput): Promise<KanbanBoard | null> {\n const organizationId = await resolveOrganizationId();\n if (!organizationId) return null;\n const res = await callCloud<{ board: CloudBoard }>('/kanban/board/create', {\n method: 'POST',\n body: { organizationId, name: input.name, description: input.description ?? '' },\n });\n return res.data?.board ?? null;\n }\n\n async update(input: UpdateKanbanBoardInput): Promise<KanbanBoard | null> {\n const res = await callCloud<{ board: CloudBoard }>('/kanban/board/update', {\n method: 'POST',\n body: input,\n });\n return res.data?.board ?? null;\n }\n\n async delete(id: string): Promise<boolean> {\n const res = await callCloud<{ success: boolean }>('/kanban/board/delete', {\n method: 'POST',\n body: { id },\n });\n return res.data?.success ?? false;\n }\n}\n\nexport const kanbanStore = new KanbanStore();\n","import { spawn } from 'node:child_process';\nimport { buildApiDocs } from './runeya-api-docs.js';\nimport { parseEndToken, TOKEN_INSTRUCTIONS } from './scenario-tokens.js';\nimport { runClaudeViaPty } from './claude-pty-runner.js';\nimport type { AiRunner, AiRunnerParams, NodeResult } from './ai-runner.js';\n\n// ─── Claude stream parser ──────────────────────────────────────────────────\n\ninterface ClaudeStreamState {\n fullContent: string;\n thinkingEmitted: boolean;\n textDeltaReceived: boolean;\n currentToolName: string;\n currentToolId: string;\n currentToolInputJson: string;\n toolInputAccumulator: Map<string, { name: string; json: string }>;\n actualSessionId: string | undefined;\n}\n\nfunction createClaudeStreamState(): ClaudeStreamState {\n return {\n fullContent: '',\n thinkingEmitted: false,\n textDeltaReceived: false,\n currentToolName: '',\n currentToolId: '',\n currentToolInputJson: '',\n toolInputAccumulator: new Map(),\n actualSessionId: undefined,\n };\n}\n\ninterface ClaudeStreamCallbacks {\n onDelta: (text: string) => void;\n onStatus: (text: string) => void;\n onThinking?: (text: string) => void;\n onToolCall?: (id: string, name: string, input: Record<string, unknown>) => void;\n onToolResult?: (id: string, name: string, result: string, isError: boolean) => void;\n onContextUsage?: (inputTokens: number, contextWindow: number) => void;\n onResult?: (result: string, sessionId: string | undefined, isError: boolean) => void;\n}\n\nfunction parseClaudeStreamLine(\n line: string,\n state: ClaudeStreamState,\n cb: ClaudeStreamCallbacks,\n): Record<string, unknown> | null {\n const trimmed = line.trim();\n if (!trimmed) return null;\n let event: Record<string, unknown>;\n try { event = JSON.parse(trimmed) as Record<string, unknown>; } catch { return null; }\n\n if (event['type'] === 'stream_event') {\n const ev = event['event'] as Record<string, unknown> | undefined;\n const evType = ev?.['type'];\n const delta = ev?.['delta'] as Record<string, unknown> | undefined;\n const contentBlock = ev?.['content_block'] as Record<string, unknown> | undefined;\n\n if (delta?.['type'] === 'thinking_delta' && typeof delta['thinking'] === 'string') {\n if (!state.thinkingEmitted) {\n state.thinkingEmitted = true;\n cb.onStatus('💭 En réflexion…');\n }\n cb.onThinking?.(delta['thinking'] as string);\n }\n\n if (evType === 'content_block_start' && contentBlock?.['type'] === 'tool_use') {\n state.currentToolName = typeof contentBlock['name'] === 'string' ? contentBlock['name'] : 'tool';\n state.currentToolId = typeof contentBlock['id'] === 'string' ? contentBlock['id'] : '';\n state.currentToolInputJson = '';\n if (state.currentToolId) {\n state.toolInputAccumulator.set(state.currentToolId, { name: state.currentToolName, json: '' });\n }\n cb.onStatus(`🔧 ${state.currentToolName}`);\n }\n\n if (delta?.['type'] === 'input_json_delta' && typeof delta['partial_json'] === 'string') {\n state.currentToolInputJson += delta['partial_json'] as string;\n if (state.currentToolId) {\n const acc = state.toolInputAccumulator.get(state.currentToolId);\n if (acc) acc.json = state.currentToolInputJson;\n }\n }\n\n if (evType === 'content_block_stop' && state.currentToolId && state.toolInputAccumulator.has(state.currentToolId)) {\n const acc = state.toolInputAccumulator.get(state.currentToolId)!;\n let parsedInput: Record<string, unknown> = {};\n try { parsedInput = JSON.parse(acc.json || '{}') as Record<string, unknown>; } catch { /* keep empty */ }\n cb.onToolCall?.(state.currentToolId, acc.name, parsedInput);\n state.currentToolId = '';\n state.currentToolInputJson = '';\n }\n\n if (delta?.['type'] === 'text_delta' && typeof delta['text'] === 'string') {\n state.textDeltaReceived = true;\n state.thinkingEmitted = false;\n state.fullContent += delta['text'];\n cb.onStatus('');\n cb.onDelta(delta['text']);\n }\n\n if (evType === 'message_start') {\n const msg = ev?.['message'] as Record<string, unknown> | undefined;\n const usage = msg?.['usage'] as Record<string, unknown> | undefined;\n if (usage && typeof usage['input_tokens'] === 'number' && cb.onContextUsage) {\n const inputTokens = (usage['input_tokens'] as number)\n + (typeof usage['cache_read_input_tokens'] === 'number' ? usage['cache_read_input_tokens'] : 0)\n + (typeof usage['cache_creation_input_tokens'] === 'number' ? usage['cache_creation_input_tokens'] : 0);\n const modelName = typeof msg?.['model'] === 'string' ? msg['model'] : '';\n const contextWindow = /claude-instant/i.test(modelName) ? 100_000 : 200_000;\n cb.onContextUsage(inputTokens, contextWindow);\n }\n }\n }\n\n if (event['type'] === 'user') {\n const msg = event['message'] as Record<string, unknown> | undefined;\n const content = msg?.['content'];\n const blocks = Array.isArray(content) ? content as Record<string, unknown>[] : [];\n for (const block of blocks) {\n if (block['type'] === 'tool_result' && typeof block['tool_use_id'] === 'string') {\n const id = block['tool_use_id'] as string;\n const isError = block['is_error'] === true;\n const blockContent = block['content'];\n let result = '';\n if (typeof blockContent === 'string') {\n result = blockContent;\n } else if (Array.isArray(blockContent)) {\n result = (blockContent as Record<string, unknown>[])\n .filter(b => b['type'] === 'text')\n .map(b => b['text'] as string)\n .join('');\n }\n const toolName = state.toolInputAccumulator.get(id)?.name ?? '';\n cb.onToolResult?.(id, toolName, result, isError);\n }\n }\n }\n\n if (event['type'] === 'result') {\n if (typeof event['session_id'] === 'string' && event['session_id']) {\n state.actualSessionId = event['session_id'];\n }\n const isError = event['is_error'] === true;\n const resultText = typeof event['result'] === 'string' ? event['result'] : '';\n if (!state.textDeltaReceived && resultText) {\n state.fullContent += resultText;\n cb.onStatus('');\n cb.onDelta(resultText);\n }\n cb.onResult?.(resultText, state.actualSessionId, isError);\n }\n\n return event;\n}\n\nconst EFFORT_THINKING_BUDGET: Record<string, number> = {\n low: 0,\n normal: 5000,\n high: 10000,\n};\n\n/** Build CLI args, env, and stdinData from runner params. Shared by runLocal and runViaAgent.\n * When `excludeMcp` is true, omit --mcp-config from args (agent builds it locally). */\nfunction buildClaudeSpawnConfig(params: AiRunnerParams, opts?: { excludeMcp?: boolean }) {\n const { sessionId, prompt, isResume, systemContext, apiBaseUrl, apiToken, model, effort, images, mcpConfig, skipTokenInstructions, injectedEnv } = params;\n\n const hasImages = images && images.length > 0;\n const sessionArg = isResume\n ? ['--resume', sessionId]\n : (sessionId ? ['--session-id', sessionId] : []);\n\n const thinkingBudget = EFFORT_THINKING_BUDGET[effort] ?? 0;\n const thinkingArgs = thinkingBudget > 0 ? ['--thinking', 'enabled'] : [];\n\n const apiDocs = buildApiDocs(apiBaseUrl, apiToken);\n const fullSystemContext = apiDocs ? `${systemContext}\\n\\n${apiDocs}` : systemContext;\n const systemPrompt = skipTokenInstructions\n ? fullSystemContext\n : `${fullSystemContext}\\n\\n${TOKEN_INSTRUCTIONS}`;\n\n const inputArgs = hasImages\n ? ['--input-format', 'stream-json']\n : ['-p', prompt];\n\n const mcpArgs = (mcpConfig && !opts?.excludeMcp) ? ['--mcp-config', mcpConfig] : [];\n\n const args = [\n ...sessionArg,\n '--output-format', 'stream-json',\n '--verbose',\n '--include-partial-messages',\n '--dangerously-skip-permissions',\n '--model', model,\n ...thinkingArgs,\n '--append-system-prompt', systemPrompt,\n ...mcpArgs,\n ...inputArgs,\n ];\n\n // Env: unset CLAUDECODE, pass apiToken via env var\n const env: Record<string, string> = {\n ...Object.fromEntries(Object.entries(process.env).filter(([k]) => k !== 'CLAUDECODE')) as Record<string, string>,\n ...injectedEnv,\n ...(apiToken ? { RUNEYA_API_TOKEN: apiToken } : {}),\n };\n\n // Build stdin data for images\n let stdinData: string | undefined;\n if (hasImages) {\n const contentBlocks: unknown[] = [{ type: 'text', text: prompt }];\n for (const img of images!) {\n contentBlocks.push({\n type: 'image',\n source: { type: 'base64', media_type: img.mimeType, data: img.base64 },\n });\n }\n stdinData = JSON.stringify({ role: 'user', content: contentBlocks }) + '\\n';\n }\n\n return { args, env, stdinData, sessionArg, hasImages };\n}\n\n/** Mutable state shared across stdout processing calls. */\ninterface ClaudeProcessingCtx {\n settled: boolean;\n earlyResult: NodeResult | null;\n lastResultError: string;\n rawStdoutLines: string[];\n}\n\n/** Process raw stdout lines from the claude CLI stream. Shared by runLocal and runViaAgent. */\nfunction processClaudeStdoutLines(\n lines: string[],\n streamState: ClaudeStreamState,\n params: AiRunnerParams,\n ctx: ClaudeProcessingCtx,\n): void {\n const { onDelta, onStatus, onThinking, onToolCall, onToolResult, skipTokenInstructions } = params;\n\n const settle = (result: NodeResult) => {\n if (ctx.settled) return;\n ctx.settled = true;\n ctx.earlyResult = result;\n // For local runs, don't remove abort listener here — let the process finish\n // to capture actualSessionId from the result event.\n };\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n ctx.rawStdoutLines.push(trimmed);\n if (ctx.rawStdoutLines.length > 50) ctx.rawStdoutLines.shift();\n\n if (ctx.settled) {\n try {\n const ev = JSON.parse(trimmed) as Record<string, unknown>;\n if (ev['type'] === 'result' && typeof ev['session_id'] === 'string') {\n streamState.actualSessionId = ev['session_id'];\n }\n if (ev['type'] === 'result' && ev['is_error'] === true) {\n const errMsg = typeof ev['error'] === 'string' ? ev['error']\n : typeof (ev['error'] as Record<string, unknown>)?.['message'] === 'string' ? (ev['error'] as Record<string, unknown>)['message'] as string : '';\n if (errMsg) ctx.lastResultError = errMsg.slice(-2000);\n }\n } catch { /* ignore */ }\n continue;\n }\n\n const event = parseClaudeStreamLine(line, streamState, {\n onDelta: (text) => {\n onDelta(text);\n if (!skipTokenInstructions) {\n const { status, message, branchChoice } = parseEndToken(streamState.fullContent);\n if (status !== 'none') {\n settle({ output: streamState.fullContent, tokenStatus: status, tokenMessage: message, branchChoice, actualSessionId: streamState.actualSessionId });\n }\n }\n },\n onStatus,\n onThinking,\n onToolCall: (id, name, input) => onToolCall?.(id, name, input),\n onToolResult: (id, _name, result, isError) => onToolResult?.(id, result, isError),\n onContextUsage: params.onContextUsage,\n onResult: (result, _sessionId, isError) => {\n if (isError) {\n const errMsg = typeof result === 'string' ? result : '';\n if (errMsg) ctx.lastResultError = errMsg.slice(-2000);\n }\n if (result) params.onResult?.(result);\n },\n });\n\n if (!event) {\n if (!ctx.lastResultError) ctx.lastResultError = trimmed.slice(-2000);\n }\n }\n}\n\nexport class ClaudeCodeRunner implements AiRunner {\n run(params: AiRunnerParams): Promise<NodeResult> {\n // The CLI always runs in an interactive PTY — there is no headless `-p`\n // mode anymore (it would switch billing from the subscription to the API).\n // The PTY lives on the agent (it owns node-pty); without an agent we can\n // only fall back to the local spawn path.\n if (params.agentId) {\n return runClaudeViaPty(params);\n }\n return this.runLocal(params);\n }\n\n // ── Run locally (original implementation) ───────────────────────────────\n\n private runLocal(params: AiRunnerParams): Promise<NodeResult> {\n const { signal, skipTokenInstructions } = params;\n const { args, env, stdinData, sessionArg, hasImages: _hasImages } = buildClaudeSpawnConfig(params);\n\n return new Promise<NodeResult>((resolve, reject) => {\n const totalArgSize = args.reduce((s, a) => s + a.length + 1, 0);\n console.log(`[claude-code-runner] arg size: ${totalArgSize} bytes (${(totalArgSize / 1024 / 1024).toFixed(2)} MB), session: ${sessionArg.join(' ')}, images: ${params.images?.length ?? 0}`);\n const displayArgs = args.map(a => {\n if (a === params.prompt) return '<prompt>';\n if (a.includes(TOKEN_INSTRUCTIONS)) return '<system-context>';\n return a;\n });\n params.onCommand?.(`claude ${displayArgs.join(' ')}`);\n const proc = spawn('claude', args, {\n stdio: ['pipe', 'pipe', 'pipe'],\n shell: false,\n env,\n });\n\n if (stdinData) {\n proc.stdin!.write(stdinData);\n proc.stdin!.end();\n } else {\n proc.stdin!.end();\n }\n\n const streamState = createClaudeStreamState();\n const ctx: ClaudeProcessingCtx = { settled: false, earlyResult: null, lastResultError: '', rawStdoutLines: [] };\n let stdoutBuffer = '';\n\n const onAbort = () => {\n try { proc.kill('SIGTERM'); } catch { /* ignore */ }\n };\n signal.addEventListener('abort', onAbort, { once: true });\n\n let stderrBuffer = '';\n\n proc.stdout!.on('data', (chunk: Buffer) => {\n stdoutBuffer += chunk.toString('utf-8');\n const lines = stdoutBuffer.split('\\n');\n stdoutBuffer = lines.pop() ?? '';\n processClaudeStdoutLines(lines, streamState, params, ctx);\n });\n\n proc.stderr!.on('data', (chunk: Buffer) => { stderrBuffer += chunk.toString('utf-8'); });\n\n proc.on('close', (code) => {\n if (ctx.earlyResult) { resolve({ ...ctx.earlyResult, actualSessionId: streamState.actualSessionId }); return; }\n\n signal.removeEventListener('abort', onAbort);\n if (signal.aborted) { reject(new Error('Aborted')); return; }\n if (code !== 0 && !streamState.fullContent) {\n const stderr = stderrBuffer.trim().slice(-2000);\n const rawStdout = ctx.rawStdoutLines.slice(-10).join('\\n').trim();\n console.error(`[claude-code-runner] exit code ${code} | stderr: ${stderr || '(empty)'} | last stdout lines: ${rawStdout || '(empty)'}`);\n const detail = ctx.lastResultError || stderr || rawStdout;\n reject(new Error(`Claude Code exited with code ${code}${detail ? `: ${detail}` : ''}`));\n return;\n }\n const { status, message, branchChoice } = skipTokenInstructions\n ? { status: 'none' as const, message: '', branchChoice: undefined }\n : parseEndToken(streamState.fullContent);\n resolve({ output: streamState.fullContent, tokenStatus: status, tokenMessage: message, branchChoice, actualSessionId: streamState.actualSessionId });\n });\n\n proc.on('error', (err) => {\n if (ctx.settled) return;\n signal.removeEventListener('abort', onAbort);\n reject(err);\n });\n });\n }\n}\n\n","// ─── Token-based node completion signals ──────────────────────────────────\n//\n// Shared between all runners (ClaudeCodeRunner, CodexRunner) and the scenario\n// runner orchestration layer. Not used in chat mode.\n\nexport function parseEndToken(output: string): { status: 'pass' | 'error' | 'ask_user' | 'none'; message: string; branchChoice?: number } {\n const tail = output.trimEnd().slice(-2000);\n\n // <pass branch=\"N\" />\n const branchMatch = tail.match(/<pass\\s+branch=\"(\\d+)\"\\s*\\/>/);\n if (branchMatch) {\n return { status: 'pass', message: '', branchChoice: Number.parseInt(branchMatch[1], 10) };\n }\n\n // <pass />\n if (/<pass\\s*\\/>/.test(tail)) {\n return { status: 'pass', message: '' };\n }\n\n // <error>message</error>\n const errorMatch = tail.match(/<error>([\\s\\S]*?)<\\/error>/);\n if (errorMatch) {\n return { status: 'error', message: errorMatch[1].trim() };\n }\n\n // <ask_user>question</ask_user>\n const askMatch = tail.match(/<ask_user>([\\s\\S]*?)<\\/ask_user>/);\n if (askMatch) {\n return { status: 'ask_user', message: askMatch[1].trim() };\n }\n\n return { status: 'none', message: '' };\n}\n\nexport const TOKEN_INSTRUCTIONS = `\n## Instructions de signalisation (OBLIGATOIRE)\n\nÀ la fin de CHAQUE réponse, tu DOIS terminer par exactement l'un de ces tags XML :\n\n- Si tu as terminé avec succès (chemin par défaut) : \\`<pass />\\`\n- Si le nœud propose plusieurs branches de sortie numérotées : \\`<pass branch=\"1\" />\\`, \\`<pass branch=\"2\" />\\`, etc. (choisis la branche qui correspond le mieux au résultat)\n- Si tu as rencontré une erreur bloquante : \\`<error>description courte</error>\\`\n- Si tu es bloqué par une information que personne dans l'équipe ne peut fournir (secret, décision business, credential externe) : \\`<ask_user>ta question</ask_user>\\` — NE PAS utiliser pour demander une confirmation ou un accord (\"es-tu prêt ?\", \"puis-je continuer ?\")\n\nNe jamais omettre ce tag. Il doit être la toute dernière ligne de ta réponse.\n`.trim();\n","import { randomUUID } from 'node:crypto';\nimport { buildApiDocs } from './runeya-api-docs.js';\nimport { parseEndToken, TOKEN_INSTRUCTIONS } from './scenario-tokens.js';\nimport { tailTranscript, type TranscriptEntry } from './claude-pty-tail.js';\nimport type { AiRunnerParams, NodeResult } from './ai-runner.js';\n\nasync function getAgentManager() {\n const { agentManager } = await import('../agent-manager.js');\n return agentManager;\n}\n\ninterface ToolAcc { id: string; name: string }\n\n/**\n * Build claude argv for interactive (PTY) mode. The prompt is passed as a\n * positional argument so claude opens the TUI with it as the first message.\n * `-p` is intentionally omitted: that's the whole point of this runner —\n * stay on the subscription pricing tier.\n */\nfunction buildPtyArgs(params: AiRunnerParams, sessionId: string, opts: { excludeMcp: boolean }) {\n const { isResume, systemContext, apiBaseUrl, apiToken, model, mcpConfig, skipTokenInstructions, prompt } = params;\n\n const sessionArg = isResume ? ['--resume', sessionId] : ['--session-id', sessionId];\n\n const apiDocs = buildApiDocs(apiBaseUrl, apiToken);\n const fullSystemContext = apiDocs ? `${systemContext}\\n\\n${apiDocs}` : systemContext;\n const systemPrompt = skipTokenInstructions\n ? fullSystemContext\n : `${fullSystemContext}\\n\\n${TOKEN_INSTRUCTIONS}`;\n\n const mcpArgs = (mcpConfig && !opts.excludeMcp) ? ['--mcp-config', mcpConfig] : [];\n\n const args = [\n ...sessionArg,\n '--dangerously-skip-permissions',\n '--model', model,\n '--append-system-prompt', systemPrompt,\n ...mcpArgs,\n prompt,\n ];\n\n return args;\n}\n\n/**\n * Extract a delta of text/tool/thinking events from a JSONL entry written by\n * claude (interactive mode). Each entry is either a user / assistant message\n * or a system event. We fire callbacks similar to the headless stream-json\n * parser but at message granularity instead of token granularity.\n */\nfunction dispatchEntry(\n entry: TranscriptEntry,\n state: { assistantText: string; tools: Map<string, ToolAcc> },\n cbs: {\n onDelta: (text: string) => void;\n onStatus: (text: string) => void;\n onThinking?: (text: string) => void;\n onToolCall?: (id: string, name: string, input: Record<string, unknown>) => void;\n onToolResult?: (id: string, result: string, isError: boolean) => void;\n },\n): void {\n if (entry.type !== 'user' && entry.type !== 'assistant') return;\n const msg = entry.message;\n if (!msg) return;\n const role = msg.role ?? entry.type;\n const content = msg.content;\n\n if (typeof content === 'string') {\n if (role === 'assistant' && content) {\n state.assistantText += content;\n cbs.onStatus('');\n cbs.onDelta(content);\n }\n return;\n }\n if (!Array.isArray(content)) return;\n\n for (const raw of content) {\n if (!raw || typeof raw !== 'object') continue;\n const block = raw as {\n type?: string;\n text?: string;\n thinking?: string;\n id?: string;\n name?: string;\n input?: Record<string, unknown>;\n tool_use_id?: string;\n content?: unknown;\n is_error?: boolean;\n };\n if (block.type === 'text' && typeof block.text === 'string' && role === 'assistant') {\n state.assistantText += block.text;\n cbs.onStatus('');\n cbs.onDelta(block.text);\n } else if (block.type === 'thinking' && typeof block.thinking === 'string') {\n cbs.onStatus('💭 En réflexion…');\n cbs.onThinking?.(block.thinking);\n } else if (block.type === 'tool_use' && block.id) {\n const name = block.name ?? 'tool';\n state.tools.set(block.id, { id: block.id, name });\n cbs.onStatus(`🔧 ${name}`);\n cbs.onToolCall?.(block.id, name, block.input ?? {});\n } else if (block.type === 'tool_result' && typeof block.tool_use_id === 'string') {\n const c = block.content;\n let result = '';\n if (typeof c === 'string') result = c;\n else if (Array.isArray(c)) {\n result = (c as Array<Record<string, unknown>>)\n .filter((b) => b['type'] === 'text')\n .map((b) => (b['text'] as string) ?? '')\n .join('');\n }\n cbs.onToolResult?.(block.tool_use_id, result, block.is_error === true);\n }\n }\n}\n\n/**\n * Run a single node turn via an interactive claude PTY.\n *\n * Flow:\n * 1. Generate a fresh session-id (or reuse params.sessionId on resume).\n * 2. Spawn `claude <args> \"<prompt>\"` in a PTY on the agent.\n * 3. Tail the JSONL transcript Claude writes to ~/.claude/projects/.\n * 4. Re-emit each new entry as onDelta/onThinking/onToolCall/onToolResult.\n * 5. parseEndToken() on accumulated assistant text. On token → kill PTY,\n * resolve. Without TOKEN_INSTRUCTIONS, resolve on transcript settling.\n */\nexport async function runClaudeViaPty(params: AiRunnerParams): Promise<NodeResult> {\n const { agentId, signal, skipTokenInstructions } = params;\n if (!agentId) throw new Error('runClaudeViaPty requires an agentId');\n\n const sessionId = params.sessionId && params.sessionId.length > 0\n ? params.sessionId\n : randomUUID();\n const args = buildPtyArgs(params, sessionId, { excludeMcp: true });\n\n const agentMgr = await getAgentManager();\n\n const displayArgs = args.map((a) => {\n if (a === params.prompt) return '<prompt>';\n if (a.includes(TOKEN_INSTRUCTIONS)) return '<system-context>';\n return a;\n });\n params.onCommand?.(`claude ${displayArgs.join(' ')}`);\n\n return new Promise<NodeResult>((resolve, reject) => {\n let settled = false;\n let spawnId: string | null = null;\n const state = { assistantText: '', tools: new Map<string, ToolAcc>() };\n\n const innerAbort = new AbortController();\n const onParentAbort = () => innerAbort.abort();\n signal.addEventListener('abort', onParentAbort, { once: true });\n\n const cleanup = () => {\n signal.removeEventListener('abort', onParentAbort);\n innerAbort.abort();\n };\n\n const killSpawn = async () => {\n if (!spawnId) return;\n try { await agentMgr.agentMutation(agentId, 'ai.kill', { spawnId }); } catch { /* best-effort */ }\n };\n\n const settle = (result: NodeResult) => {\n if (settled) return;\n settled = true;\n cleanup();\n void killSpawn();\n resolve(result);\n };\n\n const fail = (err: Error) => {\n if (settled) return;\n settled = true;\n cleanup();\n void killSpawn();\n reject(err);\n };\n\n // Tail JSONL → dispatch entries → detect end-token.\n const tail = tailTranscript({\n sessionId,\n signal: innerAbort.signal,\n onEntry: (entry) => {\n try {\n dispatchEntry(entry, state, {\n onDelta: params.onDelta,\n onStatus: params.onStatus,\n onThinking: params.onThinking,\n onToolCall: params.onToolCall,\n onToolResult: params.onToolResult,\n });\n } catch { /* never break the tail on a malformed event */ }\n\n if (!skipTokenInstructions) {\n const { status, message, branchChoice } = parseEndToken(state.assistantText);\n if (status !== 'none') {\n settle({\n output: state.assistantText,\n tokenStatus: status,\n tokenMessage: message,\n branchChoice,\n actualSessionId: sessionId,\n });\n }\n }\n },\n });\n\n // Spawn PTY on the agent.\n agentMgr.agentMutation<{ spawnId: string }>(agentId, 'ai.spawnPty', {\n cli: 'claude',\n args,\n env: params.injectedEnv && Object.keys(params.injectedEnv).length > 0 ? params.injectedEnv : undefined,\n cols: 120,\n rows: 30,\n sessionId,\n enableMcp: !!params.mcpConfig,\n mcpApiBaseUrl: params.apiBaseUrl || undefined,\n }).then(({ spawnId: id }) => {\n spawnId = id;\n if (signal.aborted) { fail(new Error('Aborted')); return; }\n }).catch((err) => {\n fail(new Error(`Failed to spawn claude PTY: ${(err as Error).message}`));\n });\n\n // Abort handling: parent signal → stop tail + kill.\n signal.addEventListener('abort', () => fail(new Error('Aborted')), { once: true });\n\n // If skipTokenInstructions, we have no end-token; rely on tail completion\n // (which only happens on abort). For scenarios we always use the token.\n void tail.whenDone.then(() => {\n if (settled) return;\n // Tail ended without a token — likely the PTY exited or user aborted.\n if (skipTokenInstructions) {\n settle({\n output: state.assistantText,\n tokenStatus: 'none',\n tokenMessage: '',\n actualSessionId: sessionId,\n });\n } else {\n fail(new Error('Claude PTY ended before producing an end token'));\n }\n });\n });\n}\n","import { open, type FileHandle } from 'node:fs/promises';\nimport { watch, type FSWatcher } from 'node:fs';\nimport { findClaudeSessionFile } from '../claude-transcript-sync.js';\n\nexport interface TranscriptEntry {\n type: string;\n uuid?: string;\n timestamp?: string;\n message?: {\n role?: string;\n content?: unknown;\n usage?: unknown;\n model?: string;\n };\n toolUseResult?: unknown;\n}\n\nexport interface TailOptions {\n sessionId: string;\n signal: AbortSignal;\n /** Max wait for the JSONL file to appear on disk before yielding control. */\n fileAppearTimeoutMs?: number;\n onEntry: (entry: TranscriptEntry) => void;\n}\n\n/** Wait until the JSONL transcript file for `sessionId` exists on disk. */\nasync function waitForFile(sessionId: string, signal: AbortSignal, timeoutMs: number): Promise<string> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n if (signal.aborted) throw new Error('Aborted');\n const path = await findClaudeSessionFile(sessionId);\n if (path) return path;\n await new Promise((r) => setTimeout(r, 150));\n }\n throw new Error(`Transcript file for session ${sessionId} never appeared (timeout ${timeoutMs}ms)`);\n}\n\n/**\n * Tail a Claude JSONL transcript: yield each new entry as it is appended.\n * Returns a `stop()` function and a `whenDone` promise that resolves on stop.\n *\n * NOTE: Reads `~/.claude/projects/<slug>/<sessionId>.jsonl` from the local\n * filesystem. This assumes the agent runs on the same host as the server\n * (local-simple mode). For remote agents, expose a tail route on the agent.\n */\nexport function tailTranscript(opts: TailOptions): { stop: () => void; whenDone: Promise<void> } {\n const { sessionId, signal, onEntry, fileAppearTimeoutMs = 30_000 } = opts;\n let stopped = false;\n let watcher: FSWatcher | null = null;\n let fh: FileHandle | null = null;\n let offset = 0;\n let pendingBuf = '';\n let reading = false;\n let queuedRead = false;\n\n const cleanup = async () => {\n stopped = true;\n if (watcher) { try { watcher.close(); } catch { /* ignore */ } watcher = null; }\n if (fh) { try { await fh.close(); } catch { /* ignore */ } fh = null; }\n };\n\n const drainBuffer = () => {\n let idx;\n while ((idx = pendingBuf.indexOf('\\n')) >= 0) {\n const line = pendingBuf.slice(0, idx).trim();\n pendingBuf = pendingBuf.slice(idx + 1);\n if (!line) continue;\n try {\n const entry = JSON.parse(line) as TranscriptEntry;\n onEntry(entry);\n } catch { /* skip malformed line */ }\n }\n };\n\n const readMore = async () => {\n if (!fh || stopped) return;\n if (reading) { queuedRead = true; return; }\n reading = true;\n try {\n while (!stopped) {\n const st = await fh.stat();\n if (st.size <= offset) break;\n const len = st.size - offset;\n const buf = Buffer.alloc(len);\n const { bytesRead } = await fh.read(buf, 0, len, offset);\n if (bytesRead <= 0) break;\n offset += bytesRead;\n pendingBuf += buf.slice(0, bytesRead).toString('utf-8');\n drainBuffer();\n }\n } finally {\n reading = false;\n if (queuedRead && !stopped) { queuedRead = false; void readMore(); }\n }\n };\n\n const whenDone = (async () => {\n const onAbort = () => { void cleanup(); };\n signal.addEventListener('abort', onAbort, { once: true });\n try {\n const path = await waitForFile(sessionId, signal, fileAppearTimeoutMs);\n if (stopped) return;\n fh = await open(path, 'r');\n // Initial drain (handles content already written between spawn and watcher).\n await readMore();\n if (stopped) return;\n watcher = watch(path, { persistent: false }, () => { void readMore(); });\n watcher.on('error', () => { /* best-effort */ });\n // Polling fallback at low cadence — fs.watch can miss events on some FS.\n const poll = setInterval(() => { void readMore(); }, 500);\n // Keep alive until stopped.\n await new Promise<void>((resolve) => {\n const tick = setInterval(() => { if (stopped) { clearInterval(tick); clearInterval(poll); resolve(); } }, 100);\n });\n } finally {\n signal.removeEventListener('abort', onAbort);\n await cleanup();\n }\n })();\n\n return {\n stop: () => { void cleanup(); },\n whenDone,\n };\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\nimport { createInterface, type Interface as ReadlineInterface } from 'node:readline';\nimport { EventEmitter } from 'node:events';\n\n// ─── Types ──────────────────────────────────────────────────────────────────\n\ntype NotificationHandler = (method: string, params: Record<string, unknown>) => void;\n\ninterface PendingRequest {\n resolve: (result: unknown) => void;\n reject: (error: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\n// ─── Client ─────────────────────────────────────────────────────────────────\n\nexport class CodexAppServerClient extends EventEmitter {\n private proc: ChildProcess | null = null;\n private rl: ReadlineInterface | null = null;\n private nextId = 1;\n private pending = new Map<number, PendingRequest>();\n private notificationHandlers = new Map<string, NotificationHandler[]>();\n private catchAllHandlers: NotificationHandler[] = [];\n private requestTimeoutMs: number;\n\n constructor(opts?: { requestTimeoutMs?: number }) {\n super();\n this.requestTimeoutMs = opts?.requestTimeoutMs ?? 120_000;\n }\n\n /** Spawn codex app-server, perform initialize handshake, return server info. */\n async connect(): Promise<Record<string, unknown>> {\n this.proc = spawn('codex', ['app-server'], {\n stdio: ['pipe', 'pipe', 'pipe'],\n env: { ...process.env },\n });\n\n this.rl = createInterface({ input: this.proc.stdout! });\n this.rl.on('line', (line) => this.handleLine(line));\n\n this.proc.on('exit', (code, signal) => {\n this.rejectAllPending(new Error(`codex app-server exited (code=${code}, signal=${signal})`));\n this.emit('exit', code, signal);\n });\n\n this.proc.on('error', (err) => {\n this.rejectAllPending(err);\n this.emit('error', err);\n });\n\n // Initialize handshake\n const result = await this.sendRequest('initialize', {\n clientInfo: { name: 'runeya', title: 'Runeya', version: '1.0.0' },\n capabilities: { experimentalApi: false },\n }, 0) as Record<string, unknown>;\n\n // Send initialized notification\n this.sendNotification('initialized', {});\n\n return result;\n }\n\n /** Send a JSON-RPC request and return a promise for the result. */\n sendRequest(method: string, params?: Record<string, unknown>, forceId?: number): Promise<unknown> {\n const id = forceId ?? this.nextId++;\n // If forceId was used and equals nextId range, bump to avoid collision\n if (forceId !== undefined && forceId >= this.nextId) {\n this.nextId = forceId + 1;\n }\n\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pending.delete(id);\n reject(new Error(`Request ${method} (id=${id}) timed out after ${this.requestTimeoutMs}ms`));\n }, this.requestTimeoutMs);\n\n this.pending.set(id, { resolve, reject, timer });\n this.writeLine({ jsonrpc: '2.0', method, id, params: params ?? {} });\n });\n }\n\n /** Send a JSON-RPC notification (no id, no response expected). */\n sendNotification(method: string, params: Record<string, unknown>): void {\n this.writeLine({ jsonrpc: '2.0', method, params });\n }\n\n /** Respond to a server-initiated request (e.g. approval workflow). */\n respond(id: number, result: unknown): void {\n this.writeLine({ jsonrpc: '2.0', id, result });\n }\n\n respondError(id: number, code: number, message: string): void {\n this.writeLine({ jsonrpc: '2.0', id, error: { code, message } });\n }\n\n /** Register a handler for a specific notification method. */\n onNotification(method: string, handler: NotificationHandler): void {\n const list = this.notificationHandlers.get(method) ?? [];\n list.push(handler);\n this.notificationHandlers.set(method, list);\n }\n\n /** Register a catch-all notification handler. */\n onAnyNotification(handler: NotificationHandler): void {\n this.catchAllHandlers.push(handler);\n }\n\n /** Gracefully shut down the child process. */\n async shutdown(): Promise<void> {\n if (!this.proc) return;\n this.rl?.close();\n this.rl = null;\n\n const proc = this.proc;\n this.proc = null;\n\n return new Promise<void>((resolve) => {\n proc.on('exit', () => resolve());\n proc.kill('SIGTERM');\n // Force kill after 5s\n const forceTimer = setTimeout(() => {\n proc.kill('SIGKILL');\n }, 5000);\n proc.on('exit', () => clearTimeout(forceTimer));\n });\n }\n\n // ─── Internal ───────────────────────────────────────────────────────────\n\n private writeLine(obj: Record<string, unknown>): void {\n if (!this.proc?.stdin?.writable) {\n throw new Error('codex app-server stdin not writable');\n }\n this.proc.stdin.write(JSON.stringify(obj) + '\\n');\n }\n\n private handleLine(line: string): void {\n const trimmed = line.trim();\n if (!trimmed) return;\n\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(trimmed);\n } catch {\n return; // ignore malformed lines\n }\n\n // Response to a pending request\n if ('id' in msg && typeof msg['id'] === 'number' && ('result' in msg || 'error' in msg)) {\n const pending = this.pending.get(msg['id'] as number);\n if (pending) {\n this.pending.delete(msg['id'] as number);\n clearTimeout(pending.timer);\n if ('error' in msg && msg['error']) {\n const err = msg['error'] as { code: number; message: string };\n pending.reject(new Error(`JSON-RPC error ${err.code}: ${err.message}`));\n } else {\n pending.resolve(msg['result']);\n }\n }\n return;\n }\n\n // Server-initiated request (has id + method, no result/error)\n if ('id' in msg && 'method' in msg && typeof msg['method'] === 'string') {\n this.emit('server-request', msg);\n return;\n }\n\n // Notification (method, no id)\n if ('method' in msg && typeof msg['method'] === 'string' && !('id' in msg)) {\n const method = msg['method'] as string;\n const params = (msg['params'] ?? {}) as Record<string, unknown>;\n\n const handlers = this.notificationHandlers.get(method);\n if (handlers) {\n for (const h of handlers) h(method, params);\n }\n for (const h of this.catchAllHandlers) h(method, params);\n }\n }\n\n private rejectAllPending(error: Error): void {\n for (const [id, pending] of this.pending) {\n clearTimeout(pending.timer);\n pending.reject(error);\n this.pending.delete(id);\n }\n }\n}\n","import { buildApiDocs } from './runeya-api-docs.js';\nimport { parseEndToken, TOKEN_INSTRUCTIONS } from './scenario-tokens.js';\nimport type { AiRunner, AiRunnerParams, NodeResult } from './ai-runner.js';\nimport { CodexAppServerClient } from './codex-app-server-client.js';\n\n// ─── Singleton app-server client ───────────────────────────────────────────\n\nlet appServerClient: CodexAppServerClient | null = null;\nlet appServerConnecting: Promise<void> | null = null;\n\nasync function getAppServerClient(): Promise<CodexAppServerClient> {\n if (appServerClient) return appServerClient;\n if (appServerConnecting) {\n await appServerConnecting;\n return appServerClient!;\n }\n const client = new CodexAppServerClient({ requestTimeoutMs: 300_000 });\n appServerConnecting = client.connect().then(() => {\n appServerClient = client;\n appServerConnecting = null;\n }).catch((err) => {\n appServerConnecting = null;\n throw err;\n });\n // Handle unexpected exit — reset singleton so next call reconnects\n client.on('exit', () => {\n if (appServerClient === client) {\n appServerClient = null;\n }\n });\n await appServerConnecting;\n return appServerClient!;\n}\n\n/** Gracefully shut down the singleton codex app-server process. */\nexport async function shutdownCodexAppServer(): Promise<void> {\n if (appServerClient) {\n const client = appServerClient;\n appServerClient = null;\n await client.shutdown();\n }\n}\n\nasync function getAgentManager() {\n const { agentManager } = await import('../agent-manager.js');\n return agentManager;\n}\n\n// ─── Codex CLI runner ──────────────────────────────────────────────────────\n//\n// Local mode: uses `codex app-server` (persistent JSON-RPC 2.0 process).\n// Agent mode: uses agent-side `codex app-server` via ai.codexRequest/ai.codexNotifications tRPC routes.\n//\n// Both modes use the app-server protocol for thread management (start/resume)\n// and turn execution with structured notifications.\n\n/** Extract route name + parsed input from a curl command targeting the Runeya tRPC API. */\nfunction parseRuneyaCurlCommand(command: string): { route: string; input: Record<string, unknown> } | null {\n // Match /api/trpc/<route> in URL\n const routeMatch = command.match(/\\/api\\/trpc\\/([\\w.]+)/);\n if (!routeMatch) return null;\n const route = routeMatch[1];\n // Try to extract JSON body from -d '...' or -d \"...\"\n let input: Record<string, unknown> = {};\n const bodyMatch = command.match(/-d\\s+'([^']+)'/) ?? command.match(/-d\\s+\"((?:[^\"\\\\]|\\\\.)*)\"/);\n if (bodyMatch) {\n try { input = JSON.parse(bodyMatch[1]) as Record<string, unknown>; } catch { /* keep empty */ }\n }\n // Also check ?input= for GET requests\n const inputQsMatch = command.match(/[?&]input=([^&\\s'\"]+)/);\n if (inputQsMatch) {\n try { input = JSON.parse(decodeURIComponent(inputQsMatch[1])) as Record<string, unknown>; } catch { /* keep empty */ }\n }\n return { route, input };\n}\n\nfunction getCommandExecutionInput(item: Record<string, unknown> | undefined): Record<string, unknown> {\n if (!item) return {};\n const command = typeof item['command'] === 'string' ? item['command'] : '';\n const parsed = command ? parseRuneyaCurlCommand(command) : null;\n if (parsed) return parsed.input;\n const input: Record<string, unknown> = {};\n if (command) input.command = command;\n if (typeof item['status'] === 'string' && item['status']) input.status = item['status'];\n if (typeof item['exit_code'] === 'number') input.exit_code = item['exit_code'];\n return input;\n}\n\nfunction getCommandExecutionName(item: Record<string, unknown> | undefined): string {\n if (!item) return 'command_execution';\n const command = typeof item['command'] === 'string' ? item['command'] : '';\n const parsed = command ? parseRuneyaCurlCommand(command) : null;\n return parsed ? parsed.route : 'command_execution';\n}\n\nfunction getCommandExecutionResult(item: Record<string, unknown> | undefined): string {\n if (!item) return '';\n if (typeof item['aggregated_output'] === 'string' && item['aggregated_output']) {\n return item['aggregated_output'] as string;\n }\n const fallback = {\n command: typeof item['command'] === 'string' ? item['command'] : undefined,\n status: typeof item['status'] === 'string' ? item['status'] : undefined,\n exit_code: typeof item['exit_code'] === 'number' ? item['exit_code'] : undefined,\n };\n return JSON.stringify(fallback, null, 2);\n}\n\n/** Map Runeya effort levels to Codex app-server effort values. */\nfunction mapEffort(effort: string): string | undefined {\n const map: Record<string, string> = { low: 'low', normal: 'medium', medium: 'medium', high: 'high' };\n return map[effort];\n}\n\nexport class CodexRunner implements AiRunner {\n /** Codex thread_id captured from `thread.started`, used for resume. */\n private lastThreadId: string | null = null;\n\n run(params: AiRunnerParams): Promise<NodeResult> {\n if (params.agentId) {\n return this.runViaAgent(params);\n }\n return this.runLocal(params);\n }\n\n // ── Run via agent (app-server JSON-RPC via agent tRPC routes) ───────────\n\n private async runViaAgent(params: AiRunnerParams): Promise<NodeResult> {\n const { agentId, prompt, systemContext, signal, model, effort, isResume, images, skipTokenInstructions, apiBaseUrl, apiToken, injectedEnv } = params;\n const agentMgr = await getAgentManager();\n\n if (isResume && params.sessionId && !this.lastThreadId) {\n this.lastThreadId = params.sessionId;\n }\n\n params.onStatus('🔧 Codex en cours…');\n params.onCommand?.('codex app-server (agent JSON-RPC)');\n\n // Env vars to inject into the agent-side app-server process:\n // active-environment variables flagged `injectIntoAi` + the Runeya API token.\n const codexEnv = (injectedEnv && Object.keys(injectedEnv).length > 0) || apiToken\n ? { ...injectedEnv, ...(apiToken ? { RUNEYA_API_TOKEN: apiToken } : {}) }\n : undefined;\n\n // 1. Start or resume thread on agent-side app-server\n let threadId: string;\n if (isResume && this.lastThreadId) {\n const res = await agentMgr.agentMutation<{ result: { thread: { id: string } } }>(agentId!, 'ai.codexRequest', {\n method: 'thread/resume',\n params: { threadId: this.lastThreadId },\n env: codexEnv,\n });\n threadId = res.result.thread.id;\n } else {\n const res = await agentMgr.agentMutation<{ result: { thread: { id: string } } }>(agentId!, 'ai.codexRequest', {\n method: 'thread/start',\n params: {\n model: model || undefined,\n cwd: process.cwd(),\n approvalPolicy: 'never',\n sandbox: 'danger-full-access',\n },\n env: codexEnv,\n });\n threadId = res.result.thread.id;\n this.lastThreadId = threadId;\n params.onThreadId?.(threadId);\n }\n\n // 2. Build turn input (same as runLocal)\n const apiDocs = buildApiDocs(apiBaseUrl, apiToken);\n const systemParts = [systemContext, ...(skipTokenInstructions ? [] : [TOKEN_INSTRUCTIONS]), apiDocs].filter(Boolean);\n const fullSystemContext = systemParts.join('\\n\\n');\n const fullPrompt = (isResume && this.lastThreadId)\n ? prompt\n : `${fullSystemContext}\\n\\n---\\n\\n${prompt}`;\n\n const input: Array<Record<string, unknown>> = [];\n if (images && images.length > 0) {\n for (const img of images) {\n input.push({ type: 'image', url: `data:${img.mimeType};base64,${img.base64}` });\n }\n }\n input.push({ type: 'text', text: fullPrompt });\n\n // 3. Subscribe to notifications BEFORE starting the turn\n // Mutable ref so the notification handler can access turnId set after turn/start\n const turnRef: { id: string | null } = { id: null };\n\n return new Promise<NodeResult>((resolve, reject) => {\n let settled = false;\n let fullContent = '';\n let thinkingEmitted = false;\n const startedCommandExecutions = new Set<string>();\n const completedCommandExecutions = new Set<string>();\n\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n signal.removeEventListener('abort', onAbort);\n if (unsubscribe) { unsubscribe(); unsubscribe = null; }\n fn();\n };\n\n const onAbort = () => {\n if (settled) return;\n if (turnRef.id) {\n agentMgr.agentMutation(agentId!, 'ai.codexRequest', {\n method: 'turn/interrupt',\n params: { threadId, turnId: turnRef.id },\n }).catch(() => { /* best-effort */ });\n }\n settle(() => reject(new Error('Aborted')));\n };\n signal.addEventListener('abort', onAbort, { once: true });\n\n let unsubscribe: (() => void) | null = agentMgr.agentSubscribe(\n agentId!,\n 'ai.codexNotifications',\n { threadId },\n (data: unknown) => {\n if (settled) return;\n const notif = data as { method: string; params: Record<string, unknown> };\n const method = notif.method;\n const p = notif.params;\n\n // Filter by threadId\n const notifThreadId = p['threadId'] as string | undefined;\n if (notifThreadId && notifThreadId !== threadId) return;\n\n // Filter by turnId if present\n const notifTurnId = (p['turnId'] ?? (p['turn'] as Record<string, unknown> | undefined)?.['id']) as string | undefined;\n if (notifTurnId && turnRef.id && notifTurnId !== turnRef.id) return;\n\n if (method === 'item/agentMessage/delta') {\n const delta = p['delta'] as string;\n if (delta) {\n thinkingEmitted = false;\n fullContent += delta;\n params.onDelta(delta);\n const { status, message, branchChoice } = parseEndToken(fullContent);\n if (status !== 'none') {\n settle(() => resolve({ output: fullContent, tokenStatus: status, tokenMessage: message, branchChoice }));\n }\n }\n } else if (method === 'item/reasoning/summaryTextDelta' || method === 'item/reasoning/textDelta') {\n const delta = p['delta'] as string;\n if (delta) {\n if (!thinkingEmitted) {\n thinkingEmitted = true;\n params.onStatus('💭 En réflexion…');\n }\n params.onThinking?.(delta);\n }\n } else if (method === 'item/started') {\n const item = p['item'] as Record<string, unknown> | undefined;\n if (!item) return;\n const itemType = item['type'] as string;\n const itemId = item['id'] as string ?? '';\n\n if (itemType === 'commandExecution') {\n const command = typeof item['command'] === 'string' ? item['command'] as string : '';\n const cmdName = getCommandExecutionName(item);\n const effectiveId = itemId || (command ? `cmd-${command.slice(0, 80)}` : '');\n params.onStatus(`🔧 ${cmdName}`);\n if (effectiveId && !startedCommandExecutions.has(effectiveId)) {\n startedCommandExecutions.add(effectiveId);\n params.onToolCall?.(effectiveId, cmdName, getCommandExecutionInput(item));\n }\n } else if (itemType === 'mcpToolCall' || itemType === 'tool_call') {\n const rawName = typeof item['tool'] === 'string' ? item['tool'] as string\n : typeof item['name'] === 'string' ? item['name'] as string : 'tool';\n const server = typeof item['server'] === 'string' ? item['server'] as string : '';\n const displayName = server ? `${server}.${rawName}` : rawName;\n params.onStatus(`🔧 ${displayName}`);\n if (itemId) {\n let toolInput: Record<string, unknown> = {};\n const rawArgs = item['arguments'];\n if (typeof rawArgs === 'string') {\n try { toolInput = JSON.parse(rawArgs) as Record<string, unknown>; } catch { /* keep empty */ }\n } else if (rawArgs && typeof rawArgs === 'object') {\n toolInput = rawArgs as Record<string, unknown>;\n }\n params.onToolCall?.(itemId, displayName, toolInput);\n }\n }\n } else if (method === 'item/completed') {\n const item = p['item'] as Record<string, unknown> | undefined;\n if (!item) return;\n const itemType = item['type'] as string;\n const itemId = item['id'] as string ?? '';\n\n if (itemType === 'commandExecution') {\n const command = typeof item['command'] === 'string' ? item['command'] as string : '';\n const effectiveId = itemId || (command ? `cmd-${command.slice(0, 80)}` : '');\n if (effectiveId && !completedCommandExecutions.has(effectiveId)) {\n completedCommandExecutions.add(effectiveId);\n const exitCode = typeof item['exit_code'] === 'number' ? item['exit_code'] as number : 0;\n params.onToolResult?.(effectiveId, getCommandExecutionResult(item), exitCode !== 0);\n }\n } else if (itemType === 'mcpToolCall' || itemType === 'tool_call') {\n if (itemId) {\n const output = item['output'];\n const result = typeof output === 'string' ? output : (output ? JSON.stringify(output) : '');\n params.onToolResult?.(itemId, result, false);\n }\n }\n } else if (method === 'turn/completed') {\n const turn = p['turn'] as Record<string, unknown> | undefined;\n const error = turn?.['error'] as Record<string, unknown> | undefined;\n if (error) {\n const msg = typeof error['message'] === 'string' ? error['message'] as string : 'Codex turn failed';\n settle(() => reject(new Error(`Codex: ${msg}`)));\n return;\n }\n const { status, message, branchChoice } = parseEndToken(fullContent);\n settle(() => resolve({ output: fullContent, tokenStatus: status, tokenMessage: message, branchChoice }));\n } else if (method === 'turn/errored') {\n const error = p['error'] as Record<string, unknown> | undefined;\n const msg = typeof error?.['message'] === 'string' ? error['message'] as string : 'Codex turn errored';\n settle(() => reject(new Error(`Codex: ${msg}`)));\n }\n },\n () => {\n // onStop — WS disconnect\n },\n );\n\n // 4. Start turn on agent-side app-server\n agentMgr.agentMutation<{ result: { turn: { id: string; status: string } } }>(agentId!, 'ai.codexRequest', {\n method: 'turn/start',\n params: {\n threadId,\n input,\n model: model || undefined,\n effort: mapEffort(effort),\n approvalPolicy: 'never',\n sandboxPolicy: { type: 'dangerFullAccess' },\n },\n }).then((turnRes) => {\n turnRef.id = turnRes.result.turn.id;\n }).catch((err) => {\n settle(() => reject(new Error(`Failed to start codex turn on agent: ${(err as Error).message}`)));\n });\n });\n }\n\n // ── Run locally via app-server client ────────────────────────────────────\n\n private async runLocal(params: AiRunnerParams): Promise<NodeResult> {\n const { prompt, systemContext, signal, model, effort, isResume, images, skipTokenInstructions, apiBaseUrl, apiToken } = params;\n\n if (isResume && params.sessionId && !this.lastThreadId) {\n this.lastThreadId = params.sessionId;\n }\n\n params.onStatus('🔧 Codex en cours…');\n params.onCommand?.('codex app-server (JSON-RPC)');\n\n // 1. Get or create the singleton client\n const client = await getAppServerClient();\n\n // 2. Start or resume thread\n let threadId: string;\n if (isResume && this.lastThreadId) {\n const res = await client.sendRequest('thread/resume', { threadId: this.lastThreadId }) as { thread: { id: string } };\n threadId = res.thread.id;\n } else {\n const res = await client.sendRequest('thread/start', {\n model: model || undefined,\n cwd: process.cwd(),\n approvalPolicy: 'never',\n sandbox: 'danger-full-access',\n }) as { thread: { id: string } };\n threadId = res.thread.id;\n this.lastThreadId = threadId;\n params.onThreadId?.(threadId);\n }\n\n // 3. Build turn input\n const apiDocs = buildApiDocs(apiBaseUrl, apiToken);\n const systemParts = [systemContext, ...(skipTokenInstructions ? [] : [TOKEN_INSTRUCTIONS]), apiDocs].filter(Boolean);\n const fullSystemContext = systemParts.join('\\n\\n');\n const fullPrompt = (isResume && this.lastThreadId)\n ? prompt\n : `${fullSystemContext}\\n\\n---\\n\\n${prompt}`;\n\n const input: Array<Record<string, unknown>> = [];\n if (images && images.length > 0) {\n for (const img of images) {\n input.push({ type: 'image', url: `data:${img.mimeType};base64,${img.base64}` });\n }\n }\n input.push({ type: 'text', text: fullPrompt });\n\n // 4. Start turn\n const turnRes = await client.sendRequest('turn/start', {\n threadId,\n input,\n model: model || undefined,\n effort: mapEffort(effort),\n approvalPolicy: 'never',\n sandboxPolicy: { type: 'dangerFullAccess' },\n }) as { turn: { id: string; status: string } };\n const turnId = turnRes.turn.id;\n\n // 5. Listen for notifications and resolve on turn/completed\n return new Promise<NodeResult>((resolve, reject) => {\n let settled = false;\n let fullContent = '';\n let thinkingEmitted = false;\n const startedCommandExecutions = new Set<string>();\n const completedCommandExecutions = new Set<string>();\n\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n signal.removeEventListener('abort', onAbort);\n fn();\n };\n\n const handler = (method: string, p: Record<string, unknown>) => {\n if (settled) return;\n\n // Filter by threadId to scope to this conversation\n const notifThreadId = p['threadId'] as string | undefined;\n if (notifThreadId && notifThreadId !== threadId) return;\n\n // Also filter by turnId if present\n const notifTurnId = (p['turnId'] ?? (p['turn'] as Record<string, unknown> | undefined)?.['id']) as string | undefined;\n if (notifTurnId && notifTurnId !== turnId) return;\n\n if (method === 'item/agentMessage/delta') {\n const delta = p['delta'] as string;\n if (delta) {\n thinkingEmitted = false;\n fullContent += delta;\n params.onDelta(delta);\n const { status, message, branchChoice } = parseEndToken(fullContent);\n if (status !== 'none') {\n settle(() => resolve({ output: fullContent, tokenStatus: status, tokenMessage: message, branchChoice }));\n }\n }\n } else if (method === 'item/reasoning/summaryTextDelta' || method === 'item/reasoning/textDelta') {\n const delta = p['delta'] as string;\n if (delta) {\n if (!thinkingEmitted) {\n thinkingEmitted = true;\n params.onStatus('💭 En réflexion…');\n }\n params.onThinking?.(delta);\n }\n } else if (method === 'item/started') {\n const item = p['item'] as Record<string, unknown> | undefined;\n if (!item) return;\n const itemType = item['type'] as string;\n const itemId = item['id'] as string ?? '';\n\n if (itemType === 'commandExecution') {\n const command = typeof item['command'] === 'string' ? item['command'] as string : '';\n const cmdName = getCommandExecutionName(item);\n const effectiveId = itemId || (command ? `cmd-${command.slice(0, 80)}` : '');\n params.onStatus(`🔧 ${cmdName}`);\n if (effectiveId && !startedCommandExecutions.has(effectiveId)) {\n startedCommandExecutions.add(effectiveId);\n params.onToolCall?.(effectiveId, cmdName, getCommandExecutionInput(item));\n }\n } else if (itemType === 'mcpToolCall' || itemType === 'tool_call') {\n const rawName = typeof item['tool'] === 'string' ? item['tool'] as string\n : typeof item['name'] === 'string' ? item['name'] as string : 'tool';\n const server = typeof item['server'] === 'string' ? item['server'] as string : '';\n const displayName = server ? `${server}.${rawName}` : rawName;\n params.onStatus(`🔧 ${displayName}`);\n if (itemId) {\n let toolInput: Record<string, unknown> = {};\n const rawArgs = item['arguments'];\n if (typeof rawArgs === 'string') {\n try { toolInput = JSON.parse(rawArgs) as Record<string, unknown>; } catch { /* keep empty */ }\n } else if (rawArgs && typeof rawArgs === 'object') {\n toolInput = rawArgs as Record<string, unknown>;\n }\n params.onToolCall?.(itemId, displayName, toolInput);\n }\n }\n } else if (method === 'item/completed') {\n const item = p['item'] as Record<string, unknown> | undefined;\n if (!item) return;\n const itemType = item['type'] as string;\n const itemId = item['id'] as string ?? '';\n\n if (itemType === 'commandExecution') {\n const command = typeof item['command'] === 'string' ? item['command'] as string : '';\n const effectiveId = itemId || (command ? `cmd-${command.slice(0, 80)}` : '');\n if (effectiveId && !completedCommandExecutions.has(effectiveId)) {\n completedCommandExecutions.add(effectiveId);\n const exitCode = typeof item['exit_code'] === 'number' ? item['exit_code'] as number : 0;\n params.onToolResult?.(effectiveId, getCommandExecutionResult(item), exitCode !== 0);\n }\n } else if (itemType === 'mcpToolCall' || itemType === 'tool_call') {\n if (itemId) {\n const output = item['output'];\n const result = typeof output === 'string' ? output : (output ? JSON.stringify(output) : '');\n params.onToolResult?.(itemId, result, false);\n }\n }\n } else if (method === 'turn/completed') {\n const turn = p['turn'] as Record<string, unknown> | undefined;\n const error = turn?.['error'] as Record<string, unknown> | undefined;\n if (error) {\n const msg = typeof error['message'] === 'string' ? error['message'] as string : 'Codex turn failed';\n settle(() => reject(new Error(`Codex: ${msg}`)));\n return;\n }\n // Turn finished normally — resolve with accumulated content\n const { status, message, branchChoice } = parseEndToken(fullContent);\n settle(() => resolve({ output: fullContent, tokenStatus: status, tokenMessage: message, branchChoice }));\n } else if (method === 'turn/errored') {\n const error = p['error'] as Record<string, unknown> | undefined;\n const msg = typeof error?.['message'] === 'string' ? error['message'] as string : 'Codex turn errored';\n settle(() => reject(new Error(`Codex: ${msg}`)));\n }\n };\n\n client.onAnyNotification(handler);\n\n const onAbort = () => {\n if (settled) return;\n client.sendRequest('turn/interrupt', { threadId, turnId }).catch(() => { /* best-effort */ });\n settle(() => reject(new Error('Aborted')));\n };\n signal.addEventListener('abort', onAbort, { once: true });\n });\n }\n}\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport Anthropic from '@anthropic-ai/sdk';\nimport OpenAI from 'openai';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { serviceStore } from '../../services/service-store.js';\nimport { agentManager } from '../../services/agent-manager.js';\nimport { getActiveProvider, DEFAULT_MODELS, OPENAI_COMPAT_BASE_URLS } from '../../services/ai-provider-utils.js';\nimport { resolveEffectiveAgentId } from './service.js';\nimport { OptionalProviderIdSchema } from '../shared-schemas.js';\n\nconst SERVICE_ID_SCHEMA = z.string().max(128);\nconst SAFE_PATH_SCHEMA = z\n .string()\n .min(1)\n .max(4096)\n .refine((p) => !p.startsWith('/') && !p.includes('../'), {\n message: 'Path must be relative and not traverse up',\n });\nconst REMOTE_SCHEMA = z.string().min(1).max(128).regex(/^[a-zA-Z0-9_\\-.]+$/);\nconst BRANCH_SCHEMA = z.string().min(1).max(256).regex(/^[a-zA-Z0-9._\\-/]+$/);\n\n/**\n * Resolve the effective agentId and absolute cwd for a service.\n * Throws if service not found or no agent is configured.\n */\nasync function resolveServiceContext(serviceId: string): Promise<{ agentId: string; cwd: string }> {\n const service = await serviceStore.get(serviceId);\n if (!service) {\n throw new TRPCError({ code: 'NOT_FOUND', message: 'Service not found' });\n }\n const agentId = await resolveEffectiveAgentId(service);\n if (!agentId) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'No agent configured for this service' });\n }\n // Pass the raw cwd — the agent resolves $VAR from its own process.env\n return { agentId, cwd: service.cwd || '.' };\n}\n\n// Shared input shape: a git target is EITHER a service (serviceId) OR an agent's\n// own repository (agentId → cwd '.'). The latter lets the AI chat reuse this\n// view against the agent's working directory when no service is attached.\nconst gitTargetShape = {\n serviceId: SERVICE_ID_SCHEMA.optional(),\n agentId: z.string().max(128).optional(),\n};\n\n/**\n * Resolve the effective agentId + cwd from a git target. Prefers serviceId when\n * present; otherwise targets the agent's own working directory (cwd '.').\n */\nasync function resolveGitContext(input: { serviceId?: string; agentId?: string }): Promise<{ agentId: string; cwd: string }> {\n if (input.serviceId) return resolveServiceContext(input.serviceId);\n // No service: target an agent's own working directory (cwd '.'). Fall back to\n // the default agent when no explicit agentId is given (e.g. a chat conversation\n // that let the server pick the agent).\n const agentId = input.agentId ?? agentManager.getDefaultAgentId();\n if (!agentId) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'No agent available' });\n }\n return { agentId, cwd: '.' };\n}\n\nexport const gitRouter = router({\n /** Get full git status */\n status: protectedProcedure\n .input(z.object({ ...gitTargetShape }))\n .query(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentQuery(agentId, 'git.status', { cwd });\n }),\n\n /** Get commit log */\n log: protectedProcedure\n .input(z.object({ ...gitTargetShape,limit: z.number().int().min(1).max(200).default(50) }))\n .query(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentQuery(agentId, 'git.log', { cwd, limit: input.limit });\n }),\n\n /** List local and remote branches */\n branches: protectedProcedure\n .input(z.object({ ...gitTargetShape }))\n .query(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentQuery(agentId, 'git.branches', { cwd });\n }),\n\n /** Checkout a branch */\n checkout: protectedProcedure\n .input(z.object({ ...gitTargetShape,branch: BRANCH_SCHEMA, create: z.boolean().default(false) }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentMutation(agentId, 'git.checkout', { cwd, branch: input.branch, create: input.create });\n }),\n\n /** Stage files */\n stage: protectedProcedure\n .input(z.object({ ...gitTargetShape,paths: z.array(SAFE_PATH_SCHEMA).min(1).max(500) }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentMutation(agentId, 'git.stage', { cwd, paths: input.paths });\n }),\n\n /** Stage all files */\n stageAll: protectedProcedure\n .input(z.object({ ...gitTargetShape }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentMutation(agentId, 'git.stageAll', { cwd });\n }),\n\n /** Unstage files */\n unstage: protectedProcedure\n .input(z.object({ ...gitTargetShape,paths: z.array(SAFE_PATH_SCHEMA).min(1).max(500) }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentMutation(agentId, 'git.unstage', { cwd, paths: input.paths });\n }),\n\n /** Unstage all files */\n unstageAll: protectedProcedure\n .input(z.object({ ...gitTargetShape }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentMutation(agentId, 'git.unstageAll', { cwd });\n }),\n\n /** Commit staged changes */\n commit: protectedProcedure\n .input(z.object({ ...gitTargetShape,message: z.string().min(1).max(4096) }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentMutation(agentId, 'git.commit', { cwd, message: input.message });\n }),\n\n /** Push to remote */\n push: protectedProcedure\n .input(z.object({ ...gitTargetShape,remote: REMOTE_SCHEMA.default('origin'), setUpstream: z.boolean().default(false) }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentMutation(agentId, 'git.push', { cwd, remote: input.remote, setUpstream: input.setUpstream });\n }),\n\n /** Pull from remote */\n pull: protectedProcedure\n .input(z.object({ ...gitTargetShape,remote: REMOTE_SCHEMA.default('origin') }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentMutation(agentId, 'git.pull', { cwd, remote: input.remote });\n }),\n\n /** Fetch from remote */\n fetch: protectedProcedure\n .input(z.object({ ...gitTargetShape,remote: REMOTE_SCHEMA.default('origin') }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentMutation(agentId, 'git.fetch', { cwd, remote: input.remote });\n }),\n\n /** Get diff for a file or the whole index */\n diff: protectedProcedure\n .input(z.object({\n ...gitTargetShape,\n path: z.string().max(4096).optional(),\n staged: z.boolean().default(false),\n untracked: z.boolean().default(false),\n }))\n .query(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentQuery(agentId, 'git.diff', { cwd, path: input.path, staged: input.staged, untracked: input.untracked });\n }),\n\n /** Discard changes to working tree files */\n discard: protectedProcedure\n .input(z.object({ ...gitTargetShape,paths: z.array(SAFE_PATH_SCHEMA).min(1).max(500) }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentMutation(agentId, 'git.discard', { cwd, paths: input.paths });\n }),\n\n /** Generate a commit message from staged diffs using AI (diff fetched from agent, AI runs on server) */\n generateCommitMessage: protectedProcedure\n .input(z.object({ ...gitTargetShape, providerId: OptionalProviderIdSchema, model: z.string().max(200).optional() }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n const { diff } = await agentManager.agentQuery<{ diff: string }>(agentId, 'git.stagedDiff', { cwd });\n\n if (!diff.trim()) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'No staged changes to generate a commit message from' });\n }\n\n // Falls back to the default (active) provider when the caller doesn't pick one.\n const active = await getActiveProvider(input.providerId);\n if (!active) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'No AI provider configured' });\n }\n\n const systemPrompt = `You are a git commit message generator. Given a git diff, write a concise and meaningful conventional commit message (e.g. feat:, fix:, refactor:, chore:, docs:, style:, test:).\nRules:\n- First line: type(optional scope): short summary (max 72 chars)\n- Optionally add a blank line and a brief body if the changes are complex\n- Write in English\n- Return ONLY the commit message, nothing else`;\n\n const { provider, plaintextKey } = active;\n const model = input.model || provider.model || DEFAULT_MODELS[provider.provider] || 'claude-opus-4-6';\n\n if (provider.provider === 'anthropic') {\n const client = new Anthropic({ apiKey: plaintextKey });\n const res = await client.messages.create({\n model,\n max_tokens: 512,\n system: systemPrompt,\n messages: [{ role: 'user', content: diff }],\n });\n const block = res.content[0];\n return { message: block?.type === 'text' ? block.text.trim() : '' };\n }\n\n if (provider.provider in OPENAI_COMPAT_BASE_URLS) {\n const baseURL = OPENAI_COMPAT_BASE_URLS[provider.provider]!;\n const client = new OpenAI({ apiKey: plaintextKey || 'ollama', baseURL });\n const res = await client.chat.completions.create({\n model,\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: diff },\n ],\n });\n return { message: res.choices[0]?.message?.content?.trim() ?? '' };\n }\n\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Unsupported AI provider' });\n }),\n\n /** Merge a branch into the current branch */\n merge: protectedProcedure\n .input(z.object({ ...gitTargetShape,branch: BRANCH_SCHEMA, noFf: z.boolean().default(false) }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentMutation(agentId, 'git.merge', { cwd, branch: input.branch, noFf: input.noFf });\n }),\n\n /** Rebase current branch onto another branch */\n rebase: protectedProcedure\n .input(z.object({ ...gitTargetShape,branch: BRANCH_SCHEMA }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentMutation(agentId, 'git.rebase', { cwd, branch: input.branch });\n }),\n\n /** List stash entries */\n stashList: protectedProcedure\n .input(z.object({ ...gitTargetShape }))\n .query(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentQuery(agentId, 'git.stashList', { cwd });\n }),\n\n /** Stash current changes */\n stashPush: protectedProcedure\n .input(z.object({ ...gitTargetShape,message: z.string().max(4096).optional(), includeUntracked: z.boolean().default(true) }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentMutation(agentId, 'git.stashPush', { cwd, message: input.message, includeUntracked: input.includeUntracked });\n }),\n\n /** Pop a stash entry */\n stashPop: protectedProcedure\n .input(z.object({ ...gitTargetShape,index: z.number().int().min(0).max(1000).default(0) }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentMutation(agentId, 'git.stashPop', { cwd, index: input.index });\n }),\n\n /** Apply a stash entry without dropping it */\n stashApply: protectedProcedure\n .input(z.object({ ...gitTargetShape,index: z.number().int().min(0).max(1000).default(0) }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentMutation(agentId, 'git.stashApply', { cwd, index: input.index });\n }),\n\n /** Drop a stash entry */\n stashDrop: protectedProcedure\n .input(z.object({ ...gitTargetShape,index: z.number().int().min(0).max(1000).default(0) }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentMutation(agentId, 'git.stashDrop', { cwd, index: input.index });\n }),\n\n /** Watch .git/ for changes and stream updated status */\n onStatusChange: protectedProcedure\n .input(z.object({ ...gitTargetShape }))\n .subscription(async function* ({ input }) {\n const { agentId, cwd } = await resolveGitContext(input);\n\n const queue: unknown[] = [];\n let resolve: (() => void) | null = null;\n let done = false;\n\n let unsubscribe: (() => void) | undefined;\n try {\n unsubscribe = agentManager.agentSubscribe(\n agentId,\n 'git.onStatusChange',\n { cwd },\n (data) => {\n queue.push(data);\n if (resolve) { resolve(); resolve = null; }\n },\n () => {\n done = true;\n if (resolve) { resolve(); resolve = null; }\n },\n );\n } catch (err) {\n throw new TRPCError({\n code: 'BAD_REQUEST',\n message: `Cannot subscribe to git status: ${(err as Error).message}`,\n });\n }\n\n try {\n while (!done || queue.length > 0) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n unsubscribe?.();\n }\n }),\n\n /** List remotes */\n remotes: protectedProcedure\n .input(z.object({ ...gitTargetShape }))\n .query(async ({ input }) => {\n const { agentId, cwd } = await resolveGitContext(input);\n return agentManager.agentQuery(agentId, 'git.remotes', { cwd });\n }),\n});\n","import { randomUUID } from 'node:crypto';\nimport { TRPCError } from '@trpc/server';\nimport { z } from 'zod';\nimport { ScenarioNodeSchema, ScenarioGroupSchema } from '@runeya/packages-shared';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { createOrBadRequest, deleteOrNotFound, getOrNotFound, updateOrThrow } from '../crud-procedure-utils.js';\nimport { streamWithActiveProvider } from '../ai-generation-procedure-utils.js';\nimport {\n ConversationIdSchema,\n DescriptionSchema,\n Id128Schema,\n NameSchema,\n OptionalProviderIdSchema,\n} from '../shared-schemas.js';\nimport { scenarioStore } from '../../services/scenario-store.js';\nimport { scenarioRunStore } from '../../services/scenario-run-store.js';\nimport { runScenario, tapBus, isScenarioRunning, abortScenario, resolveNodeInput } from '../../services/scenario-runner.js';\nimport { listPresets, getPreset } from '../../services/scenario-presets.js';\n\n// ─── AI generation helpers ────────────────────────────────────────────────────\n\nconst SCENARIO_SYSTEM_PROMPT = `You are an scenario org-chart builder assistant. You generate JSON structures representing an scenario hierarchy.\n\nIMPORTANT: Respond with ONLY a valid JSON object. No markdown, no code fences, no explanation. Pure JSON only.\n\nOutput schema:\n{\n \"leaderId\": \"string — id of the leader node\",\n \"groups\": [{ \"id\": \"string\", \"name\": \"string\", \"position\": { \"x\": number, \"y\": number }, \"width\": number, \"height\": number }],\n \"nodes\": [{ \"id\": \"string\", \"label\": \"string\", \"role\": \"manager|engineer|designer|analyst|qa|devops|product|writer|researcher|other\", \"groupId\": \"string (must match a group id)\", \"parentId\": \"string|null (null only for the leader)\", \"prompt\": \"string — detailed role description and instructions for this AI agent\", \"autoGenerated\": true, \"canAddNode\": false, \"position\": { \"x\": number, \"y\": number } }]\n}\n\nRules:\n- Every node MUST have a groupId that references an existing group id.\n- Exactly one node is the leader: parentId=null, their id = leaderId.\n- All other nodes MUST have parentId set to their manager's id.\n- The leader MUST always be in the group with id \"group-management\" and name \"Management\".\n- The leader MUST always have role \"manager\".\n- Use role to reflect each node's actual function: managers coordinate and delegate (never implement), engineers write code, etc.\n- Use short readable ids: \"group-engineering\", \"node-alice\", etc.\n- Groups: position spaced 400px apart (e.g. x=0, x=400, x=800). width >= 300, height >= 200.\n- Nodes positions are relative to their group: x/y in 30-260 range.\n- The \"prompt\" field must be detailed: role, responsibilities, communication style, expected outputs.`;\n\nfunction buildScenarioUserMessage(\n userPrompt: string,\n current?: { leaderId: string; groups: unknown[]; nodes: unknown[] },\n): string {\n if (current && (current.groups.length > 0 || current.nodes.length > 0)) {\n return `Current scenario:\\n${JSON.stringify(current, null, 2)}\\n\\nUser request: ${userPrompt}\\n\\nModify the scenario. Keep existing ids when possible.`;\n }\n return `Generate an scenario org-chart based on: ${userPrompt}`;\n}\n\nexport const scenarioRouter = router({\n list: protectedProcedure.query(() => scenarioStore.list()),\n\n get: protectedProcedure\n .input(z.object({ id: Id128Schema }))\n .query(({ input }) => getOrNotFound(() => scenarioStore.get(input.id), 'Scenario not found')),\n\n create: protectedProcedure\n .input(z.object({\n name: NameSchema,\n icon: z.string().max(64).optional(),\n description: DescriptionSchema.optional(),\n leaderId: Id128Schema,\n groups: z.array(ScenarioGroupSchema).max(100).optional(),\n nodes: z.array(ScenarioNodeSchema).min(1).max(500),\n traversalMode: z.enum(['hierarchical', 'topological']).optional(),\n presetId: z.string().max(128).optional(),\n isPublished: z.boolean().optional(),\n }))\n .mutation(({ input }) => {\n const now = Date.now();\n return createOrBadRequest(() => scenarioStore.create({\n id: randomUUID(),\n name: input.name,\n icon: input.icon,\n description: input.description,\n leaderId: input.leaderId,\n groups: input.groups ?? [],\n nodes: input.nodes,\n traversalMode: input.traversalMode ?? 'hierarchical',\n presetId: input.presetId,\n isPublished: input.isPublished ?? false,\n createdAt: now,\n updatedAt: now,\n }));\n }),\n\n update: protectedProcedure\n .input(z.object({\n id: Id128Schema,\n name: NameSchema.optional(),\n icon: z.string().max(64).optional(),\n description: DescriptionSchema.optional(),\n leaderId: Id128Schema.optional(),\n groups: z.array(ScenarioGroupSchema).max(100).optional(),\n nodes: z.array(ScenarioNodeSchema).min(1).max(500).optional(),\n traversalMode: z.enum(['hierarchical', 'topological']).optional(),\n presetId: z.string().max(128).optional(),\n isPublished: z.boolean().optional(),\n }))\n .mutation(({ input }) => updateOrThrow(\n () => scenarioStore.update(input.id, {\n name: input.name,\n icon: input.icon,\n description: input.description,\n leaderId: input.leaderId,\n groups: input.groups,\n nodes: input.nodes,\n traversalMode: input.traversalMode,\n presetId: input.presetId,\n isPublished: input.isPublished,\n updatedAt: Date.now(),\n }),\n 'Scenario not found',\n )),\n\n delete: protectedProcedure\n .input(z.object({ id: Id128Schema }))\n .mutation(({ input }) => deleteOrNotFound(() => scenarioStore.delete(input.id), 'Scenario not found')),\n\n run: protectedProcedure\n .input(z.object({\n conversationId: ConversationIdSchema,\n scenarioId: Id128Schema,\n userRequest: z.string().max(100_000),\n runnerOverride: z.enum(['claude-code', 'codex']).optional(),\n modelOverride: Id128Schema.optional(),\n agentId: Id128Schema.optional(),\n resume: z.boolean().optional(),\n }))\n .subscription(async function* ({ input, signal }) {\n const scenario = await scenarioStore.get(input.scenarioId);\n if (!scenario) throw new TRPCError({ code: 'NOT_FOUND', message: 'Scenario not found' });\n\n // Start only on explicit user request or resume.\n // Reconnect/resubscribe paths pass an empty request and must never restart runs.\n const canStart = input.userRequest.trim().length > 0 || !!input.resume;\n if (!isScenarioRunning(input.conversationId) && canStart) {\n // On resume, load original user request from workspace if not provided\n let userRequest = input.userRequest;\n if (input.resume && !userRequest.trim()) {\n userRequest = await scenarioRunStore.readUserRequest(input.conversationId) ?? '';\n }\n void runScenario(input.conversationId, input.scenarioId, userRequest, {\n runnerOverride: input.runnerOverride,\n modelOverride: input.modelOverride,\n agentId: input.agentId,\n }, !!input.resume);\n // Small yield to let the bus be created before tapping\n await new Promise(r => setTimeout(r, 10));\n }\n\n // Tap into the live event bus (replays buffer for late subscribers)\n yield* tapBus(input.conversationId, signal ?? new AbortController().signal);\n }),\n\n stop: protectedProcedure\n .input(z.object({ conversationId: ConversationIdSchema }))\n .mutation(({ input }) => {\n abortScenario(input.conversationId);\n return { ok: true };\n }),\n\n sendNodeInput: protectedProcedure\n .input(z.object({\n conversationId: ConversationIdSchema,\n nodeId: Id128Schema,\n text: z.string().min(1).max(100_000),\n }))\n .mutation(({ input }) => {\n const resolved = resolveNodeInput(input.conversationId, input.nodeId, input.text);\n if (!resolved) throw new TRPCError({ code: 'NOT_FOUND', message: 'No pending input request for this node' });\n return { ok: true };\n }),\n\n isRunning: protectedProcedure\n .input(z.object({ conversationId: ConversationIdSchema }))\n .query(({ input }) => ({ running: isScenarioRunning(input.conversationId) })),\n\n runState: protectedProcedure\n .input(z.object({ conversationId: ConversationIdSchema }))\n .query(({ input }) => {\n const runState = scenarioRunStore.getRunState(input.conversationId);\n return runState ?? { nodeStates: {}, nodeOutputs: {}, activeNodeId: undefined };\n }),\n\n getPersistedRunState: protectedProcedure\n .input(z.object({ conversationId: ConversationIdSchema }))\n .query(async ({ input }) => {\n return await scenarioRunStore.loadPersistedRunState(input.conversationId);\n }),\n\n getReadme: protectedProcedure\n .input(z.object({ conversationId: ConversationIdSchema }))\n .query(async ({ input }) => {\n return await scenarioRunStore.readReadme(input.conversationId);\n }),\n\n getSnapshot: protectedProcedure\n .input(z.object({ conversationId: ConversationIdSchema }))\n .query(async ({ input }) => {\n return await scenarioRunStore.loadScenarioSnapshot(input.conversationId);\n }),\n\n streamGenerateWithAI: protectedProcedure\n .input(z.object({\n prompt: z.string().min(1).max(10_000),\n providerId: OptionalProviderIdSchema,\n model: z.string().max(200).optional(),\n current: z.object({\n leaderId: Id128Schema,\n groups: z.array(ScenarioGroupSchema).max(100),\n nodes: z.array(ScenarioNodeSchema).max(500),\n }).optional(),\n }))\n .subscription(async function* ({ input, signal }) {\n const userMessage = buildScenarioUserMessage(input.prompt, input.current);\n yield* streamWithActiveProvider({\n providerId: input.providerId,\n model: input.model,\n systemPrompt: SCENARIO_SYSTEM_PROMPT,\n userMessage,\n maxTokens: 8192,\n signal: signal ?? undefined,\n });\n }),\n\n streamRunEvents: protectedProcedure\n .input(z.object({ conversationId: ConversationIdSchema }))\n .subscription(async function* ({ input }) {\n const convId = input.conversationId;\n // For now, yield the current state once\n // In a real implementation, this would track state changes over time\n const runState = scenarioRunStore.getRunState(convId);\n if (runState) {\n for (const [nodeId, state] of Object.entries(runState.nodeStates)) {\n yield { type: 'node_state' as const, nodeId, state };\n }\n }\n }),\n\n /**\n * Returns the Claude Code session-id + agent-id for a node, so the UI can\n * open a debug PTY with `claude --resume <sessionId>` on the right agent.\n * Falls back to the persisted run-state for past nodes.\n */\n getNodeSession: protectedProcedure\n .input(z.object({\n conversationId: ConversationIdSchema,\n nodeId: Id128Schema,\n }))\n .query(async ({ input }) => {\n return await scenarioRunStore.getNodeSessionPersistent(input.conversationId, input.nodeId);\n }),\n\n listPresets: protectedProcedure.query(() => listPresets()),\n\n getPreset: protectedProcedure\n .input(z.object({ id: Id128Schema }))\n .query(({ input }) => {\n const preset = getPreset(input.id);\n if (!preset) throw new TRPCError({ code: 'NOT_FOUND', message: 'Preset not found' });\n return preset;\n }),\n});\n","import { TRPCError } from '@trpc/server';\n\nexport async function getOrNotFound<T>(\n getter: () => Promise<T | null>,\n notFoundMessage: string,\n): Promise<T> {\n const entity = await getter();\n if (!entity) throw new TRPCError({ code: 'NOT_FOUND', message: notFoundMessage });\n return entity;\n}\n\nexport async function createOrBadRequest<T>(creator: () => Promise<T>): Promise<T> {\n try {\n return await creator();\n } catch (err) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: (err as Error).message });\n }\n}\n\nexport async function updateOrThrow<T>(\n updater: () => Promise<T | null>,\n notFoundMessage: string,\n): Promise<T> {\n try {\n const entity = await updater();\n if (!entity) throw new TRPCError({ code: 'NOT_FOUND', message: notFoundMessage });\n return entity;\n } catch (err) {\n if (err instanceof TRPCError) throw err;\n throw new TRPCError({ code: 'BAD_REQUEST', message: (err as Error).message });\n }\n}\n\nexport async function deleteOrNotFound(\n deleter: () => Promise<boolean>,\n notFoundMessage: string,\n): Promise<{ ok: true }> {\n const deleted = await deleter();\n if (!deleted) throw new TRPCError({ code: 'NOT_FOUND', message: notFoundMessage });\n return { ok: true };\n}\n","import { TRPCError } from '@trpc/server';\nimport { streamProviderText } from '../services/ai-generation.js';\nimport { DEFAULT_MODELS, getActiveProvider } from '../services/ai-provider-utils.js';\n\ninterface ActiveProviderGenerationOptions {\n providerId?: string;\n /** Overrides the provider's configured model when the caller picked one. */\n model?: string;\n systemPrompt: string;\n userMessage: string;\n maxTokens?: number;\n signal?: AbortSignal;\n}\n\nexport async function* streamWithActiveProvider(\n opts: ActiveProviderGenerationOptions,\n): AsyncGenerator<{ type: 'delta' | 'done'; text: string }> {\n const active = await getActiveProvider(opts.providerId);\n if (!active) throw new TRPCError({ code: 'BAD_REQUEST', message: 'Aucun fournisseur IA configuré' });\n\n const { provider, plaintextKey } = active;\n const model = opts.model || provider.model || DEFAULT_MODELS[provider.provider] || '';\n\n try {\n for await (const text of streamProviderText({\n provider,\n plaintextKey,\n model,\n systemPrompt: opts.systemPrompt,\n userMessage: opts.userMessage,\n maxTokens: opts.maxTokens,\n signal: opts.signal,\n })) {\n yield { type: 'delta', text };\n }\n yield { type: 'done', text: '' };\n } catch (err) {\n if (String((err as Error)?.message ?? '').startsWith('Unsupported provider:')) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: `Fournisseur non supporté: ${provider.provider}` });\n }\n throw err;\n }\n}\n","import Anthropic from '@anthropic-ai/sdk';\nimport OpenAI from 'openai';\nimport type { AIProvider } from '@runeya/packages-shared';\nimport { OPENAI_COMPAT_BASE_URLS } from './ai-provider-utils.js';\n\nexport interface ProviderGenerationInput {\n provider: AIProvider;\n plaintextKey: string;\n model: string;\n systemPrompt: string;\n userMessage: string;\n maxTokens?: number;\n signal?: AbortSignal;\n}\n\nexport async function* streamProviderText(input: ProviderGenerationInput): AsyncGenerator<string> {\n const {\n provider,\n plaintextKey,\n model,\n systemPrompt,\n userMessage,\n maxTokens = 8192,\n signal,\n } = input;\n\n if (provider.provider === 'anthropic') {\n const client = new Anthropic({ apiKey: plaintextKey });\n const stream = client.messages.stream({\n model,\n max_tokens: maxTokens,\n system: systemPrompt,\n messages: [{ role: 'user', content: userMessage }],\n });\n for await (const event of stream) {\n if (signal?.aborted) return;\n if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') {\n yield event.delta.text;\n }\n }\n return;\n }\n\n if (provider.provider in OPENAI_COMPAT_BASE_URLS) {\n const baseURL = OPENAI_COMPAT_BASE_URLS[provider.provider]!;\n const client = new OpenAI({ apiKey: plaintextKey || 'ollama', baseURL });\n const stream = await client.chat.completions.create({\n model,\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userMessage },\n ],\n stream: true,\n max_tokens: maxTokens,\n }, { signal: signal ?? undefined });\n for await (const chunk of stream) {\n if (signal?.aborted) return;\n const text = chunk.choices[0]?.delta?.content;\n if (text) yield text;\n }\n return;\n }\n\n throw new Error(`Unsupported provider: ${provider.provider}`);\n}\n","import { mkdir } from 'node:fs/promises';\nimport { randomUUID } from 'node:crypto';\nimport { join } from 'node:path';\nimport { scenarioStore } from './scenario-store.js';\nimport { scenarioRunStore, type NodeState } from './scenario-run-store.js';\nimport type { Scenario, ScenarioNode } from '@runeya/packages-shared';\nimport { getPreset } from './scenario-presets.js';\nimport { atomicWriteSecure, resolveConversationRunDir } from './run-store-utils.js';\nimport { ClaudeCodeRunner } from './ai-runners/claude-code-runner.js';\nimport { CodexRunner } from './ai-runners/codex-runner.js';\nimport type { AiRunner } from './ai-runners/ai-runner.js';\nimport { agentManager } from './agent-manager.js';\n\nconst DEFAULT_NODE_MODELS: Record<'claude-code' | 'codex', string> = {\n 'claude-code': 'sonnet',\n codex: '',\n};\n\nexport interface ScenarioRunOverrides {\n runnerOverride?: 'claude-code' | 'codex';\n modelOverride?: string;\n agentId?: string;\n}\n\n// ─── Event types ──────────────────────────────────────────────────────────────\n\nexport type ScenarioEvent =\n | { type: 'node_started'; nodeId: string }\n | { type: 'node_delta'; nodeId: string; text: string }\n | { type: 'node_status'; nodeId: string; text: string }\n | { type: 'node_tool_call'; nodeId: string; id: string; name: string; input: Record<string, unknown>; rawInput?: string }\n | { type: 'node_tool_result'; nodeId: string; id: string; result: string; isError: boolean }\n | { type: 'node_thinking'; nodeId: string; text: string }\n | { type: 'node_command'; nodeId: string; command: string }\n | { type: 'node_duration'; nodeId: string; durationMs: number }\n | { type: 'node_done'; nodeId: string; output: string; state: string }\n | { type: 'node_state_change'; nodeId: string; state: string }\n | { type: 'node_error'; nodeId: string; error: string }\n | { type: 'node_waiting_input'; nodeId: string; question: string }\n | { type: 'node_prompt'; nodeId: string; label: string; systemContext: string; userMessage: string }\n | { type: 'readme_append'; text: string }\n | { type: 'scenario_complete'; summary: string }\n | { type: 'scenario_error'; error: string };\n\n// ─── Event bus ────────────────────────────────────────────────────────────────\n\nconst MAX_BUFFER = 500;\n\ninterface RunBus {\n buffer: ScenarioEvent[];\n /** Absolute index of buffer[0] in the full event stream */\n baseIndex: number;\n listeners: Set<(evt: ScenarioEvent | null) => void>;\n done: boolean;\n}\n\nconst activeBuses = new Map<string, RunBus>();\nconst activeAbortControllers = new Map<string, AbortController>();\n\nfunction formatTs(): string {\n const d = new Date();\n const off = -d.getTimezoneOffset();\n const sign = off >= 0 ? '+' : '-';\n const pad2 = (n: number) => String(n).padStart(2, '0');\n return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())} ${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())} ${sign}${pad2(Math.floor(Math.abs(off) / 60))}:${pad2(Math.abs(off) % 60)}`;\n}\n\n// ─── Pending user-input requests (keyed by conversationId:nodeId) ──────────\n\nconst pendingNodeInputs = new Map<string, (text: string) => void>();\n\nfunction pendingNodeKey(conversationId: string, nodeId: string) {\n return `${conversationId}:${nodeId}`;\n}\n\n/** Called by scenario.sendNodeInput tRPC mutation when the user submits their reply. */\nexport function resolveNodeInput(conversationId: string, nodeId: string, text: string): boolean {\n const key = pendingNodeKey(conversationId, nodeId);\n const resolver = pendingNodeInputs.get(key);\n if (!resolver) return false;\n pendingNodeInputs.delete(key);\n resolver(text);\n return true;\n}\n\nfunction createBus(conversationId: string): RunBus {\n const bus: RunBus = { buffer: [], baseIndex: 0, listeners: new Set(), done: false };\n activeBuses.set(conversationId, bus);\n return bus;\n}\n\n// Events that are only useful in real-time and should not be replayed to late subscribers\nconst NO_BUFFER_EVENTS = new Set<ScenarioEvent['type']>(['node_status', 'node_thinking']);\n\nfunction publishToBus(bus: RunBus, evt: ScenarioEvent | null): void {\n if (evt !== null) {\n if (!NO_BUFFER_EVENTS.has(evt.type)) {\n bus.buffer.push(evt);\n while (bus.buffer.length > MAX_BUFFER) {\n const idx = bus.buffer.findIndex(e => e.type === 'node_delta');\n bus.buffer.splice(idx >= 0 ? idx : 0, 1);\n bus.baseIndex += 1;\n }\n }\n } else {\n bus.done = true;\n }\n for (const listener of bus.listeners) listener(evt);\n bus.listeners.clear();\n}\n\nexport async function* tapBus(conversationId: string, signal: AbortSignal): AsyncGenerator<ScenarioEvent> {\n const bus = activeBuses.get(conversationId);\n if (!bus) return;\n\n let cursor = bus.baseIndex;\n\n while (true) {\n if (cursor < bus.baseIndex) {\n // Buffer rotated (old events dropped). Jump forward to oldest still available.\n cursor = bus.baseIndex;\n }\n while (cursor < bus.baseIndex + bus.buffer.length) {\n const evt = bus.buffer[cursor - bus.baseIndex]!;\n cursor += 1;\n yield evt;\n }\n if (bus.done) return;\n if (signal.aborted) return;\n\n await new Promise<void>((resolve) => {\n const onAbort = () => {\n bus.listeners.delete(notify);\n resolve();\n };\n const notify = () => {\n signal.removeEventListener('abort', onAbort);\n resolve();\n };\n bus.listeners.add(notify);\n signal.addEventListener('abort', onAbort, { once: true });\n // Race guard: if an event was published between the last buffer drain and\n // listener registration, wake immediately instead of waiting forever.\n if (cursor < bus.baseIndex + bus.buffer.length || bus.done || signal.aborted) {\n bus.listeners.delete(notify);\n signal.removeEventListener('abort', onAbort);\n resolve();\n }\n });\n }\n}\n\nexport function isScenarioRunning(conversationId: string): boolean {\n const bus = activeBuses.get(conversationId);\n return bus !== undefined && !bus.done;\n}\n\nexport function abortScenario(conversationId: string): boolean {\n const ctrl = activeAbortControllers.get(conversationId);\n if (!ctrl) return false;\n ctrl.abort();\n return true;\n}\n\n// ─── Hierarchy helpers ────────────────────────────────────────────────────────\n\nconst FINISHED_STATES = new Set(['done', 'error', 'synthesized']);\nconst MAX_MANAGER_REVIEW_ROUNDS = Infinity;\n\n/**\n * After a BFS level completes, promote any 'waiting' ancestor to 'done'\n * if all their descendants (recursively) are now in a finished state.\n */\nfunction resolveWaitingStates(\n nodes: ScenarioNode[],\n conversationId: string,\n byParent: Map<string, ScenarioNode[]>,\n publish: (evt: ScenarioEvent) => void,\n skipNodeIds: Set<string> = new Set(),\n): void {\n function allDescendantsDone(nodeId: string): boolean {\n for (const child of byParent.get(nodeId) ?? []) {\n const s = scenarioRunStore.getRunState(conversationId)?.nodeStates[child.id];\n if (!s || !FINISHED_STATES.has(s)) return false;\n if (!allDescendantsDone(child.id)) return false;\n }\n return true;\n }\n\n for (const node of nodes) {\n if (skipNodeIds.has(node.id)) continue;\n const s = scenarioRunStore.getRunState(conversationId)?.nodeStates[node.id];\n if (s === 'waiting' && allDescendantsDone(node.id)) {\n scenarioRunStore.setNodeState(conversationId, node.id, 'done');\n publish({ type: 'node_state_change', nodeId: node.id, state: 'done' });\n }\n }\n}\n\nfunction normalizeForMatch(value: string): string {\n return value\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, ' ')\n .trim();\n}\n\nfunction getDirectReports(nodes: ScenarioNode[], managerId: string): ScenarioNode[] {\n return nodes.filter((p) => p.parentIds[0] === managerId);\n}\n\n/**\n * Parse <next_person> directives from AI output.\n *\n * Supported forms:\n * <next_person name=\"Alice Martin\">specific instruction (multiline ok)</next_person>\n * <next_person name=\"STOP\" />\n */\nfunction parseRuneyaNextNodeDirectives(output: string): { name: string; instruction: string | null }[] {\n const results: { name: string; instruction: string | null }[] = [];\n // Self-closing form: <next_person name=\"STOP\" />\n for (const m of output.matchAll(/<next_person\\s+name=\"([^\"]*?)\"\\s*\\/>/g)) {\n results.push({ name: m[1].trim(), instruction: null });\n }\n // Content form: <next_person name=\"Alice\">instruction</next_person>\n for (const m of output.matchAll(/<next_person\\s+name=\"([^\"]*?)\">([\\s\\S]*?)<\\/next_person>/g)) {\n results.push({ name: m[1].trim(), instruction: m[2].trim() || null });\n }\n return results;\n}\n\ninterface HireDirectivePayload {\n label: string;\n role: string;\n prompt: string;\n}\n\n/**\n * Parse <hire_person> directives from AI output.\n *\n * <hire_person label=\"Jane Doe\" role=\"engineer\">Task focus prompt</hire_person>\n */\nfunction parseRuneyaHireDirectives(output: string): HireDirectivePayload[] {\n const results: HireDirectivePayload[] = [];\n for (const m of output.matchAll(/<hire_person\\s+label=\"([^\"]*?)\"\\s+role=\"([^\"]*?)\">([\\s\\S]*?)<\\/hire_person>/g)) {\n const label = m[1].trim();\n const role = m[2].trim();\n const prompt = m[3].trim();\n if (label && role && prompt) results.push({ label, role, prompt });\n }\n return results;\n}\n\nconst HIRE_LAYOUT = {\n startY: 88,\n siblingGap: 24,\n minXInTeam: 20,\n minYInTeam: 36,\n nodeWidthEstimate: 180,\n nodeHeightEstimate: 50,\n groupRightPadding: 24,\n groupBottomPadding: 28,\n minGroupWidth: 300,\n minGroupHeight: 200,\n} as const;\n\nfunction computeHirePosition(manager: ScenarioNode, nodes: ScenarioNode[]): { x: number; y: number } {\n const sameTeamReports = nodes.filter((p) => p.parentIds[0] === manager.id && p.groupId === (manager.groupId ?? null));\n const managerX = Number.isFinite(manager.position?.x) ? manager.position.x : 140;\n const managerY = Number.isFinite(manager.position?.y) ? manager.position.y : 40;\n const baseY = managerY + HIRE_LAYOUT.startY;\n const rightMost = sameTeamReports\n .filter((p) => Number.isFinite(p.position?.x))\n .sort((a, b) => (a.position?.x ?? 0) - (b.position?.x ?? 0))\n .at(-1);\n\n let x = managerX;\n let y = baseY;\n if (rightMost) {\n x = (rightMost.position?.x ?? managerX) + HIRE_LAYOUT.nodeWidthEstimate + HIRE_LAYOUT.siblingGap;\n y = Math.max(baseY, rightMost.position?.y ?? baseY);\n }\n\n if (manager.groupId) {\n x = Math.max(HIRE_LAYOUT.minXInTeam, x);\n y = Math.max(HIRE_LAYOUT.minYInTeam, y);\n } else {\n x = Math.max(0, x);\n y = Math.max(0, y);\n }\n\n return { x, y };\n}\n\nfunction ensureGroupCanContainNode(scenario: Scenario, groupId: string | null, position: { x: number; y: number }): void {\n if (!groupId) return;\n const group = scenario.groups.find((t) => t.id === groupId);\n if (!group) return;\n\n const width = Number.isFinite(group.width) ? group.width : HIRE_LAYOUT.minGroupWidth;\n const height = Number.isFinite(group.height) ? group.height : HIRE_LAYOUT.minGroupHeight;\n\n const neededWidth = position.x + HIRE_LAYOUT.nodeWidthEstimate + HIRE_LAYOUT.groupRightPadding;\n const neededHeight = position.y + HIRE_LAYOUT.nodeHeightEstimate + HIRE_LAYOUT.groupBottomPadding;\n\n group.width = Math.max(width, HIRE_LAYOUT.minGroupWidth, neededWidth);\n group.height = Math.max(height, HIRE_LAYOUT.minGroupHeight, neededHeight);\n}\n\nfunction applyHireDirectivesFromOutput(\n manager: ScenarioNode,\n scenario: Scenario,\n output: string,\n): ScenarioNode[] {\n const hireDirectives = parseRuneyaHireDirectives(output);\n if (hireDirectives.length === 0) return [];\n if (!manager.canAddNode) {\n throw new Error(`${manager.label} attempted to hire without permission`);\n }\n\n const hired: ScenarioNode[] = [];\n for (const payload of hireDirectives) {\n const id = `hire-${randomUUID().slice(0, 8)}`;\n const position = computeHirePosition(manager, scenario.nodes);\n ensureGroupCanContainNode(scenario, manager.groupId ?? null, position);\n const node: ScenarioNode = {\n id,\n type: 'ai',\n parentIds: [manager.id],\n groupId: manager.groupId ?? null,\n label: payload.label,\n role: payload.role,\n prompt: payload.prompt,\n question: '',\n autoGenerated: true,\n canAddNode: false,\n aiCli: manager.aiCli ?? 'claude-code',\n model: '',\n position,\n injectParentOutputs: false,\n injectedAncestorIds: [],\n };\n scenario.nodes.push(node);\n hired.push(node);\n }\n return hired;\n}\n\nfunction selectExplicitDirectReportsFromOutput(\n manager: ScenarioNode,\n nodes: ScenarioNode[],\n managerOutput: string,\n): { selected: ScenarioNode[]; unknownNames: string[]; assignments: Map<string, string>; missingAssignments: string[] } {\n const directReports = getDirectReports(nodes, manager.id);\n\n const directives = parseRuneyaNextNodeDirectives(managerOutput);\n const normalizedDirectives = directives.map((d) => ({ norm: normalizeForMatch(d.name), instruction: d.instruction }));\n const stopDirective = normalizedDirectives.length === 1 && normalizedDirectives[0]!.norm === 'stop';\n if (normalizedDirectives.length === 0 || stopDirective) return { selected: [], unknownNames: [], assignments: new Map(), missingAssignments: [] };\n\n const selected: ScenarioNode[] = [];\n const assignments = new Map<string, string>();\n const matchedDirectives = new Set<string>();\n for (const report of directReports) {\n const fullName = normalizeForMatch(report.label);\n const reverseName = normalizeForMatch(`${report.label}`);\n const matched = normalizedDirectives.find((d) => d.norm === fullName || d.norm === reverseName);\n if (matched) {\n selected.push(report);\n matchedDirectives.add(matched.norm);\n if (matched.instruction) assignments.set(report.id, matched.instruction);\n }\n }\n const unknownNames = normalizedDirectives.filter((d) => d.norm !== 'stop' && !matchedDirectives.has(d.norm)).map((d) => d.norm);\n const missingAssignments = selected.filter((r) => !assignments.has(r.id)).map((r) => r.label);\n return { selected, unknownNames, assignments, missingAssignments };\n}\n\n\n\nfunction hasExplicitNoDelegationDecision(output: string): boolean {\n const nextDirectives = parseRuneyaNextNodeDirectives(output);\n // STOP is only valid when it is the single NEXT_PERSON directive.\n return nextDirectives.length === 1 && normalizeForMatch(nextDirectives[0]?.name ?? '') === 'stop';\n}\n\nfunction buildDelegationRetryMessage(\n manager: ScenarioNode,\n directReports: ScenarioNode[],\n userRequest: string,\n previousOutput: string,\n): string {\n const reportsList = directReports\n .map((r) => `- ${r.label} | role: ${r.role ?? 'other'} | profile: ${r.prompt || 'no description'}`)\n .join('\\n');\n\n return [\n `## Original Request`,\n userRequest,\n ``,\n `## Your Previous Output`,\n `<previous_output>`,\n previousOutput,\n `</previous_output>`,\n ``,\n `## Delegation Retry (mandatory)`,\n `You must explicitly choose which direct reports to contact now.`,\n `Use the exact full names from the allowed list below.`,\n `If you still do not provide explicit names, your run will fail.`,\n ``,\n `## Allowed Direct Reports`,\n reportsList || '(none)',\n ``,\n ...(manager.canAddNode ? [\n `## Optional Hire Command`,\n `You may hire temporary contractors with:`,\n `<hire_person label=\"Jane Doe\" role=\"engineer\">Task focus prompt</hire_person>`,\n `If you hire someone and want them to run now, also include: <next_person name=\"Jane Doe\">their task</next_person>`,\n ``,\n ] : []),\n `## Output Format`,\n `Write one XML tag per selected node including their specific instruction:`,\n `<next_person name=\"FirstName LastName\">their specific task (multiline ok)</next_person>`,\n `Or explicitly choose no delegation with: <next_person name=\"STOP\" />`,\n ].join('\\n');\n}\n\nfunction buildMissingAssignmentsRetryMessage(\n _manager: ScenarioNode,\n missingNames: string[],\n previousOutput: string,\n): string {\n return [\n `## Missing Assignments`,\n `You selected the following nodes but did not provide a specific instruction for each:`,\n missingNames.map((n) => `- ${n}`).join('\\n'),\n ``,\n `## Your Previous Output`,\n `<previous_output>`,\n previousOutput,\n `</previous_output>`,\n ``,\n `## Required Format`,\n `For each node listed above, output one XML tag with their instruction:`,\n `<next_person name=\"FirstName LastName\">their specific task instruction (multiline ok)</next_person>`,\n `The instruction content is mandatory. Be concise and actionable.`,\n ].join('\\n');\n}\n\nfunction buildManagerReviewMessage(\n manager: ScenarioNode,\n directReports: ScenarioNode[],\n userRequest: string,\n previousOutput: string,\n childReportsSection: string,\n): string {\n const reportsList = directReports\n .map((r) => `- ${r.label} | role: ${r.role ?? 'other'} | profile: ${r.prompt || 'no description'}`)\n .join('\\n');\n\n return [\n `## Original Request`,\n userRequest,\n ``,\n `## Your Previous Output`,\n `<previous_output>`,\n previousOutput,\n `</previous_output>`,\n ``,\n `## Children Reports Collected`,\n childReportsSection || '(none)',\n ``,\n `## Parent Review Decision (mandatory)`,\n `You are now in review mode after collecting child reports.`,\n `Your decision rule is simple:`,\n `- If the deliverable is complete and satisfies the original request → output <next_person name=\"STOP\" /> immediately. Do NOT re-run for process reasons (wrong node assigned, style preferences, etc.).`,\n `- If something is factually missing or incorrect in the deliverable → request a targeted re-run with precise instructions.`,\n `Use the exact full names from your direct reports list below.`,\n ``,\n `## Allowed Direct Reports`,\n reportsList || '(none)',\n ``,\n ...(manager.canAddNode ? [\n `## Optional Hire Command`,\n `You may hire temporary contractors with:`,\n `<hire_person label=\"Jane Doe\" role=\"engineer\">Task focus prompt</hire_person>`,\n `If you hire someone and want them to run now, also include: <next_person name=\"Jane Doe\">their task</next_person>`,\n ``,\n ] : []),\n `## Output Format`,\n `If no more child work is needed: output <next_person name=\"STOP\" /> first, then immediately write a complete synthesis of all children's deliverables so your parent can evaluate the result. Do NOT summarize — include the full content (scripts, outputs, data, etc.).`,\n `If refinement is needed, output one XML tag per selected node with their specific instruction:`,\n `<next_person name=\"FirstName LastName\">precise refinement instruction (multiline ok)</next_person>`,\n ].join('\\n');\n}\n\n// ─── Prompt builders ──────────────────────────────────────────────────────────\n\n\nfunction buildSystemPrompt(\n node: ScenarioNode,\n scenario: Scenario,\n): string {\n const group = scenario.groups.find(t => t.id === node.groupId);\n const manager = node.parentIds[0] ? scenario.nodes.find(p => p.id === node.parentIds[0]) : null;\n const reports = getDirectReports(scenario.nodes, node.id);\n\n const preset = scenario.presetId ? getPreset(scenario.presetId) : undefined;\n const presetRole = preset?.roles.find(r => r.id === (node.role ?? 'other'));\n const roleBehavior = presetRole?.systemPrompt ?? '';\n const rolePrompt = presetRole?.prompt ?? '';\n\n const lines = [\n `You are ${node.label}${group ? `, member of the ${group.name} group` : ''}.`,\n `Your role type: **${(node.role ?? 'other').toUpperCase()}**.`,\n '',\n ];\n\n if (roleBehavior) {\n lines.push('## Role Behavior (strictly enforce)', roleBehavior, '');\n }\n\n const profileSection = [node.prompt, rolePrompt].filter(Boolean).join('\\n\\n');\n lines.push('## Your Profile & Instructions', profileSection || '(No profile provided)', '');\n\n if (manager) {\n lines.push(`## Reporting Line`, `You report to ${manager.label} (${manager.role ?? 'other'}).`, '');\n } else {\n lines.push(`## Position`, `You are the leader of this scenario. You coordinate all groups.`, '');\n }\n\n if (reports.length > 0) {\n lines.push(\n `## Your Direct Reports`,\n ...reports.map(r => {\n const rGroup = scenario.groups.find(g => g.id === r.groupId);\n const groupInfo = rGroup\n ? ` | group: ${rGroup.name}${rGroup.description ? ` (${rGroup.description})` : ''}`\n : '';\n return `- ${r.label} (${r.role ?? 'other'})${groupInfo}: ${r.prompt || '(No profile provided)'}`;\n }),\n '',\n );\n }\n\n if (node.canAddNode) {\n lines.push(\n '## Hiring Capability',\n 'You are allowed to hire temporary contractors for this run.',\n 'Use exactly: <hire_person label=\"Jane Doe\" role=\"engineer\">Task focus prompt</hire_person>',\n 'Any hired node will automatically be placed in your own group.',\n 'To execute the hired node in this run, also output: <next_person name=\"Jane Doe\">their task</next_person>',\n '',\n );\n }\n\n lines.push(\n '## Output Instructions',\n 'Write your output clearly and in a structured format.',\n 'Stay strictly within your role — do not produce deliverables that belong to a different role.',\n 'Be concise and actionable.',\n 'Only use <ask_user>...</ask_user> when you are genuinely blocked by missing information that no one in the group can provide (e.g. a secret, a business decision, an external credential). NEVER use it to ask for confirmation, approval, or readiness (e.g. \"are you ready?\", \"shall I proceed?\"). Always proceed autonomously unless truly blocked.',\n );\n\n // Inject RUNEYA_AI_* environment variables\n const runeya_ai_vars = Object.entries(process.env)\n .filter(([k]) => k.startsWith('RUNEYA_AI_'))\n .map(([k, v]) => `${k}=${v}`)\n .join('\\n');\n if (runeya_ai_vars) {\n lines.push('', '## Environment', '', runeya_ai_vars);\n }\n\n return lines.join('\\n');\n}\n\nfunction buildUserMessage(\n node: ScenarioNode,\n scenario: Scenario,\n userRequest: string,\n managerOutput: string | null,\n isLeaderSynthesis: boolean,\n isLeaderDispatch: boolean,\n allOutputs?: Map<string, string>,\n): string {\n const parts: string[] = [];\n\n if (node.prompt) {\n parts.push(`## Your Profile & Instructions (reminder)\\n\\n${node.prompt}`);\n }\n\n parts.push(`## Original Request\\n\\n${userRequest}`);\n\n if (isLeaderSynthesis && allOutputs) {\n // Leader's final synthesis pass: receive all group outputs\n const teamSection = scenario.nodes\n .filter(p => p.id !== scenario.leaderId && allOutputs.has(p.id))\n .map(p => {\n const name = p.label.trim() || p.id;\n const output = allOutputs.get(p.id) ?? '';\n return `<team_member id=\"${p.id}\" name=\"${name}\">\\n${output}\\n</team_member>`;\n })\n .join('\\n\\n');\n\n if (teamSection) {\n parts.push(`## Your Group's Outputs\\n\\n${teamSection}`);\n }\n\n parts.push(\n `## Your Task`,\n `Synthesize all group outputs above and deliver a final, comprehensive answer to the original request.`,\n `Highlight key results, decisions, and any remaining open points.`,\n );\n } else if (isLeaderDispatch) {\n // Leader's dispatch pass: break down the request and assign sub-tasks\n const directReports = getDirectReports(scenario.nodes, node.id);\n const reportsList = directReports\n .map(r => {\n const group = scenario.groups.find(t => t.id === r.groupId);\n return `- ${r.label} | role: ${r.role ?? 'other'}${group ? ` | group: ${group.name}${group.description ? ` (${group.description})` : ''}` : ''} | profile: ${r.prompt || 'no description'}`;\n })\n .join('\\n');\n\n parts.push(\n `## Your Direct Reports\\n\\n${reportsList || '(none)'}`,\n `## Your Task`,\n `As the leader, your role here is STRICTLY to delegate — NEVER to solve the request yourself.`,\n `Do NOT ask yourself whether you should answer directly or delegate. You ALWAYS delegate.`,\n `⚠️ IMPORTANT: Before selecting anyone, re-read your Profile & Instructions above. Any constraint written there (e.g. \"do not contact X\", \"must hire someone\") is MANDATORY and overrides everything else.`,\n `Instead, analyze the request and produce a clear **delegation plan**:`,\n `1. Break down the request into concrete sub-tasks, one per direct report (or group of reports if relevant).`,\n `2. For each node, write a specific, actionable assignment that fits their role and expertise.`,\n `3. Provide any strategic context, constraints, or success criteria they need.`,\n `4. Do NOT produce the final answer — your group will do that. You coordinate.`,\n `5. IMPORTANT: explicitly mention the exact full name of each direct report you want to contact. Only explicitly mentioned nodes will be executed.`,\n `6. For each node you assign, output one XML tag with their name AND specific instruction: <next_person name=\"FirstName LastName\">their specific instruction (multiline ok)</next_person>`,\n `7. If you intentionally decide to contact nobody, write exactly: <next_person name=\"STOP\" />`,\n ...(node.canAddNode ? [\n `8. You may hire temporary contractors with: <hire_person label=\"Jane Doe\" role=\"engineer\">Task focus prompt</hire_person>`,\n `9. Hired nodes are always placed in your own group (no group field needed).`,\n `10. If you hire someone and want them to execute now, also include: <next_person name=\"Jane Doe\">their task</next_person>`,\n ] : []),\n ``,\n `Format your output as a brief intro followed by one clearly labeled section per direct report.`,\n );\n } else {\n if (managerOutput) {\n const manager = scenario.nodes.find(p => p.id === node.parentIds[0]);\n const managerName = manager ? manager.label.trim() : 'your manager';\n parts.push(\n `## Assignment from ${managerName}\\n\\n<manager_output>\\n${managerOutput}\\n</manager_output>`,\n );\n }\n\n // Inject outputs from explicitly selected ancestor nodes\n if (allOutputs && !isLeaderSynthesis) {\n const injectedIds = new Set<string>();\n // Always inject all parent outputs when the node has multiple parents (aggregation node),\n // or when explicitly requested via injectParentOutputs.\n if (node.injectParentOutputs || node.parentIds.length > 1) {\n for (const pid of node.parentIds) injectedIds.add(pid);\n }\n for (const aid of (node.injectedAncestorIds ?? [])) injectedIds.add(aid);\n // Remove first parent since its output is already shown as \"Assignment from manager\" (avoid duplicate)\n injectedIds.delete(node.parentIds[0] ?? '');\n\n const prevOutputs = scenario.nodes\n .filter(p => injectedIds.has(p.id) && allOutputs.has(p.id))\n .map(p => {\n const name = p.label.trim() || p.id;\n const output = allOutputs.get(p.id) ?? '';\n return `<context_node id=\"${p.id}\" name=\"${name}\">\\n${output}\\n</context_node>`;\n })\n .join('\\n\\n');\n if (prevOutputs) {\n parts.push(`## Context from Related Nodes\\n\\n${prevOutputs}`);\n }\n }\n\n parts.push(\n `## Your Task`,\n `Based on the original request${managerOutput ? ' and your manager\\'s assignment above' : ''}${allOutputs && !isLeaderSynthesis && ((node.parentIds.length > 1 || node.injectParentOutputs) || (node.injectedAncestorIds ?? []).length > 0) ? ' and the context from related nodes above' : ''}, ` +\n `complete your specific part according to your role and expertise. ` +\n `Be thorough and actionable. Report your output clearly — your manager will use it for the final synthesis.`,\n );\n\n const directReports = getDirectReports(scenario.nodes, node.id);\n if (directReports.length > 0) {\n const reportsList = directReports\n .map((r) => `- ${r.label} | role: ${r.role ?? 'other'} | profile: ${r.prompt || 'no description'}`)\n .join('\\n');\n parts.push(\n ...(node.canAddNode ? [\n `## Hiring (available to you)`,\n `You may hire a temporary contractor for this run: <hire_person label=\"Jane Doe\" role=\"engineer\">Task focus prompt</hire_person>`,\n `If you hire someone and want them to execute immediately, also add: <next_person name=\"Jane Doe\">their task</next_person>`,\n `Hired nodes join your group automatically — no group field needed.`,\n ] : []),\n `## Direct Reports You Can Also Contact\\n\\n${reportsList}`,\n `⚠️ MANDATORY: Re-read your Profile & Instructions above before selecting anyone. Any constraint there (e.g. \"do not contact X\", \"must hire\") overrides everything.`,\n `For each node you assign, output one XML tag with their name AND specific instruction: <next_person name=\"FirstName LastName\">their specific instruction (multiline ok)</next_person>`,\n `Only names declared with <next_person> will run.`,\n `If you intentionally choose to delegate to nobody, write: <next_person name=\"STOP\" />`,\n );\n }\n }\n\n return parts.join('\\n\\n');\n}\n\n// ─── Single-node AI call (streaming) ───────────────────────────────────────\n\nfunction resolveNodeExecutionConfig(\n node: ScenarioNode,\n runOverrides?: ScenarioRunOverrides,\n): { aiCli: 'claude-code' | 'codex'; model: string } {\n const baseCli = node.aiCli ?? 'claude-code';\n const aiCli = runOverrides?.runnerOverride ?? baseCli;\n const crossFamily = !!runOverrides?.runnerOverride && runOverrides.runnerOverride !== baseCli;\n const modelOverride = runOverrides?.modelOverride?.trim() ?? '';\n const nodeModel = node.model?.trim() ?? '';\n const model = modelOverride || (crossFamily ? DEFAULT_NODE_MODELS[aiCli] : (nodeModel || DEFAULT_NODE_MODELS[aiCli]));\n return { aiCli, model };\n}\n\n// ─── Per-node runner state (session continuity across ASK_USER loops) ───────\n\ninterface NodeRunnerState {\n runner: AiRunner;\n sessionId: string;\n isResume: boolean;\n}\n\nfunction createNodeRunnerState(aiCli: 'claude-code' | 'codex'): NodeRunnerState {\n return {\n runner: aiCli === 'codex' ? new CodexRunner() : new ClaudeCodeRunner(),\n sessionId: '',\n isResume: false,\n };\n}\n\nasync function runNodeCall(\n conversationId: string,\n node: ScenarioNode,\n systemContext: string,\n userMessage: string,\n runOverrides: ScenarioRunOverrides | undefined,\n signal: AbortSignal,\n publish: (evt: ScenarioEvent) => void,\n onDelta: (text: string) => void,\n runnerStates: Map<string, NodeRunnerState>,\n label = 'call',\n readme?: (text: string) => Promise<void>,\n): Promise<string> {\n publish({ type: 'node_prompt', nodeId: node.id, label, systemContext, userMessage });\n const { aiCli, model } = resolveNodeExecutionConfig(node, runOverrides);\n\n if (!runnerStates.has(node.id)) {\n runnerStates.set(node.id, createNodeRunnerState(aiCli));\n }\n const state = runnerStates.get(node.id)!;\n\n let currentPrompt = userMessage;\n let accumulated = '';\n let persistTimer: ReturnType<typeof setTimeout> | null = null;\n\n const schedulePersist = () => {\n if (persistTimer) return;\n persistTimer = setTimeout(() => {\n persistTimer = null;\n appendNodeOutput(conversationId, node, accumulated).catch(() => {});\n }, 500);\n };\n\n const flushPersist = () => {\n if (persistTimer) { clearTimeout(persistTimer); persistTimer = null; }\n };\n\n while (true) {\n const turnStart = Date.now();\n\n const result = await state.runner.run({\n agentId: runOverrides?.agentId ?? agentManager.getDefaultAgentId() ?? undefined,\n sessionId: state.sessionId,\n prompt: currentPrompt,\n isResume: state.isResume,\n systemContext,\n apiBaseUrl: '',\n apiToken: '',\n model,\n effort: 'normal',\n signal,\n onDelta: (text) => {\n accumulated += text;\n onDelta(text);\n schedulePersist();\n },\n onStatus: (text) => publish({ type: 'node_status', nodeId: node.id, text }),\n onToolCall: (id, name, input, rawInput) => publish({ type: 'node_tool_call', nodeId: node.id, id, name, input, rawInput }),\n onToolResult: (id, result, isError) => publish({ type: 'node_tool_result', nodeId: node.id, id, result, isError }),\n onThinking: (text) => publish({ type: 'node_thinking', nodeId: node.id, text }),\n onCommand: (cmd) => publish({ type: 'node_command', nodeId: node.id, command: cmd }),\n });\n\n flushPersist();\n // Update to the actual session ID reported by claude (may differ from our initial UUID)\n if (result.actualSessionId) state.sessionId = result.actualSessionId;\n state.isResume = true;\n\n // Persist the claude session-id per node so the user can later open a\n // `claude --resume <sessionId>` PTY from the debug button.\n const agentForNode = runOverrides?.agentId ?? agentManager.getDefaultAgentId() ?? null;\n if (state.sessionId && agentForNode) {\n scenarioRunStore.setNodeSession(conversationId, node.id, state.sessionId, agentForNode);\n void scenarioRunStore.persistRunState(conversationId);\n }\n\n if (result.tokenStatus === 'ask_user') {\n publish({ type: 'node_duration', nodeId: node.id, durationMs: Date.now() - turnStart });\n scenarioRunStore.setNodeState(conversationId, node.id, 'waiting_input');\n scenarioRunStore.setWaitingInput(conversationId, node.id, result.tokenMessage);\n flushPersist();\n publish({ type: 'node_waiting_input', nodeId: node.id, question: result.tokenMessage });\n await readme?.(`- ❓ [${formatTs()}] **${node.label}** — waiting for user input\\n`);\n\n const answer = await new Promise<string>((resolve, reject) => {\n const key = pendingNodeKey(conversationId, node.id);\n pendingNodeInputs.set(key, resolve);\n signal.addEventListener('abort', () => {\n pendingNodeInputs.delete(key);\n reject(new Error('Aborted'));\n }, { once: true });\n });\n\n scenarioRunStore.clearWaitingInput(conversationId, node.id);\n await readme?.(`- 💬 [${formatTs()}] **User replied** to ${node.label}\\n`);\n const qaBlock = `\\n\\n---\\n**Question:** ${result.tokenMessage}\\n\\n**Your answer:** ${answer}\\n`;\n await appendNodeOutput(conversationId, node, qaBlock);\n publish({ type: 'node_delta', nodeId: node.id, text: qaBlock });\n accumulated = '';\n scenarioRunStore.setNodeState(conversationId, node.id, 'running');\n publish({ type: 'node_started', nodeId: node.id });\n currentPrompt = `L'utilisateur a répondu : ${answer}`;\n continue;\n }\n\n publish({ type: 'node_duration', nodeId: node.id, durationMs: Date.now() - turnStart });\n return result.output;\n }\n}\n\n// ─── Persist output to workspace file ────────────────────────────────────────\n\nfunction getScenarioRunDir(conversationId: string): string | null {\n try {\n return resolveConversationRunDir('scenario-runs', conversationId);\n } catch {\n return null;\n }\n}\n\nasync function appendNodeOutput(conversationId: string, node: ScenarioNode, output: string): Promise<void> {\n const dir = getScenarioRunDir(conversationId);\n if (!dir) return;\n\n const slug = node.label.toLowerCase().replace(/[^a-z0-9]+/g, '-').slice(0, 60) || 'member';\n const safeId = node.id.replace(/[^a-z0-9_-]/gi, '-').slice(0, 80);\n const filePath = join(dir, `${slug}_${safeId}.md`);\n\n const content = `## Output\\n\\n${output}\\n`;\n await atomicWriteSecure(filePath, content);\n}\n\nasync function appendToReadme(\n conversationId: string,\n bus: RunBus,\n text: string,\n): Promise<void> {\n const dir = getScenarioRunDir(conversationId);\n if (!dir) return;\n\n const line = `${text}\\n`;\n try {\n await mkdir(dir, { recursive: true });\n const { appendFile } = await import('node:fs/promises');\n await appendFile(join(dir, 'README.md'), line, 'utf-8');\n } catch {\n // Non-fatal — still publish the event even if disk write fails\n }\n publishToBus(bus, { type: 'readme_append', text: line });\n}\n\nasync function writeFinalMd(\n conversationId: string,\n bus: RunBus,\n userRequest: string,\n content: string,\n): Promise<void> {\n const dir = getScenarioRunDir(conversationId);\n if (!dir) return;\n\n const fullContent = `# Final Report\\n\\n## User Request\\n\\n> ${userRequest.replaceAll('\\n', '\\n> ')}\\n\\n---\\n\\n## Result\\n\\n${content}\\n`;\n\n const filePath = join(dir, 'FINAL.md');\n await atomicWriteSecure(filePath, fullContent);\n\n // Stream FINAL.md content as readme_append so UI sees it inline\n await appendToReadme(conversationId, bus,\n `\\n---\\n\\n## ✅ FINAL REPORT\\n\\n**User request:**\\n\\n> ${userRequest.replaceAll('\\n', '\\n> ')}\\n\\n${content}\\n`,\n );\n}\n\n// ─── Main orchestration ───────────────────────────────────────────────────────\n\n/**\n * Runs the scenario multi-agent workflow for a given conversation.\n * Execution order: BFS level by level (leader → direct reports → their reports, …).\n * Nodes at the same level run in parallel.\n * After all agents complete, the leader runs a synthesis pass.\n * All events are published to the run bus so late subscribers can reconnect.\n */\nfunction applyRunOverridesToScenario(\n scenario: Scenario,\n runOverrides?: ScenarioRunOverrides,\n): Scenario {\n if (!runOverrides?.runnerOverride && !runOverrides?.modelOverride?.trim()) return scenario;\n return {\n ...scenario,\n nodes: scenario.nodes.map((node) => {\n const { aiCli, model } = resolveNodeExecutionConfig(node, runOverrides);\n return { ...node, aiCli, model };\n }),\n };\n}\n\nexport async function runScenario(\n conversationId: string,\n scenarioId: string,\n userRequest: string,\n runOverrides?: ScenarioRunOverrides,\n resume?: boolean,\n): Promise<void> {\n if (isScenarioRunning(conversationId)) return;\n\n const bus = createBus(conversationId);\n const ctrl = new AbortController();\n activeAbortControllers.set(conversationId, ctrl);\n const signal = ctrl.signal;\n\n const publish = (evt: ScenarioEvent) => publishToBus(bus, evt);\n const readme = (text: string) => appendToReadme(conversationId, bus, text);\n // Bullet list item with automatic timestamp prefix: `- emoji [ts] rest`\n const li = (emoji: string, content: string) => readme(`- ${emoji} [${formatTs()}] ${content}\\n`);\n\n const ts = () => formatTs();\n const fmtDuration = (startMs: number) => {\n const ms = Math.max(0, Date.now() - startMs);\n const sec = ms / 1000;\n return sec < 10 ? `${sec.toFixed(1)}s` : `${Math.round(sec)}s`;\n };\n\n let finalWritten = false;\n\n async function execute() {\n try {\n const scenario: Scenario = await (async () => {\n const base = await scenarioRunStore.loadScenarioSnapshot(conversationId)\n ?? await scenarioStore.get(scenarioId);\n if (!base) throw new Error(`Scenario ${scenarioId} not found`);\n // Apply overrides in memory only — snapshot on disk stays clean\n return applyRunOverridesToScenario(base, runOverrides);\n })();\n const leader = scenario.nodes.find((p) => p.id === scenario.leaderId);\n if (!leader) throw new Error('Scenario has no leader');\n\n // Build parent→children map for hierarchy lookups\n const byParent = new Map<string, ScenarioNode[]>();\n const nodesById = new Map(scenario.nodes.map((p) => [p.id, p]));\n\n // outputs[nodeId] = full text output of that node\n const outputs = new Map<string, string>();\n let leaderDispatchOutput: string | null = null;\n let leaderDispatchAssignments: Map<string, string> = new Map();\n\n // Runner state per node — preserves session for ASK_USER continuations\n const runnerStates = new Map<string, NodeRunnerState>();\n\n // ── Resume: load persisted state and pre-populate outputs for done persons ──\n const persistedState = resume\n ? await scenarioRunStore.loadPersistedRunState(conversationId)\n : null;\n\n function isSubtreeComplete(nodeId: string): boolean {\n if (!persistedState) return false;\n const state = persistedState.nodeStates[nodeId];\n if (state !== 'done' && state !== 'synthesized') return false;\n for (const child of getDirectReports(scenario.nodes, nodeId)) {\n if (!isSubtreeComplete(child.id)) return false;\n }\n return true;\n }\n\n if (persistedState) {\n for (const [nodeId, output] of Object.entries(persistedState.nodeOutputs)) {\n const state = persistedState.nodeStates[nodeId];\n if (state === 'done' || state === 'synthesized') {\n outputs.set(nodeId, output);\n scenarioRunStore.setNodeState(conversationId, nodeId, state as NodeState);\n scenarioRunStore.setNodeOutput(conversationId, nodeId, output);\n }\n }\n }\n\n if (resume) {\n await readme(`\\n---\\n\\n## ♻️ Run resumed — ${ts()}\\n`);\n } else {\n await readme(`\\n## Run started — ${ts()}\\n\\n**User request:**\\n\\n> ${userRequest.replaceAll('\\n', '\\n> ')}\\n`);\n }\n\n // Resume: restore leader dispatch from cache if available\n let leaderDispatchHandled = false;\n if (persistedState && outputs.has(leader.id)) {\n const cachedOut = outputs.get(leader.id)!;\n leaderDispatchOutput = cachedOut;\n const leaderResult = selectExplicitDirectReportsFromOutput(leader, scenario.nodes, cachedOut);\n byParent.set(leader.id, leaderResult.selected);\n leaderDispatchAssignments = leaderResult.assignments;\n const leaderState = leaderResult.selected.length > 0 ? 'waiting' : 'done';\n scenarioRunStore.setNodeState(conversationId, leader.id, leaderState);\n publish({ type: 'node_state_change', nodeId: leader.id, state: leaderState });\n publish({ type: 'node_done', nodeId: leader.id, output: cachedOut, state: leaderState });\n await li('♻️', `**${leader.label}** (Leader) — restored from previous run`);\n leaderDispatchHandled = true;\n }\n\n // Leader dispatch phase — hierarchical mode only\n if (scenario.traversalMode !== 'topological' && !leaderDispatchHandled) {\n const startedAt = Date.now();\n publish({ type: 'node_started', nodeId: leader.id });\n scenarioRunStore.setNodeState(conversationId, leader.id, 'running');\n await readme(`### [${ts()}] 📋 ${leader.label} (Leader) — dispatching assignments\\n`);\n await li('▶️', `**${leader.label}** — started`);\n\n try {\n const systemPrompt = buildSystemPrompt(leader, scenario);\n const userMsg = buildUserMessage(leader, scenario, userRequest, null, false, true);\n const out = await runNodeCall(conversationId, leader, systemPrompt, userMsg, runOverrides, signal, publish, (delta) => {\n publish({ type: 'node_delta', nodeId: leader.id, text: delta });\n }, runnerStates, 'dispatch', readme);\n\n outputs.set(leader.id, out);\n leaderDispatchOutput = out;\n const hiredByLeader = applyHireDirectivesFromOutput(leader, scenario, out);\n if (hiredByLeader.length > 0) {\n await scenarioRunStore.saveScenarioSnapshot(conversationId, scenario);\n await li('🆕', `${leader.label} hired: ${hiredByLeader.map((p) => `${p.label} (${p.role})`).join(', ')}`);\n }\n const directReports = getDirectReports(scenario.nodes, leader.id);\n const leaderResult = selectExplicitDirectReportsFromOutput(leader, scenario.nodes, out);\n // Auto-include hired nodes not already named in NEXT_PERSON\n const seenIds = new Set(leaderResult.selected.map((r) => r.id));\n for (const h of hiredByLeader) { if (!seenIds.has(h.id)) { leaderResult.selected.push(h); seenIds.add(h.id); } }\n let assignedReports = leaderResult.selected;\n let leaderAssignments = leaderResult.assignments;\n let explicitStop = hasExplicitNoDelegationDecision(out);\n let finalLeaderOutput = out;\n const needsRetry = directReports.length > 0 && assignedReports.length === 0 && !explicitStop;\n const hasUnknown = leaderResult.unknownNames.length > 0;\n const hasMissingAssignments = leaderResult.missingAssignments.length > 0;\n if (needsRetry || hasUnknown || hasMissingAssignments) {\n if (hasUnknown) await li('⚠️', `Unknown node(s) named by ${leader.label}: ${leaderResult.unknownNames.join(', ')}. Retrying.`);\n else if (hasMissingAssignments) await li('⚠️', `Missing assignments for ${leaderResult.missingAssignments.join(', ')} from ${leader.label}. Retrying.`);\n else await li('⚠️', `No explicit assignees parsed for ${leader.label}. Retrying once to force explicit selection.`);\n const retryUserMsg = hasMissingAssignments\n ? buildMissingAssignmentsRetryMessage(leader, leaderResult.missingAssignments, out)\n : buildDelegationRetryMessage(leader, directReports, userRequest, out);\n // Fresh session for retry — --resume on a killed/early-exited process is unreliable\n runnerStates.delete(leader.id);\n const retryOut = await runNodeCall(conversationId, leader, systemPrompt, retryUserMsg, runOverrides, signal, publish, (delta) => {\n publish({ type: 'node_delta', nodeId: leader.id, text: delta });\n }, runnerStates, 'dispatch-retry', readme);\n const hiredOnRetry = applyHireDirectivesFromOutput(leader, scenario, retryOut);\n if (hiredOnRetry.length > 0) {\n await scenarioRunStore.saveScenarioSnapshot(conversationId, scenario);\n await li('🆕', `${leader.label} hired on retry: ${hiredOnRetry.map((p) => `${p.label} (${p.role})`).join(', ')}`);\n }\n const retryResult = selectExplicitDirectReportsFromOutput(leader, scenario.nodes, retryOut);\n const seenRetryIds = new Set(retryResult.selected.map((r) => r.id));\n for (const h of hiredOnRetry) { if (!seenRetryIds.has(h.id)) { retryResult.selected.push(h); seenRetryIds.add(h.id); } }\n assignedReports = retryResult.selected;\n leaderAssignments = new Map([...leaderAssignments, ...retryResult.assignments]);\n explicitStop = hasExplicitNoDelegationDecision(retryOut);\n finalLeaderOutput = `${out}\\n\\n## Delegation Retry Output\\n${retryOut}`;\n if (assignedReports.length === 0 && !explicitStop) {\n throw new Error(`No explicit assignees parsed for ${leader.label} after retry`);\n }\n if (assignedReports.length > 0) {\n await li('✅', `Explicit assignees parsed for ${leader.label} after retry.`);\n }\n }\n if (assignedReports.length === 0 && explicitStop) {\n await li('⏹️', `${leader.label} explicitly chose to delegate to nobody (STOP).`);\n }\n\n outputs.set(leader.id, finalLeaderOutput);\n leaderDispatchOutput = finalLeaderOutput;\n await appendNodeOutput(conversationId, leader, finalLeaderOutput);\n\n byParent.set(leader.id, assignedReports);\n scenarioRunStore.setNodeState(conversationId, leader.id, assignedReports.length > 0 ? 'waiting' : 'done');\n scenarioRunStore.setNodeOutput(conversationId, leader.id, finalLeaderOutput);\n await scenarioRunStore.persistRunState(conversationId);\n\n for (const report of assignedReports) {\n await li('→', `**${report.label}** assigned by ${leader.label}`);\n }\n leaderDispatchAssignments = leaderAssignments;\n await li('✅', `**${leader.label}** (Leader) — done in ${fmtDuration(startedAt)}`);\n publish({ type: 'node_done', nodeId: leader.id, output: finalLeaderOutput, state: scenarioRunStore.getRunState(conversationId)?.nodeStates[leader.id] ?? 'done' });\n } catch (err) {\n if (signal.aborted) throw err;\n const msg = (err as Error).message;\n scenarioRunStore.setNodeState(conversationId, leader.id, 'error');\n await readme(`### [${ts()}] ❌ ${leader.label} (Leader) — FAILED after ${fmtDuration(startedAt)}: ${msg}\\n`);\n publish({ type: 'node_error', nodeId: leader.id, error: msg });\n runnerStates.delete(leader.id);\n const leaderErrorOutput = `❌ Leader failed: ${msg}`;\n scenarioRunStore.setNodeOutput(conversationId, leader.id, leaderErrorOutput);\n await appendNodeOutput(conversationId, leader, leaderErrorOutput);\n publish({ type: 'node_delta', nodeId: leader.id, text: `\\n\\n${leaderErrorOutput}` });\n throw new Error(`Leader failed: ${msg}`);\n }\n }\n\n // Group execution with parent review loops:\n // manager executes -> children execute -> manager reviews and decides STOP or targeted re-run.\n async function runDelegationPass(\n node: ScenarioNode,\n userMsg: string,\n modeLabel: string,\n ): Promise<{ finalOutput: string; assignedReports: ScenarioNode[]; assignments: Map<string, string> }> {\n const startedAt = Date.now();\n publish({ type: 'node_started', nodeId: node.id });\n scenarioRunStore.setNodeState(conversationId, node.id, 'running');\n await li('▶️', `**${node.label}** — started`);\n try {\n const manager = node.parentIds[0] ? nodesById.get(node.parentIds[0]) ?? null : null;\n const systemPrompt = buildSystemPrompt(node, scenario);\n const out = await runNodeCall(conversationId, node, systemPrompt, userMsg, runOverrides, signal, publish, (delta) => {\n publish({ type: 'node_delta', nodeId: node.id, text: delta });\n }, runnerStates, modeLabel, readme);\n const hiredByNode = applyHireDirectivesFromOutput(node, scenario, out);\n if (hiredByNode.length > 0) {\n await scenarioRunStore.saveScenarioSnapshot(conversationId, scenario);\n await li('🆕', `${node.label} hired: ${hiredByNode.map((p) => `${p.label} (${p.role})`).join(', ')}`);\n }\n\n const directReports = getDirectReports(scenario.nodes, node.id);\n let nodeResult = selectExplicitDirectReportsFromOutput(node, scenario.nodes, out);\n const seenIds = new Set(nodeResult.selected.map((r) => r.id));\n for (const h of hiredByNode) { if (!seenIds.has(h.id)) { nodeResult.selected.push(h); seenIds.add(h.id); } }\n let assignedReports = nodeResult.selected;\n let assignments = nodeResult.assignments;\n let explicitStop = hasExplicitNoDelegationDecision(out);\n let finalOutput = out;\n const needsRetry = directReports.length > 0 && assignedReports.length === 0 && !explicitStop;\n const hasUnknown = nodeResult.unknownNames.length > 0;\n const hasMissingAssignments = nodeResult.missingAssignments.length > 0;\n if (needsRetry || hasUnknown || hasMissingAssignments) {\n if (hasUnknown) await li('⚠️', `Unknown node(s) named by ${node.label}: ${nodeResult.unknownNames.join(', ')}. Retrying.`);\n else if (hasMissingAssignments) await li('⚠️', `Missing assignments for ${nodeResult.missingAssignments.join(', ')} from ${node.label}. Retrying.`);\n else await li('⚠️', `No explicit assignees parsed for ${node.label}. Retrying once to force explicit selection.`);\n const retryUserMsg = hasMissingAssignments\n ? buildMissingAssignmentsRetryMessage(node, nodeResult.missingAssignments, out)\n : buildDelegationRetryMessage(node, directReports, userRequest, out);\n // Fresh session for retry — --resume on a killed/early-exited process is unreliable\n runnerStates.delete(node.id);\n const retryOut = await runNodeCall(conversationId, node, systemPrompt, retryUserMsg, runOverrides, signal, publish, (delta) => {\n publish({ type: 'node_delta', nodeId: node.id, text: delta });\n }, runnerStates, `${modeLabel}-retry`, readme);\n const hiredOnRetry = applyHireDirectivesFromOutput(node, scenario, retryOut);\n if (hiredOnRetry.length > 0) {\n await scenarioRunStore.saveScenarioSnapshot(conversationId, scenario);\n await li('🆕', `${node.label} hired on retry: ${hiredOnRetry.map((p) => `${p.label} (${p.role})`).join(', ')}`);\n }\n const retryResult = selectExplicitDirectReportsFromOutput(node, scenario.nodes, retryOut);\n const seenRetryIds = new Set(retryResult.selected.map((r) => r.id));\n for (const h of hiredOnRetry) { if (!seenRetryIds.has(h.id)) { retryResult.selected.push(h); seenRetryIds.add(h.id); } }\n assignedReports = retryResult.selected;\n assignments = new Map([...assignments, ...retryResult.assignments]);\n explicitStop = hasExplicitNoDelegationDecision(retryOut);\n finalOutput = `${out}\\n\\n## Delegation Retry Output\\n${retryOut}`;\n if (assignedReports.length === 0 && !explicitStop) {\n throw new Error(`No explicit assignees parsed for ${node.label} after retry`);\n }\n if (assignedReports.length > 0) {\n await li('✅', `Explicit assignees parsed for ${node.label} after retry.`);\n }\n }\n if (assignedReports.length === 0 && explicitStop) {\n await li('⏹️', `${node.label} explicitly chose to delegate to nobody (STOP).`);\n }\n\n outputs.set(node.id, finalOutput);\n await appendNodeOutput(conversationId, node, finalOutput);\n byParent.set(node.id, assignedReports);\n\n scenarioRunStore.setNodeState(conversationId, node.id, assignedReports.length > 0 ? 'waiting' : 'done');\n scenarioRunStore.setNodeOutput(conversationId, node.id, finalOutput);\n await scenarioRunStore.persistRunState(conversationId);\n\n if (assignedReports.length > 0) {\n for (const report of assignedReports) {\n await li('→', `**${report.label}** assigned by ${node.label}`);\n }\n }\n const reportTo = manager ? manager.label : 'Leader';\n await li('✅', `**${node.label}** (${node.role ?? 'other'}) — done in ${fmtDuration(startedAt)}, reporting to ${reportTo}`);\n publish({ type: 'node_done', nodeId: node.id, output: finalOutput, state: scenarioRunStore.getRunState(conversationId)?.nodeStates[node.id] ?? 'done' });\n return { finalOutput, assignedReports, assignments };\n } catch (err) {\n if (signal.aborted) throw err;\n const msg = (err as Error).message;\n scenarioRunStore.setNodeState(conversationId, node.id, 'error');\n await li('❌', `**${node.label}** — error after ${fmtDuration(startedAt)}: ${msg}`);\n publish({ type: 'node_error', nodeId: node.id, error: msg });\n // Reset runner state so next retry starts a fresh session\n runnerStates.delete(node.id);\n const errorOutput = `[ERROR: ${node.label} failed — ${msg}]\\n\\n${outputs.get(node.id) ?? ''}`.trim();\n outputs.set(node.id, errorOutput);\n scenarioRunStore.setNodeOutput(conversationId, node.id, errorOutput);\n await appendNodeOutput(conversationId, node, `\\n\\n❌ Error: ${msg}`);\n publish({ type: 'node_delta', nodeId: node.id, text: `\\n\\n❌ Error: ${msg}` });\n return { finalOutput: errorOutput, assignedReports: [], assignments: new Map() };\n }\n }\n\n async function runAskNode(node: ScenarioNode): Promise<string> {\n const question = node.question?.trim() || node.label || node.id;\n publish({ type: 'node_started', nodeId: node.id });\n scenarioRunStore.setNodeState(conversationId, node.id, 'waiting_input');\n scenarioRunStore.setWaitingInput(conversationId, node.id, question);\n publish({ type: 'node_waiting_input', nodeId: node.id, question });\n await readme(`- ❓ [${ts()}] **${node.label || node.id}** — waiting for user input\\n`);\n\n const answer = await new Promise<string>((resolve, reject) => {\n const key = pendingNodeKey(conversationId, node.id);\n pendingNodeInputs.set(key, resolve);\n signal.addEventListener('abort', () => {\n pendingNodeInputs.delete(key);\n reject(new Error('Aborted'));\n }, { once: true });\n });\n\n scenarioRunStore.clearWaitingInput(conversationId, node.id);\n await readme(`- 💬 [${ts()}] **User replied** to ${node.label || node.id}\\n`);\n const output = `**Question:** ${question}\\n\\n**Answer:** ${answer}`;\n scenarioRunStore.setNodeOutput(conversationId, node.id, output);\n outputs.set(node.id, output);\n scenarioRunStore.setNodeState(conversationId, node.id, 'done');\n publish({ type: 'node_done', nodeId: node.id, output, state: 'done' });\n return output;\n }\n\n async function runNodeSubtree(node: ScenarioNode, managerOutput: string | null): Promise<void> {\n // Ask node: skip AI entirely, wait for human input\n if (node.type === 'ask') {\n if (!isSubtreeComplete(node.id)) await runAskNode(node);\n else {\n publish({ type: 'node_state_change', nodeId: node.id, state: 'done' });\n publish({ type: 'node_done', nodeId: node.id, output: outputs.get(node.id) ?? '', state: 'done' });\n }\n return;\n }\n\n // Resume: skip entire subtree if all persons in it are done\n if (isSubtreeComplete(node.id)) {\n publish({ type: 'node_state_change', nodeId: node.id, state: 'done' });\n publish({ type: 'node_done', nodeId: node.id, output: outputs.get(node.id) ?? '', state: 'done' });\n return;\n }\n\n // Resume: if this node's own execution is cached but children aren't all done,\n // use cached output to derive delegation (skip the AI call for this node only)\n let firstPassResult: { finalOutput: string; assignedReports: ScenarioNode[]; assignments: Map<string, string> };\n if (persistedState && outputs.has(node.id)) {\n const cachedOut = outputs.get(node.id)!;\n const result = selectExplicitDirectReportsFromOutput(node, scenario.nodes, cachedOut);\n byParent.set(node.id, result.selected);\n const newState = result.selected.length > 0 ? 'waiting' : 'done';\n scenarioRunStore.setNodeState(conversationId, node.id, newState);\n scenarioRunStore.setNodeOutput(conversationId, node.id, cachedOut);\n publish({ type: 'node_state_change', nodeId: node.id, state: newState });\n publish({ type: 'node_done', nodeId: node.id, output: cachedOut, state: newState });\n await li('♻️', `**${node.label}** — restored from previous run`);\n firstPassResult = { finalOutput: cachedOut, assignedReports: result.selected, assignments: result.assignments };\n } else {\n const initialUserMsg = buildUserMessage(node, scenario, userRequest, managerOutput, false, false);\n firstPassResult = await runDelegationPass(node, initialUserMsg, '(execution)');\n }\n\n let { finalOutput, assignedReports, assignments } = firstPassResult;\n\n let reviewRound = 0;\n while (assignedReports.length > 0) {\n if (signal.aborted) throw new Error('Aborted');\n reviewRound += 1;\n if (reviewRound > MAX_MANAGER_REVIEW_ROUNDS) {\n throw new Error(`${node.label} exceeded review loop limit (${MAX_MANAGER_REVIEW_ROUNDS})`);\n }\n\n await readme(`\\n### [${ts()}] Review loop ${reviewRound} for ${node.label} — collecting child reports\\n`);\n await Promise.all(assignedReports.map((report) => {\n const instruction = assignments.get(report.id) ?? null;\n return runNodeSubtree(report, instruction ?? finalOutput);\n }));\n\n const childReportsSection = assignedReports\n .map((report) => {\n const reportOut = outputs.get(report.id) ?? '';\n return `<child_report node=\"${report.label}\" id=\"${report.id}\">\\n${reportOut}\\n</child_report>`;\n })\n .join('\\n\\n');\n\n const reviewUserMsg = buildManagerReviewMessage(\n node,\n getDirectReports(scenario.nodes, node.id),\n userRequest,\n finalOutput,\n childReportsSection,\n );\n const pass = await runDelegationPass(node, reviewUserMsg, `(review round ${reviewRound})`);\n finalOutput = pass.finalOutput;\n assignedReports = pass.assignedReports;\n assignments = pass.assignments;\n }\n }\n\n if (scenario.traversalMode === 'topological') {\n // ── Topological mode: level-by-level, siblings run in parallel ──\n // Helper: get all parent IDs of a node (parentId + parentIds)\n const allParentIds = (n: ScenarioNode): string[] => n.parentIds ?? [];\n // Helper: get all children of a node (nodes that list it as any parent)\n const allChildren = (nodeId: string): ScenarioNode[] =>\n scenario.nodes.filter((n) => allParentIds(n).includes(nodeId));\n\n // Build levels: a node's level = max(parent levels) + 1\n const nodeLevelMap = new Map<string, number>();\n nodeLevelMap.set(leader.id, 0);\n // BFS to assign levels\n const bfsQueue: ScenarioNode[] = [leader];\n while (bfsQueue.length > 0) {\n const cur = bfsQueue.shift()!;\n const curLevel = nodeLevelMap.get(cur.id) ?? 0;\n for (const child of allChildren(cur.id)) {\n const newLevel = curLevel + 1;\n const existing = nodeLevelMap.get(child.id) ?? -1;\n if (newLevel > existing) {\n nodeLevelMap.set(child.id, newLevel);\n bfsQueue.push(child);\n }\n }\n }\n // Group nodes by level\n const maxLevel = Math.max(...nodeLevelMap.values());\n const levels: ScenarioNode[][] = Array.from({ length: maxLevel + 1 }, () => []);\n for (const node of scenario.nodes) {\n const lvl = nodeLevelMap.get(node.id);\n if (lvl !== undefined) levels[lvl].push(node);\n }\n\n const runTopoNode = async (node: ScenarioNode) => {\n if (signal.aborted) throw new Error('Aborted');\n\n // Ask node: skip AI entirely, wait for human input\n if (node.type === 'ask') {\n if (persistedState && outputs.has(node.id)) {\n scenarioRunStore.setNodeState(conversationId, node.id, 'done');\n scenarioRunStore.setNodeOutput(conversationId, node.id, outputs.get(node.id)!);\n publish({ type: 'node_state_change', nodeId: node.id, state: 'done' });\n publish({ type: 'node_done', nodeId: node.id, output: outputs.get(node.id)!, state: 'done' });\n await li('♻️', `**${node.label}** — restored from previous run`);\n } else {\n await runAskNode(node);\n }\n return;\n }\n\n // Resume: skip already-done nodes\n if (persistedState && outputs.has(node.id)) {\n const cached = outputs.get(node.id)!;\n scenarioRunStore.setNodeState(conversationId, node.id, 'done');\n scenarioRunStore.setNodeOutput(conversationId, node.id, cached);\n publish({ type: 'node_state_change', nodeId: node.id, state: 'done' });\n publish({ type: 'node_done', nodeId: node.id, output: cached, state: 'done' });\n await li('♻️', `**${node.label}** — restored from previous run`);\n return;\n }\n\n const startedAt = Date.now();\n publish({ type: 'node_started', nodeId: node.id });\n scenarioRunStore.setNodeState(conversationId, node.id, 'running');\n await readme(`### [${ts()}] ▶️ ${node.label} — started\\n`);\n await li('▶️', `**${node.label}** — started`);\n\n try {\n const parentOutput = node.parentIds[0] ? outputs.get(node.parentIds[0]) ?? null : null;\n const systemPrompt = buildSystemPrompt(node, scenario);\n const userMsg = buildUserMessage(node, scenario, userRequest, parentOutput, false, false, new Map(outputs));\n const out = await runNodeCall(conversationId, node, systemPrompt, userMsg, runOverrides, signal, publish, (delta) => {\n publish({ type: 'node_delta', nodeId: node.id, text: delta });\n }, runnerStates, '(topological)', readme);\n\n outputs.set(node.id, out);\n scenarioRunStore.setNodeState(conversationId, node.id, 'done');\n scenarioRunStore.setNodeOutput(conversationId, node.id, out);\n await scenarioRunStore.persistRunState(conversationId);\n await appendNodeOutput(conversationId, node, out);\n await li('✅', `**${node.label}** — done in ${fmtDuration(startedAt)}`);\n publish({ type: 'node_done', nodeId: node.id, output: out, state: 'done' });\n } catch (err) {\n if (signal.aborted) throw err;\n const msg = (err as Error).message;\n scenarioRunStore.setNodeState(conversationId, node.id, 'error');\n await readme(`### [${ts()}] ❌ ${node.label} — FAILED after ${fmtDuration(startedAt)}: ${msg}\\n`);\n publish({ type: 'node_error', nodeId: node.id, error: msg });\n runnerStates.delete(node.id);\n throw new Error(`${node.label} failed: ${msg}`);\n }\n };\n\n for (const level of levels) {\n // Run all nodes in the same level in parallel, wait before next level\n await Promise.all(level.map(runTopoNode));\n }\n } else {\n // ── Hierarchical mode: leader review loops + recursive subtree runs ──\n let leaderAssignedReports = byParent.get(leader.id) ?? [];\n let leaderCurrentOutput = leaderDispatchOutput ?? outputs.get(leader.id) ?? '';\n let leaderAssignments: Map<string, string> = leaderDispatchAssignments;\n let leaderReviewRound = 0;\n\n while (leaderAssignedReports.length > 0) {\n if (signal.aborted) throw new Error('Aborted');\n leaderReviewRound += 1;\n if (leaderReviewRound > MAX_MANAGER_REVIEW_ROUNDS) {\n throw new Error(`${leader.label} exceeded review loop limit (${MAX_MANAGER_REVIEW_ROUNDS})`);\n }\n\n await readme(`\\n### [${ts()}] Leader review loop ${leaderReviewRound} — running assigned children in parallel\\n`);\n await Promise.all(leaderAssignedReports.map((report) => {\n const instruction = leaderAssignments.get(report.id) ?? null;\n return runNodeSubtree(report, instruction ?? leaderCurrentOutput);\n }));\n\n const leaderChildReportsSection = leaderAssignedReports\n .map((report) => {\n const reportOut = outputs.get(report.id) ?? '';\n return `<child_report node=\"${report.label}\" id=\"${report.id}\">\\n${reportOut}\\n</child_report>`;\n })\n .join('\\n\\n');\n\n const leaderReviewMsg = buildManagerReviewMessage(\n leader,\n getDirectReports(scenario.nodes, leader.id),\n userRequest,\n leaderCurrentOutput,\n leaderChildReportsSection,\n );\n const leaderPass = await runDelegationPass(leader, leaderReviewMsg, `(leader review round ${leaderReviewRound})`);\n leaderCurrentOutput = leaderPass.finalOutput;\n leaderDispatchOutput = leaderCurrentOutput;\n leaderAssignedReports = leaderPass.assignedReports;\n leaderAssignments = leaderPass.assignments;\n }\n\n resolveWaitingStates(scenario.nodes, conversationId, byParent, publish, new Set([scenario.leaderId]));\n }\n\n // ── Phase 2: Leader synthesis → writes FINAL.md ────────────────────────\n const synthesisKey = `${leader.id}:synthesis`;\n const synthesisAlreadyDone = persistedState?.nodeStates[synthesisKey] === 'synthesized'\n && !!persistedState?.nodeOutputs[synthesisKey];\n\n if (synthesisAlreadyDone) {\n const summary = persistedState!.nodeOutputs[synthesisKey]!;\n await writeFinalMd(conversationId, bus, userRequest, summary);\n finalWritten = true;\n scenarioRunStore.setNodeState(conversationId, leader.id, 'done');\n publish({ type: 'node_state_change', nodeId: leader.id, state: 'done' });\n scenarioRunStore.setNodeState(conversationId, synthesisKey, 'synthesized');\n publish({ type: 'node_state_change', nodeId: synthesisKey, state: 'synthesized' });\n publish({ type: 'scenario_complete', summary });\n await li('♻️', `Synthesis restored from previous run`);\n } else if (scenario.nodes.length > 1) {\n const startedAt = Date.now();\n publish({ type: 'node_started', nodeId: `${leader.id}:synthesis` });\n await readme(`\\n### [${ts()}] 🔄 ${leader.label} (Leader) — synthesizing all outputs\\n`);\n await li('▶️', `**${leader.label}** synthesis — started`);\n\n try {\n const systemPrompt = buildSystemPrompt(leader, scenario);\n const userMsg = buildUserMessage(leader, scenario, userRequest, null, true, false, outputs);\n\n let summary = '';\n summary = await runNodeCall(conversationId, leader, systemPrompt, userMsg, runOverrides, signal, publish, (delta) => {\n publish({ type: 'node_delta', nodeId: `${leader.id}:synthesis`, text: delta });\n }, runnerStates, 'synthesis', readme);\n\n await writeFinalMd(conversationId, bus, userRequest, summary);\n finalWritten = true;\n\n // Leader completion condition: FINAL.md has been written.\n scenarioRunStore.setNodeState(conversationId, leader.id, 'done');\n publish({ type: 'node_state_change', nodeId: leader.id, state: 'done' });\n\n scenarioRunStore.setNodeState(conversationId, `${leader.id}:synthesis`, 'synthesized');\n scenarioRunStore.setNodeOutput(conversationId, `${leader.id}:synthesis`, summary);\n await scenarioRunStore.persistRunState(conversationId);\n\n await li('✅', `**${leader.label}** synthesis — done in ${fmtDuration(startedAt)}`);\n publish({ type: 'node_done', nodeId: `${leader.id}:synthesis`, output: summary, state: 'synthesized' });\n publish({ type: 'scenario_complete', summary });\n } catch (err) {\n if (signal.aborted) throw err;\n // Synthesis failed — write FINAL.md with what we have as fallback\n const fallback = [...outputs.entries()]\n .map(([id, out]) => {\n const p = scenario.nodes.find(x => x.id === id);\n const name = p ? p.label.trim() : id;\n return `### ${name}\\n\\n${out}`;\n })\n .join('\\n\\n---\\n\\n');\n await readme(`\\n⚠️ Leader synthesis failed — writing partial FINAL.md\\n`);\n await li('❌', `**${leader.label}** synthesis — failed after ${fmtDuration(startedAt)}`);\n await writeFinalMd(conversationId, bus, userRequest, fallback);\n finalWritten = true;\n // Leader completion condition: FINAL.md has been written.\n scenarioRunStore.setNodeState(conversationId, leader.id, 'done');\n publish({ type: 'node_state_change', nodeId: leader.id, state: 'done' });\n publish({ type: 'scenario_complete', summary: fallback });\n }\n } else {\n // Solo leader — their output IS the final\n const summary = leaderDispatchOutput ?? outputs.get(leader.id) ?? '';\n await writeFinalMd(conversationId, bus, userRequest, summary);\n finalWritten = true;\n // Leader completion condition: FINAL.md has been written.\n scenarioRunStore.setNodeState(conversationId, leader.id, 'done');\n publish({ type: 'node_state_change', nodeId: leader.id, state: 'done' });\n publish({ type: 'scenario_complete', summary });\n }\n } catch (err) {\n if (!signal.aborted) {\n const msg = (err as Error).message;\n // Guard: if we exit without FINAL.md, report it explicitly\n if (!finalWritten) {\n await appendToReadme(conversationId, bus,\n `\\n### [${ts()}] 🚨 GUARD: Run ended without FINAL.md — ${msg}\\n`,\n ).catch(() => {/* non-fatal */});\n }\n publish({ type: 'scenario_error', error: msg });\n }\n } finally {\n if (!finalWritten && !signal.aborted) {\n // Secondary guard: bus closing without FINAL.md written\n await appendToReadme(conversationId, bus,\n `\\n### [${ts()}] 🚨 GUARD: No FINAL.md detected at end of run. Check individual agent outputs.\\n`,\n ).catch(() => {/* non-fatal */});\n }\n // Final persist: capture any state changes (solo-leader done, synthesis\n // fallback, last-second updates) so a reload after completion shows the\n // finished scenario instead of a fresh-looking one.\n await scenarioRunStore.persistRunState(conversationId).catch(() => {/* non-fatal */});\n publishToBus(bus, null); // signal end-of-stream\n activeAbortControllers.delete(conversationId);\n }\n }\n\n // Fire-and-forget — run asynchronously so callers can subscribe immediately\n execute().catch(() => {/* errors published to bus */});\n}\n","import type { ScenarioPreset } from '@runeya/packages-shared';\n\nconst BUILT_IN_PRESETS: ScenarioPreset[] = [\n {\n id: 'enterprise',\n name: 'Enterprise',\n icon: 'pi-building',\n labels: {\n group: { en: 'Department', fr: 'Département' },\n node: { en: 'Employee', fr: 'Employé' },\n role: { en: 'Position', fr: 'Poste' },\n leader: { en: 'Director', fr: 'Directeur' },\n },\n defaultTraversalMode: 'hierarchical',\n canChangeTraversalMode: false,\n initialData: {\n leaderId: 'leader',\n groups: [\n { id: 'group-management', name: 'Management', position: { x: 0, y: 0 }, width: 300, height: 200 },\n ],\n nodes: [\n {\n id: 'leader',\n type: 'ai' as const,\n parentIds: [],\n groupId: 'group-management',\n label: 'Leader One',\n role: 'manager',\n prompt: 'Analyze the objective. Break it into concrete tasks and assign each to the right team member with a clear expected output. Do not do the technical work yourself.',\n question: '',\n autoGenerated: false,\n canAddNode: false,\n aiCli: 'claude-code',\n model: 'sonnet',\n position: { x: 50, y: 50 },\n },\n ],\n },\n roles: [\n {\n id: 'manager',\n name: 'Manager',\n systemPrompt: [\n 'You are a MANAGER. Your only job is to coordinate, plan, and delegate.',\n 'NEVER write code, scripts, or any technical artifact — not even as an example.',\n 'NEVER answer a technical question directly — always assign it to the right person.',\n 'Output only: task breakdowns, assignments, decisions, and synthesis.',\n ].join('\\n'),\n prompt: '',\n },\n {\n id: 'engineer',\n name: 'Engineer',\n systemPrompt: [\n 'You are an ENGINEER. Write working, production-ready code.',\n 'Always prefer real implementation over pseudocode or high-level descriptions.',\n 'Be concise in prose; let the code speak.',\n 'Output: source files, architecture decisions, technical specifications.',\n ].join('\\n'),\n prompt: '',\n },\n {\n id: 'designer',\n name: 'Designer',\n systemPrompt: [\n 'You are a DESIGNER. Define UX flows, visual hierarchy, and interaction patterns.',\n 'NEVER write code or CSS.',\n 'Describe interfaces in structured text: component name, layout, states, behavior.',\n 'Output: text wireframes, design decisions, component specs, UX guidelines.',\n ].join('\\n'),\n prompt: '',\n },\n {\n id: 'analyst',\n name: 'Analyst',\n systemPrompt: [\n 'You are an ANALYST. Investigate data, identify patterns, and surface actionable insights.',\n 'NEVER write code or scripts — if you need data processed, request it from an Engineer.',\n 'Output: structured analysis, metrics, findings, and evidence-based recommendations.',\n ].join('\\n'),\n prompt: '',\n },\n {\n id: 'qa',\n name: 'QA',\n systemPrompt: [\n 'You are a QA ENGINEER. Define what must be tested and how.',\n 'NEVER write implementation code.',\n 'You may write Gherkin / BDD scenarios or structured test cases as plain text.',\n 'Output: test plans, test cases, edge cases, risk assessments, acceptance criteria.',\n ].join('\\n'),\n prompt: '',\n },\n {\n id: 'devops',\n name: 'DevOps',\n systemPrompt: [\n 'You are a DEVOPS ENGINEER. Own infrastructure, deployment, and operations.',\n 'Write actual scripts and configuration files (shell, YAML, HCL, Dockerfile…) — no pseudocode.',\n 'Output: scripts, CI/CD pipelines, infrastructure-as-code, runbooks.',\n ].join('\\n'),\n prompt: '',\n },\n {\n id: 'product',\n name: 'Product',\n systemPrompt: [\n 'You are a PRODUCT MANAGER. Own requirements and priorities.',\n 'NEVER write code or technical specifications.',\n 'Output: PRDs, user stories with acceptance criteria, prioritization decisions, roadmap items.',\n ].join('\\n'),\n prompt: '',\n },\n {\n id: 'writer',\n name: 'Writer',\n systemPrompt: [\n 'You are a TECHNICAL WRITER. Produce clear, accurate, well-structured written content.',\n 'NEVER write code. If a code example is needed, flag it for an Engineer.',\n 'Output: documentation, guides, release notes, changelogs, communication drafts.',\n ].join('\\n'),\n prompt: '',\n },\n {\n id: 'researcher',\n name: 'Researcher',\n systemPrompt: [\n 'You are a RESEARCHER. Gather information, compare options, and synthesize knowledge into actionable insights.',\n 'NEVER write code.',\n 'Output: research summaries, comparisons, pros/cons analyses, evidence-based recommendations.',\n ].join('\\n'),\n prompt: '',\n },\n {\n id: 'other',\n name: 'Other',\n systemPrompt: '',\n prompt: '',\n },\n ],\n },\n];\n\nexport function listPresets(): ScenarioPreset[] {\n return BUILT_IN_PRESETS;\n}\n\nexport function getPreset(id: string): ScenarioPreset | undefined {\n return BUILT_IN_PRESETS.find(p => p.id === id);\n}\n","import { randomUUID } from 'node:crypto';\nimport { TRPCError } from '@trpc/server';\nimport { z } from 'zod';\nimport { protectedProcedure, router } from '../trpc.js';\n\ntype RandomTickEvent = {\n type: 'tick';\n jobId: string;\n index: number;\n value: number;\n at: number;\n};\n\ntype RandomDoneEvent = {\n type: 'done';\n jobId: string;\n reason: 'stopped' | 'max_ticks';\n at: number;\n};\n\ntype RandomJobEvent = RandomTickEvent | RandomDoneEvent;\n\ninterface RandomJob {\n id: string;\n startedAt: number;\n intervalMs: number;\n maxTicks: number;\n tick: number;\n done: boolean;\n timer: ReturnType<typeof setInterval>;\n buffer: RandomJobEvent[];\n baseIndex: number;\n listeners: Set<(event: RandomJobEvent | null) => void>;\n}\n\nconst MAX_BUFFER = 300;\nconst jobs = new Map<string, RandomJob>();\n\nfunction publish(job: RandomJob, event: RandomJobEvent | null): void {\n if (event) {\n job.buffer.push(event);\n if (job.buffer.length > MAX_BUFFER) {\n job.buffer.shift();\n job.baseIndex += 1;\n }\n } else {\n job.done = true;\n }\n\n for (const listener of job.listeners) listener(event);\n job.listeners.clear();\n}\n\nfunction stopJob(jobId: string, reason: 'stopped' | 'max_ticks'): boolean {\n const job = jobs.get(jobId);\n if (!job) return false;\n if (job.done) return true;\n\n clearInterval(job.timer);\n publish(job, { type: 'done', jobId, reason, at: Date.now() });\n publish(job, null);\n jobs.delete(jobId);\n return true;\n}\n\nasync function* tapJob(job: RandomJob, signal: AbortSignal): AsyncGenerator<RandomJobEvent> {\n let cursor = job.baseIndex;\n\n while (true) {\n if (cursor < job.baseIndex) cursor = job.baseIndex;\n while (cursor < job.baseIndex + job.buffer.length) {\n const evt = job.buffer[cursor - job.baseIndex];\n cursor += 1;\n if (!evt) continue;\n yield evt;\n }\n\n if (job.done || signal.aborted) return;\n\n await new Promise<void>((resolve) => {\n const onAbort = () => {\n job.listeners.delete(notify);\n resolve();\n };\n\n const notify = () => {\n signal.removeEventListener('abort', onAbort);\n resolve();\n };\n\n job.listeners.add(notify);\n signal.addEventListener('abort', onAbort, { once: true });\n if (cursor < job.baseIndex + job.buffer.length || job.done || signal.aborted) {\n job.listeners.delete(notify);\n signal.removeEventListener('abort', onAbort);\n resolve();\n }\n });\n }\n}\n\nexport const debugRouter = router({\n startRandomJob: protectedProcedure\n .input(z.object({\n intervalMs: z.number().int().min(100).max(5000).optional(),\n maxTicks: z.number().int().min(1).max(10000).optional(),\n }).optional())\n .mutation(({ input }) => {\n const jobId = randomUUID();\n const intervalMs = input?.intervalMs ?? 400;\n const maxTicks = input?.maxTicks ?? 500;\n\n const job: RandomJob = {\n id: jobId,\n startedAt: Date.now(),\n intervalMs,\n maxTicks,\n tick: 0,\n done: false,\n timer: setInterval(() => {\n const current = jobs.get(jobId);\n if (!current || current.done) return;\n\n current.tick += 1;\n publish(current, {\n type: 'tick',\n jobId,\n index: current.tick,\n value: Math.random(),\n at: Date.now(),\n });\n\n if (current.tick >= current.maxTicks) {\n stopJob(jobId, 'max_ticks');\n }\n }, intervalMs),\n buffer: [],\n baseIndex: 0,\n listeners: new Set(),\n };\n\n jobs.set(jobId, job);\n return { jobId, intervalMs, maxTicks, startedAt: job.startedAt };\n }),\n\n streamRandomJob: protectedProcedure\n .input(z.object({ jobId: z.string().max(128) }))\n .subscription(async function* ({ input, signal }) {\n const job = jobs.get(input.jobId);\n if (!job) {\n throw new TRPCError({ code: 'NOT_FOUND', message: 'Random job not found' });\n }\n\n yield* tapJob(job, signal ?? new AbortController().signal);\n }),\n\n stopRandomJob: protectedProcedure\n .input(z.object({ jobId: z.string().max(128) }))\n .mutation(({ input }) => ({ ok: stopJob(input.jobId, 'stopped') })),\n\n randomJobStatus: protectedProcedure\n .input(z.object({ jobId: z.string().max(128) }))\n .query(({ input }) => {\n const job = jobs.get(input.jobId);\n return {\n running: !!job && !job.done,\n tick: job?.tick ?? 0,\n };\n }),\n});\n","import { z } from 'zod';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { kanbanQueue } from '../../services/kanban-queue.js';\nimport type { KanbanQueueState } from '../../services/kanban-queue.js';\n\nexport const kanbanQueueRouter = router({\n getState: protectedProcedure.query(() => kanbanQueue.getState()),\n\n add: protectedProcedure\n .input(z.object({\n boardId: z.string().max(128),\n cardId: z.string().max(128),\n runner: z.enum(['claude-code', 'codex']).optional(),\n model: z.string().max(128).optional(),\n scenarioId: z.string().max(128).optional(),\n }))\n .mutation(({ input }) => kanbanQueue.add(input)),\n\n addColumn: protectedProcedure\n .input(z.object({\n boardId: z.string().max(128),\n columnId: z.string().max(128),\n runner: z.enum(['claude-code', 'codex']).optional(),\n model: z.string().max(128).optional(),\n scenarioId: z.string().max(128).optional(),\n }))\n .mutation(async ({ input }) => {\n const { boardId, columnId, ...options } = input;\n return kanbanQueue.addColumn(boardId, columnId, options);\n }),\n\n remove: protectedProcedure\n .input(z.object({ itemId: z.string().max(128) }))\n .mutation(({ input }) => ({ removed: kanbanQueue.remove(input.itemId) })),\n\n stopAll: protectedProcedure\n .mutation(() => { kanbanQueue.stopAll(); return { ok: true }; }),\n\n setMaxConcurrent: protectedProcedure\n .input(z.object({ max: z.number().int().min(1).max(20) }))\n .mutation(({ input }) => { kanbanQueue.setMaxConcurrent(input.max); return kanbanQueue.getState(); }),\n\n onChanged: protectedProcedure.subscription(async function* () {\n const queue: KanbanQueueState[] = [];\n let resolve: (() => void) | null = null;\n\n const handler = () => {\n if (queue.length >= 50) queue.shift();\n queue.push(kanbanQueue.getState());\n if (resolve) { resolve(); resolve = null; }\n };\n\n kanbanQueue.on('changed', handler);\n // Emit initial state\n queue.push(kanbanQueue.getState());\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n kanbanQueue.off('changed', handler);\n }\n }),\n});\n","import { randomUUID } from 'node:crypto';\nimport { EventEmitter } from 'node:events';\nimport { kanbanStore } from './kanban-store.js';\nimport { conversationStore } from './conversation-store.js';\nimport { scenarioRunStore } from './scenario-run-store.js';\nimport { scenarioStore } from './scenario-store.js';\nimport { runScenario, tapBus, abortScenario } from './scenario-runner.js';\nimport { activeSessionRegistry } from './active-session-registry.js';\nimport { startClaudeCodeSession, startCodexSession } from '../trpc/routers/chat.js';\n\nexport interface KanbanQueueItem {\n id: string;\n boardId: string;\n cardId: string;\n runner?: 'claude-code' | 'codex';\n model?: string;\n scenarioId?: string;\n addedAt: string;\n}\n\ninterface KanbanRunningItem {\n id: string;\n boardId: string;\n cardId: string;\n conversationId: string;\n startedAt: string;\n}\n\nexport interface KanbanQueueState {\n items: KanbanQueueItem[];\n running: KanbanRunningItem[];\n maxConcurrent: number;\n}\n\nclass KanbanQueueService extends EventEmitter {\n private items: KanbanQueueItem[] = [];\n private running: KanbanRunningItem[] = [];\n private maxConcurrent = 1;\n private startingCount = 0; // items whose startItem() is in-flight but not yet in this.running\n\n getState(): KanbanQueueState {\n return {\n items: [...this.items],\n running: [...this.running],\n maxConcurrent: this.maxConcurrent,\n };\n }\n\n add(item: Omit<KanbanQueueItem, 'id' | 'addedAt'>): KanbanQueueItem {\n const alreadyQueued = this.items.find(i => i.boardId === item.boardId && i.cardId === item.cardId);\n if (alreadyQueued) return alreadyQueued;\n const alreadyRunning = this.running.find(r => r.boardId === item.boardId && r.cardId === item.cardId);\n if (alreadyRunning) {\n // Return a fake item representing the running entry\n return { id: alreadyRunning.id, addedAt: alreadyRunning.startedAt, ...item };\n }\n\n const queueItem: KanbanQueueItem = {\n id: randomUUID(),\n ...item,\n addedAt: new Date().toISOString(),\n };\n this.items.push(queueItem);\n this.emit('changed');\n this.tick();\n return queueItem;\n }\n\n async addColumn(\n boardId: string,\n columnId: string,\n options: { runner?: 'claude-code' | 'codex'; model?: string; scenarioId?: string },\n ): Promise<KanbanQueueItem[]> {\n const board = await kanbanStore.get(boardId);\n if (!board) return [];\n const col = board.columns.find(c => c.id === columnId);\n if (!col) return [];\n return col.cards.map(card => this.add({ boardId, cardId: card.id, ...options }));\n }\n\n remove(itemId: string): boolean {\n const idx = this.items.findIndex(i => i.id === itemId);\n if (idx >= 0) {\n this.items.splice(idx, 1);\n this.emit('changed');\n return true;\n }\n const runIdx = this.running.findIndex(r => r.id === itemId);\n if (runIdx >= 0) {\n const run = this.running[runIdx];\n abortScenario(run.conversationId);\n activeSessionRegistry.kill(run.conversationId);\n this.running.splice(runIdx, 1);\n this.emit('changed');\n this.tick();\n return true;\n }\n return false;\n }\n\n stopAll(): void {\n this.items = [];\n for (const run of this.running) {\n abortScenario(run.conversationId);\n activeSessionRegistry.kill(run.conversationId);\n }\n this.running = [];\n this.emit('changed');\n }\n\n setMaxConcurrent(max: number): void {\n this.maxConcurrent = Math.max(1, max);\n this.emit('changed');\n this.tick();\n }\n\n private tick(): void {\n while (this.running.length + this.startingCount < this.maxConcurrent && this.items.length > 0) {\n const item = this.items.shift()!;\n this.startingCount++;\n this.startItem(item).catch(err => {\n console.error('[kanban-queue] startItem error:', err);\n }).finally(() => {\n this.startingCount--;\n });\n }\n }\n\n private async startItem(item: KanbanQueueItem): Promise<void> {\n const board = await kanbanStore.get(item.boardId);\n if (!board) { this.tick(); return; }\n\n let card = null;\n for (const col of board.columns) {\n card = col.cards.find(c => c.id === item.cardId) ?? null;\n if (card) break;\n }\n if (!card) { this.tick(); return; }\n\n const conv = await conversationStore.create(\n `Queue: ${card.title}`,\n !!item.runner,\n item.scenarioId,\n item.scenarioId ? 'scenario' : undefined,\n item.runner,\n item.boardId,\n item.cardId,\n );\n\n const cardContent = card.title + (card.markdown ? '\\n\\n' + card.markdown : '');\n\n if (item.scenarioId) {\n const scenario = await scenarioStore.get(item.scenarioId);\n if (scenario) {\n await scenarioRunStore.initializeConversationWorkspace(conv.id, scenario, cardContent);\n }\n }\n\n const runItem: KanbanRunningItem = {\n id: item.id,\n boardId: item.boardId,\n cardId: item.cardId,\n conversationId: conv.id,\n startedAt: new Date().toISOString(),\n };\n this.running.push(runItem);\n this.emit('changed');\n\n // Write conversation_started history entry so the frontend can show status badges\n const eventType = item.scenarioId ? 'scenario_started' : 'conversation_started';\n for (const col of board.columns) {\n const target = col.cards.find(c => c.id === item.cardId);\n if (target) {\n target.history = [...(target.history ?? []), {\n type: eventType,\n timestamp: new Date().toISOString(),\n detail: conv.id,\n }];\n kanbanStore.update({ id: board.id, columns: board.columns }).catch(() => {});\n break;\n }\n }\n\n if (item.scenarioId) {\n void runScenario(conv.id, item.scenarioId, cardContent, {\n runnerOverride: item.runner,\n modelOverride: item.model,\n });\n this.monitorCompletion(runItem).catch(() => {});\n } else if (item.runner) {\n this.runWithRunner(runItem, item, cardContent).catch(err => {\n console.error('[kanban-queue] runWithRunner error:', err);\n this.finishItem(item.id);\n });\n } else {\n this.finishItem(item.id);\n }\n }\n\n private async runWithRunner(\n runItem: KanbanRunningItem,\n item: KanbanQueueItem,\n cardContent: string,\n ): Promise<void> {\n try {\n const model = item.model || (item.runner === 'codex' ? '' : 'claude-opus-4-6');\n const starter = item.runner === 'codex' ? startCodexSession : startClaudeCodeSession;\n const { done } = await starter(runItem.conversationId, cardContent, { model });\n await done;\n } finally {\n this.finishItem(runItem.id);\n }\n }\n\n private async monitorCompletion(runItem: KanbanRunningItem): Promise<void> {\n // Wait a bit for the scenario bus to be created\n await new Promise(r => setTimeout(r, 100));\n const abortCtrl = new AbortController();\n try {\n for await (const event of tapBus(runItem.conversationId, abortCtrl.signal)) {\n if (event.type === 'scenario_complete') break;\n }\n } catch {\n // Aborted or ended\n } finally {\n this.finishItem(runItem.id);\n }\n }\n\n private finishItem(itemId: string): void {\n const idx = this.running.findIndex(r => r.id === itemId);\n if (idx >= 0) this.running.splice(idx, 1);\n this.emit('changed');\n this.tick();\n }\n}\n\nexport const kanbanQueue = new KanbanQueueService();\n","import { z } from 'zod';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { executeKanbanCommands, executeKanbanBoardCommands } from '../../services/kanban-commands.js';\n\nexport const kanbanRouter = router({\n moveCard: protectedProcedure\n .input(z.object({\n boardId: z.string().max(128),\n cardId: z.string().max(128),\n targetColumn: z.string().max(256),\n }))\n .mutation(async ({ input }) => {\n await executeKanbanCommands(input.boardId, input.cardId, [\n { type: 'move_card', columnTitle: input.targetColumn },\n ]);\n return { ok: true };\n }),\n\n addComment: protectedProcedure\n .input(z.object({\n boardId: z.string().max(128),\n cardId: z.string().max(128),\n comment: z.string().max(20000),\n }))\n .mutation(async ({ input }) => {\n await executeKanbanCommands(input.boardId, input.cardId, [\n { type: 'add_comment', comment: input.comment },\n ]);\n return { ok: true };\n }),\n\n addCard: protectedProcedure\n .input(z.object({\n boardId: z.string().max(128),\n column: z.string().max(256),\n title: z.string().max(512),\n content: z.string().max(20000).optional(),\n }))\n .mutation(async ({ input }) => {\n await executeKanbanBoardCommands(input.boardId, [\n { type: 'add_card', columnTitle: input.column, cardTitle: input.title, cardContent: input.content },\n ]);\n return { ok: true };\n }),\n});\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { agentManager } from '../../services/agent-manager.js';\n\nexport const terminalRouter = router({\n /** Create a PTY shell session on the target agent */\n create: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n cwd: z.string().max(512).optional(),\n cols: z.number().int().min(1).max(512).optional(),\n rows: z.number().int().min(1).max(256).optional(),\n }))\n .mutation(async ({ input }) => {\n const result = await agentManager.agentMutation<{ sessionId: string }>(\n input.agentId,\n 'terminal.create',\n { cwd: input.cwd, cols: input.cols, rows: input.rows },\n );\n return result;\n }),\n\n /** Send keystrokes / data to a PTY session */\n write: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n sessionId: z.string().max(128),\n data: z.string().max(65536),\n }))\n .mutation(async ({ input }) => {\n await agentManager.agentMutation(\n input.agentId,\n 'terminal.write',\n { sessionId: input.sessionId, data: input.data },\n );\n return { ok: true as const };\n }),\n\n /** Resize the PTY */\n resize: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n sessionId: z.string().max(128),\n cols: z.number().int().min(1).max(512),\n rows: z.number().int().min(1).max(256),\n }))\n .mutation(async ({ input }) => {\n await agentManager.agentMutation(\n input.agentId,\n 'terminal.resize',\n { sessionId: input.sessionId, cols: input.cols, rows: input.rows },\n );\n return { ok: true as const };\n }),\n\n /** Destroy a PTY session */\n destroy: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n sessionId: z.string().max(128),\n }))\n .mutation(async ({ input }) => {\n await agentManager.agentMutation(\n input.agentId,\n 'terminal.destroy',\n { sessionId: input.sessionId },\n );\n return { ok: true as const };\n }),\n\n /** Stream PTY output — proxied via AgentWSBridge dynamic subscription */\n onData: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n sessionId: z.string().max(128),\n }))\n .subscription(async function* ({ input }) {\n const queue: string[] = [];\n let resolve: (() => void) | null = null;\n let done = false;\n\n let unsubscribe: (() => void) | undefined;\n try {\n unsubscribe = agentManager.agentSubscribe(\n input.agentId,\n 'terminal.onData',\n { sessionId: input.sessionId },\n (data) => {\n if (typeof data === 'string') queue.push(data);\n if (resolve) { resolve(); resolve = null; }\n },\n () => {\n done = true;\n if (resolve) { resolve(); resolve = null; }\n },\n );\n } catch (err) {\n throw new TRPCError({\n code: 'BAD_REQUEST',\n message: `Cannot subscribe to terminal: ${(err as Error).message}`,\n });\n }\n\n try {\n while (!done || queue.length > 0) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n unsubscribe?.();\n }\n }),\n});\n","import { z } from 'zod';\nimport { router, protectedProcedure } from '../trpc.js';\n\nconst MAX_WAIT_MS = 5 * 60 * 1000; // 5 minutes max\n\nexport const utilityRouter = router({\n wait: protectedProcedure\n .input(z.object({\n ms: z.number().int().min(0).max(MAX_WAIT_MS),\n }))\n .mutation(async ({ input }) => {\n await new Promise(resolve => setTimeout(resolve, input.ms));\n return { waited: input.ms };\n }),\n});\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { readFile, readdir, stat, realpath, writeFile, mkdir, rename, rm } from 'node:fs/promises';\nimport type { Dirent } from 'node:fs';\nimport { resolve as resolvePath, join, relative, sep, dirname } from 'node:path';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { env } from '../../config/env.js';\nimport { serviceStore } from '../../services/service-store.js';\nimport { settingsManager } from '../../services/settings-manager.js';\nimport { agentManager } from '../../services/agent-manager.js';\nimport { resolveEffectiveAgentId } from './service.js';\n\nconst SCOPE_SCHEMA = z.union([\n z.literal('global'),\n z.string().regex(/^service:[A-Za-z0-9_-]{1,128}$/, 'Invalid service scope'),\n]);\nconst REL_PATH_SCHEMA = z\n .string()\n .min(1)\n .max(512)\n .regex(/^[A-Za-z0-9_./-]+$/)\n .refine((p) => !p.includes('..') && !p.startsWith('/'), {\n message: 'Path must be a relative path without traversal',\n });\n\nconst MAX_FILES = 500;\nconst MAX_DEPTH = 8;\nconst MAX_FILE_BYTES = 2_000_000;\nconst IGNORED_DIRS = new Set([\n 'node_modules', '.git', 'dist', 'build', '.next', '.turbo',\n '.cache', 'coverage', '.yarn', '.pnpm-store', 'target', 'out',\n]);\n\ntype DocsFileEntry = { type: 'file'; name: string; path: string };\ntype DocsDirEntry = { type: 'dir'; name: string; path: string; children: DocsEntry[] };\nexport type DocsEntry = DocsFileEntry | DocsDirEntry;\n\nconst DocsEntrySchema: z.ZodType<DocsEntry> = z.lazy(() => z.union([\n z.object({ type: z.literal('file'), name: z.string(), path: z.string() }),\n z.object({ type: z.literal('dir'), name: z.string(), path: z.string(), children: z.array(DocsEntrySchema) }),\n]));\n\n/**\n * For service scope: resolve via agent (agent expands $VAR and ~).\n * Returns { mode: 'agent', agentId, cwd } to call agent endpoints.\n *\n * For global scope: resolve locally on the server using the absolute globalDocsPath.\n * Returns { mode: 'local', root }.\n */\nasync function resolveScope(scope: string): Promise<\n | { mode: 'agent'; agentId: string; cwd: string }\n | { mode: 'local'; root: string }\n> {\n if (scope === 'global') {\n const settings = await settingsManager.getSettings();\n const sub = (settings.globalDocsPath?.trim() || 'wiki').replace(/^[\\\\/]+|[\\\\/]+$/g, '');\n if (sub.includes('..') || sub.includes('\\0')) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Sous-chemin invalide' });\n }\n // Base = parent of DATA_DIR (docs live alongside the data dir, not inside it)\n const dataDirAbs = resolvePath(env.DATA_DIR);\n await mkdir(dataDirAbs, { recursive: true });\n const base = dirname(await realpath(dataDirAbs));\n const target = resolvePath(base, sub);\n // Pre-check (defense-in-depth): the resolved target path must already live under base.\n if (target !== base && !(target + sep).startsWith(base + sep)) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Hors du dossier de données du serveur' });\n }\n await mkdir(target, { recursive: true });\n const root = await realpath(target);\n // Post-realpath check: a pre-existing symlink at `target` could resolve outside base.\n if (root !== base && !(root + sep).startsWith(base + sep)) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Le dossier wiki résout hors du dossier de données' });\n }\n return { mode: 'local', root };\n }\n // service:<id>\n const serviceId = scope.slice('service:'.length);\n const service = await serviceStore.get(serviceId);\n if (!service) throw new TRPCError({ code: 'NOT_FOUND', message: 'Service introuvable' });\n const agentId = await resolveEffectiveAgentId(service);\n if (!agentId) throw new TRPCError({ code: 'BAD_REQUEST', message: 'Aucun agent configuré pour ce service' });\n // Pass docsPath if defined, else fall back to cwd.\n const cwd = (service.docsPath?.trim() || service.cwd || '.').toString();\n return { mode: 'agent', agentId, cwd };\n}\n\n// ─── Local FS helpers (for global scope) ──────────────────────────────\n\nasync function walkLocal(root: string, dir: string, depth: number, counter: { n: number }): Promise<DocsEntry[]> {\n if (depth > MAX_DEPTH || counter.n >= MAX_FILES) return [];\n let entries: Dirent[];\n try { entries = await readdir(dir, { withFileTypes: true }); } catch { return []; }\n const out: DocsEntry[] = [];\n for (const e of entries) {\n if (counter.n >= MAX_FILES) break;\n if (e.name.startsWith('.') && e.name !== '.') continue;\n const abs = join(dir, e.name);\n const rel = relative(root, abs).split(sep).join('/');\n if (e.isDirectory()) {\n if (IGNORED_DIRS.has(e.name)) continue;\n const children = await walkLocal(root, abs, depth + 1, counter);\n out.push({ type: 'dir', name: e.name, path: rel, children });\n } else if (e.isFile() && /\\.(md|markdown)$/i.test(e.name)) {\n counter.n += 1;\n out.push({ type: 'file', name: e.name, path: rel });\n }\n }\n out.sort((a, b) => {\n if (a.type !== b.type) return a.type === 'dir' ? -1 : 1;\n return a.name.localeCompare(b.name);\n });\n return out;\n}\n\nasync function resolveSafeLocal(root: string, relPath: string, requireExist: boolean): Promise<string> {\n if (relPath.includes('..') || relPath.startsWith('/')) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Chemin invalide' });\n }\n const target = resolvePath(root, relPath);\n if (requireExist) {\n let real: string;\n try { real = await realpath(target); } catch {\n throw new TRPCError({ code: 'NOT_FOUND', message: 'Chemin introuvable' });\n }\n if (real !== root && !(real + sep).startsWith(root + sep)) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Hors du dossier autorisé' });\n }\n return real;\n }\n const parent = dirname(target);\n let realParent: string;\n try { realParent = await realpath(parent); } catch { realParent = parent; }\n if (realParent !== root && !(realParent + sep).startsWith(root + sep)) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Hors du dossier autorisé' });\n }\n return resolvePath(realParent, target.slice(parent.length).replace(/^[\\\\/]+/, ''));\n}\n\n// ─── Router ───────────────────────────────────────────────────────────\n\nexport const wikiRouter = router({\n list: protectedProcedure\n .input(z.object({ scope: SCOPE_SCHEMA }))\n .output(z.object({ root: z.string(), entries: z.array(DocsEntrySchema), truncated: z.boolean() }))\n .query(async ({ input }) => {\n const target = await resolveScope(input.scope);\n if (target.mode === 'agent') {\n return agentManager.agentQuery(target.agentId, 'wiki.listRepoMarkdown', { cwd: target.cwd }) as Promise<{ root: string; entries: DocsEntry[]; truncated: boolean }>;\n }\n const counter = { n: 0 };\n const entries = await walkLocal(target.root, target.root, 0, counter);\n return { root: target.root, entries, truncated: counter.n >= MAX_FILES };\n }),\n\n read: protectedProcedure\n .input(z.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA }))\n .output(z.object({ path: z.string(), content: z.string() }))\n .query(async ({ input }) => {\n if (!/\\.(md|markdown)$/i.test(input.path)) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Seuls les .md/.markdown sont autorisés' });\n }\n const target = await resolveScope(input.scope);\n if (target.mode === 'agent') {\n return agentManager.agentQuery(target.agentId, 'wiki.readRepoMarkdown', { cwd: target.cwd, path: input.path }) as Promise<{ path: string; content: string }>;\n }\n const file = await resolveSafeLocal(target.root, input.path, true);\n const s = await stat(file);\n if (!s.isFile()) throw new TRPCError({ code: 'BAD_REQUEST', message: 'Pas un fichier' });\n if (s.size > MAX_FILE_BYTES) throw new TRPCError({ code: 'PAYLOAD_TOO_LARGE', message: 'Fichier trop volumineux' });\n const content = await readFile(file, 'utf-8');\n return { path: input.path, content };\n }),\n\n write: protectedProcedure\n .input(z.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA, content: z.string().max(5_000_000) }))\n .mutation(async ({ input }) => {\n if (!/\\.(md|markdown)$/i.test(input.path)) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Seuls les .md/.markdown sont autorisés' });\n }\n const target = await resolveScope(input.scope);\n if (target.mode === 'agent') {\n return agentManager.agentMutation(target.agentId, 'wiki.writeMarkdown', { cwd: target.cwd, path: input.path, content: input.content }) as Promise<{ path: string; ok: boolean }>;\n }\n const file = await resolveSafeLocal(target.root, input.path, false);\n await mkdir(dirname(file), { recursive: true });\n await writeFile(file, input.content, 'utf-8');\n return { path: input.path, ok: true };\n }),\n\n createFile: protectedProcedure\n .input(z.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA }))\n .mutation(async ({ input }) => {\n if (!/\\.(md|markdown)$/i.test(input.path)) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Seuls les .md/.markdown sont autorisés' });\n }\n const target = await resolveScope(input.scope);\n if (target.mode === 'agent') {\n return agentManager.agentMutation(target.agentId, 'wiki.createFile', { cwd: target.cwd, path: input.path }) as Promise<{ path: string; ok: boolean }>;\n }\n const file = await resolveSafeLocal(target.root, input.path, false);\n try { await stat(file); throw new TRPCError({ code: 'CONFLICT', message: 'Fichier déjà existant' }); }\n catch (err) { if (err instanceof TRPCError) throw err; }\n await mkdir(dirname(file), { recursive: true });\n await writeFile(file, '', 'utf-8');\n return { path: input.path, ok: true };\n }),\n\n createDir: protectedProcedure\n .input(z.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA }))\n .mutation(async ({ input }) => {\n const target = await resolveScope(input.scope);\n if (target.mode === 'agent') {\n return agentManager.agentMutation(target.agentId, 'wiki.createDir', { cwd: target.cwd, path: input.path }) as Promise<{ path: string; ok: boolean }>;\n }\n const dir = await resolveSafeLocal(target.root, input.path, false);\n await mkdir(dir, { recursive: true });\n return { path: input.path, ok: true };\n }),\n\n rename: protectedProcedure\n .input(z.object({ scope: SCOPE_SCHEMA, fromPath: REL_PATH_SCHEMA, toPath: REL_PATH_SCHEMA }))\n .mutation(async ({ input }) => {\n const target = await resolveScope(input.scope);\n if (target.mode === 'agent') {\n return agentManager.agentMutation(target.agentId, 'wiki.renamePath', { cwd: target.cwd, fromPath: input.fromPath, toPath: input.toPath }) as Promise<{ fromPath: string; toPath: string; ok: boolean }>;\n }\n const from = await resolveSafeLocal(target.root, input.fromPath, true);\n const to = await resolveSafeLocal(target.root, input.toPath, false);\n try { await stat(to); throw new TRPCError({ code: 'CONFLICT', message: 'La cible existe déjà' }); }\n catch (err) { if (err instanceof TRPCError) throw err; }\n await mkdir(dirname(to), { recursive: true });\n await rename(from, to);\n return { fromPath: input.fromPath, toPath: input.toPath, ok: true };\n }),\n\n ensureRoot: protectedProcedure\n .input(z.object({ scope: SCOPE_SCHEMA }))\n .mutation(async ({ input }) => {\n if (input.scope === 'global') {\n // Already created by resolveScope for global — call it once to materialise\n await resolveScope('global');\n return { ok: true };\n }\n // Service scope: ask the agent to mkdir its resolved docsPath\n const serviceId = input.scope.slice('service:'.length);\n const service = await serviceStore.get(serviceId);\n if (!service) throw new TRPCError({ code: 'NOT_FOUND', message: 'Service introuvable' });\n const agentId = await resolveEffectiveAgentId(service);\n if (!agentId) throw new TRPCError({ code: 'BAD_REQUEST', message: 'Aucun agent configuré' });\n const cwd = (service.docsPath?.trim() || service.cwd || '.').toString();\n return agentManager.agentMutation(agentId, 'wiki.ensureRoot', { cwd }) as Promise<{ root: string; ok: boolean }>;\n }),\n\n delete: protectedProcedure\n .input(z.object({ scope: SCOPE_SCHEMA, path: REL_PATH_SCHEMA }))\n .mutation(async ({ input }) => {\n const target = await resolveScope(input.scope);\n if (target.mode === 'agent') {\n return agentManager.agentMutation(target.agentId, 'wiki.deletePath', { cwd: target.cwd, path: input.path }) as Promise<{ path: string; ok: boolean }>;\n }\n const fp = await resolveSafeLocal(target.root, input.path, true);\n if (fp === target.root) throw new TRPCError({ code: 'FORBIDDEN', message: 'Impossible de supprimer la racine' });\n await rm(fp, { recursive: true, force: true });\n return { path: input.path, ok: true };\n }),\n});\n","import { router, publicProcedure } from '../trpc.js';\nimport { env } from '../../config/env.js';\n\n/**\n * Runtime configuration the web app needs before/without authentication.\n * The cloud endpoints are set on the server at launch (env vars) and fetched\n * by the web — never configured in the browser.\n */\nexport const configRouter = router({\n cloud: publicProcedure.query(() => ({\n apiUrl: env.CLOUD_URL,\n appUrl: env.CLOUD_APP_URL,\n })),\n});\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { cloudSyncStore } from '../../services/cloud-sync-store.js';\nimport { cloudSyncBridge } from '../../services/cloud-sync-bridge.js';\nimport { cloudFetch } from './cloud-auth.js';\nimport { matchesCanary, readVerifyFile } from '../../services/master-password.js';\nimport { getEncryptionKey } from '../../utils/encryption-key.js';\nimport { env } from '../../config/env.js';\n\n/**\n * Reconcile this machine's encryption key with the organization's.\n *\n * Members share one key, out of band — the cloud never carries it. What the org\n * does publish is a canary: a blob only the right key can open. So before\n * syncing, this machine proves its key opens the org's canary; otherwise it\n * would happily receive everyone's data and be unable to read any secret in it,\n * with no explanation.\n *\n * The first machine to sync an org publishes its own canary and becomes the\n * reference for the others.\n */\nasync function reconcileOrgCanary(orgId: string): Promise<void> {\n const key = getEncryptionKey();\n if (!key) {\n throw new TRPCError({ code: 'PRECONDITION_FAILED', message: 'Encryption key not loaded.' });\n }\n const local = await readVerifyFile(env.DATA_DIR);\n if (!local) {\n throw new TRPCError({ code: 'PRECONDITION_FAILED', message: 'This machine has no key canary yet.' });\n }\n\n // Publishing is write-once server-side: the value that comes back is the org's\n // reference, whether we just set it or someone else already had.\n const res = await cloudFetch('/api/auth/organization/canary', {\n method: 'POST',\n body: { organizationId: orgId, canary: local },\n });\n if (!res.ok) {\n throw new TRPCError({ code: 'BAD_GATEWAY', message: 'Could not reach the organization on the cloud.' });\n }\n const { canary } = (await res.json()) as { canary?: unknown };\n if (typeof canary !== 'string') {\n throw new TRPCError({ code: 'BAD_GATEWAY', message: 'The cloud returned no key canary.' });\n }\n if (!matchesCanary(canary, key)) {\n throw new TRPCError({\n code: 'FORBIDDEN',\n message:\n 'This organization uses a different encryption key. Ask a member for the key already in use,'\n + ' then set it up on this machine before syncing.',\n });\n }\n}\n\n/**\n * Manages this local server's continuous-sync links to the cloud.\n *\n * A link carries no credential: the transport authenticates with this machine's\n * cloud session, so the web UI only has to say which org to sync.\n */\nexport const cloudSyncRouter = router({\n /**\n * Register/replace a sync link for an org and start syncing immediately.\n *\n * Refuses when this machine's key is not the org's — better to stop here than\n * to sync a project whose secrets will not open.\n */\n link: protectedProcedure\n .input(\n z.object({\n orgId: z.string().min(1).max(128),\n cloudUrl: z.string().url().max(2048),\n }),\n )\n .mutation(async ({ input }) => {\n await reconcileOrgCanary(input.orgId);\n await cloudSyncStore.upsert(input.orgId, input.cloudUrl);\n await cloudSyncBridge.connect({ orgId: input.orgId, cloudUrl: input.cloudUrl });\n return { success: true as const };\n }),\n\n /** Stop syncing an org and forget its token. */\n unlink: protectedProcedure\n .input(z.object({ orgId: z.string().min(1).max(128) }))\n .mutation(async ({ input }) => {\n cloudSyncBridge.disconnect(input.orgId);\n await cloudSyncStore.remove(input.orgId);\n return { success: true as const };\n }),\n\n /**\n * List orgs this server is linked to, with their live sync state so the UI can\n * surface an org whose sync is paused awaiting a fresh cloud sign-in.\n */\n list: protectedProcedure.query(async () => {\n const links = await cloudSyncStore.list();\n const states = new Map(cloudSyncBridge.states().map((s) => [s.orgId, s.state]));\n return links.map((l) => ({\n orgId: l.orgId,\n cloudUrl: l.cloudUrl,\n state: states.get(l.orgId) ?? 'stopped',\n }));\n }),\n});\n","import { readFile, writeFile, rename, mkdir, chmod } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { env } from '../config/env.js';\n\nconst FILENAME = 'cloud-sync.json';\n\n/** A cloud sync link: an org this local server continuously syncs with. */\nexport interface CloudSyncLink {\n orgId: string;\n cloudUrl: string;\n}\n\n/**\n * Persists which organizations this local server continuously syncs with.\n *\n * No credentials live here: the sync transport authenticates with this\n * machine's cloud session (see `cloud-session-store.ts`), read fresh on every\n * request. A link is therefore only a pointer, and access follows the session —\n * signing out of the cloud stops the sync, and signing back in resumes it.\n */\nclass CloudSyncStore {\n private links: Map<string, CloudSyncLink> = new Map();\n private loaded = false;\n\n private getFilePath(): string {\n return join(env.DATA_DIR, FILENAME);\n }\n\n private async load(): Promise<void> {\n if (this.loaded) return;\n try {\n const raw = await readFile(this.getFilePath(), 'utf-8');\n const data: (CloudSyncLink & { encryptedToken?: string })[] = JSON.parse(raw);\n // Links written before session auth carry an `encryptedToken` — it is now\n // unused, and dropped on the next save.\n for (const l of data) this.links.set(l.orgId, { orgId: l.orgId, cloudUrl: l.cloudUrl });\n } catch {\n // No file yet — start empty.\n }\n this.loaded = true;\n }\n\n private async save(): Promise<void> {\n await mkdir(env.DATA_DIR, { recursive: true });\n const filePath = this.getFilePath();\n const tmpPath = filePath + '.tmp';\n const data = JSON.stringify(Array.from(this.links.values()), null, 2);\n await writeFile(tmpPath, data, 'utf-8');\n await rename(tmpPath, filePath);\n await chmod(filePath, 0o600);\n }\n\n /** Store (or replace) the sync link for an organization. */\n async upsert(orgId: string, cloudUrl: string): Promise<void> {\n await this.load();\n this.links.set(orgId, { orgId, cloudUrl });\n await this.save();\n }\n\n async remove(orgId: string): Promise<void> {\n await this.load();\n if (this.links.delete(orgId)) await this.save();\n }\n\n /** All sync links (for the bridge on startup). */\n async list(): Promise<CloudSyncLink[]> {\n await this.load();\n return Array.from(this.links.values());\n }\n\n async get(orgId: string): Promise<CloudSyncLink | null> {\n await this.load();\n return this.links.get(orgId) ?? null;\n }\n}\n\nexport const cloudSyncStore = new CloudSyncStore();\n","import { randomUUID } from 'node:crypto';\nimport * as Y from 'yjs';\nimport { projectStore } from './project-store.js';\nimport { serviceStore } from './service-store.js';\nimport { environmentStore } from './environment-store.js';\nimport { cloudSyncStore, type CloudSyncLink } from './cloud-sync-store.js';\nimport { cloudSessionStore } from './cloud-session-store.js';\nimport { getCollection, readEntity, writeEntity } from '@runeya/packages-shared';\n\n/**\n * Continuous, bidirectional synchronization between this local server and the\n * cloud, for every organization this server is linked to.\n *\n * Scope follows the hierarchy — org → project → services/environments — and\n * mirrors what git already shares: each entity's *on-disk* form, whatever\n * fields it happens to carry. Runtime-only state (a project's active\n * environment, a service's resolved env) is not persisted, so it is not synced\n * either; no allowlist decides this, \"is it on disk?\" does.\n *\n * Local-first is preserved: the `.runeya` JSON files stay the source of truth.\n * A per-org `Y.Doc` (CRDT) mirrors them and is relayed through the cloud over an\n * HTTP + SSE transport, so concurrent edits from different members merge instead\n * of overwriting each other.\n *\n * Loop prevention relies on Yjs transaction origins:\n * - local mutation → reconcile into doc under origin `local-bridge` → the\n * resulting incremental update is POSTed to the cloud.\n * - remote update → applied to the doc under origin `remote` → the observer\n * writes it back into the stores.\n * The stores then save and notify, which re-enters reconciliation — harmless\n * only because every write here is diff-guarded down to the field.\n */\n\nconst LOCAL_ORIGIN = 'local-bridge';\nconst REMOTE_ORIGIN = 'remote';\nconst RECONNECT_DELAY_MS = 3_000;\n\n/**\n * How long to wait before retrying once the cloud rejected our session.\n *\n * A rejection usually needs a human (sign in again), so retrying on the normal\n * 3s cadence would just spam the logs forever. But it is not always terminal —\n * a cloud-side bug or a deploy rejects perfectly good sessions too, and those\n * heal on their own. Retrying slowly keeps the sync self-healing without the\n * noise; a fresh sign-in still resumes immediately via `resumeAll()`.\n */\nconst UNAUTHENTICATED_RETRY_MS = 5 * 60_000;\n\ntype CollectionName = 'projects' | 'services' | 'environments';\nconst COLLECTIONS: CollectionName[] = ['projects', 'services', 'environments'];\n\n/** What the sync of one organization is currently doing, for the UI. */\nexport type SyncState = 'connecting' | 'live' | 'unauthenticated' | 'stopped';\n\n/** The cloud rejected our session (expired, signed out, or membership revoked). */\nclass SyncAuthError extends Error {\n constructor(status: number) {\n super(`cloud rejected the session (HTTP ${status})`);\n }\n}\n\n/** One live sync connection for a single organization. */\nclass OrgSyncConnection {\n private readonly doc = new Y.Doc();\n private readonly projects = getCollection(this.doc, 'projects');\n private readonly services = getCollection(this.doc, 'services');\n private readonly environments = getCollection(this.doc, 'environments');\n private readonly conn = randomUUID();\n private readonly link: CloudSyncLink;\n private stopped = false;\n private initializing = true;\n private abort: AbortController | null = null;\n private state: SyncState = 'connecting';\n /** Local state still owed to the cloud (initial sync, or a rejected episode). */\n private needsPush = false;\n private readonly unsubscribes: (() => void)[] = [];\n private readonly onSaved = () => void this.reconcileLocalToDoc();\n\n constructor(link: CloudSyncLink) {\n this.link = link;\n }\n\n private collection(name: CollectionName): Y.Map<unknown> {\n return this[name];\n }\n\n getState(): SyncState {\n return this.state;\n }\n\n getLink(): CloudSyncLink {\n return this.link;\n }\n\n async start(): Promise<void> {\n // Outbound: relay local-origin doc updates to the cloud (skipped while the\n // initial full push is being assembled).\n this.doc.on('update', (update: Uint8Array, origin: unknown) => {\n if (this.stopped || this.initializing) return;\n if (origin === LOCAL_ORIGIN) void this.pushUpdate(update);\n });\n\n // Inbound: apply remote-origin doc changes back into the local stores.\n for (const name of COLLECTIONS) {\n this.collection(name).observeDeep((events, txn) => {\n if (txn.origin !== REMOTE_ORIGIN) return;\n void this.applyDocEventsToStore(name, events);\n });\n }\n\n projectStore.events.on('saved', this.onSaved);\n this.unsubscribes.push(serviceStore.onChange(this.onSaved));\n this.unsubscribes.push(environmentStore.onChange(this.onSaved));\n\n // Seed the doc with current local state; the loop then pushes whatever the\n // cloud is missing and goes live. A rejected session does not abort the\n // start — the loop retries slowly and recovers on its own.\n await this.reconcileLocalToDoc();\n this.initializing = false;\n this.needsPush = true;\n void this.streamLoop();\n }\n\n stop(): void {\n this.stopped = true;\n this.state = 'stopped';\n projectStore.events.off('saved', this.onSaved);\n for (const off of this.unsubscribes.splice(0)) off();\n this.abort?.abort();\n this.doc.destroy();\n }\n\n // ---- Transport -------------------------------------------------------\n\n /**\n * Read the cloud session token fresh on every request, so signing back in\n * resumes sync without a restart. Throws when signed out, which the callers\n * treat as terminal exactly like a rejection from the cloud.\n */\n private async authHeader(): Promise<string> {\n const token = await cloudSessionStore.getToken();\n if (!token) throw new SyncAuthError(401);\n return `Bearer ${token}`;\n }\n\n private async headers(): Promise<Record<string, string>> {\n return { Authorization: await this.authHeader(), 'Content-Type': 'application/json' };\n }\n\n /**\n * Mark this org as needing a fresh sign-in. Logged once per episode, not on\n * every slow retry: the point of retrying is to recover quietly.\n */\n private markUnauthenticated(err: SyncAuthError): void {\n const alreadyReported = this.state === 'unauthenticated';\n this.state = 'unauthenticated';\n // Anything local was written while we were rejected: push it again once the\n // session works, or those changes would never reach the cloud.\n this.needsPush = true;\n if (alreadyReported) return;\n console.error(\n `[cloud-sync] org ${this.link.orgId}: ${err.message} — sync paused; retrying every`\n + ` ${UNAUTHENTICATED_RETRY_MS / 60_000} min, or immediately when you sign in to the cloud again.`,\n );\n }\n\n /** Sleep that gives up as soon as the connection is stopped. */\n private async delay(ms: number): Promise<void> {\n const step = 250;\n for (let waited = 0; waited < ms && !this.stopped; waited += step) {\n await new Promise((r) => setTimeout(r, Math.min(step, ms - waited)));\n }\n }\n\n private url(path: string): string {\n return `${this.link.cloudUrl.replace(/\\/$/, '')}/api/sync/${encodeURIComponent(this.link.orgId)}${path}`;\n }\n\n private async initialPush(): Promise<void> {\n try {\n const svRes = await fetch(this.url('/state-vector'), {\n headers: await this.headers(),\n signal: AbortSignal.timeout(15_000),\n });\n if (svRes.status === 401 || svRes.status === 403) throw new SyncAuthError(svRes.status);\n if (!svRes.ok) return;\n const { sv } = (await svRes.json()) as { sv: string };\n const cloudSv = new Uint8Array(Buffer.from(sv, 'base64'));\n const diff = Y.encodeStateAsUpdate(this.doc, cloudSv);\n await this.pushUpdate(diff);\n } catch (err) {\n if (err instanceof SyncAuthError) throw err;\n console.error('[cloud-sync] initial push failed for org %s:', this.link.orgId, (err as Error).message);\n }\n }\n\n private async pushUpdate(update: Uint8Array): Promise<void> {\n try {\n const res = await fetch(this.url('/update'), {\n method: 'POST',\n headers: await this.headers(),\n body: JSON.stringify({ update: Buffer.from(update).toString('base64'), conn: this.conn }),\n signal: AbortSignal.timeout(15_000),\n });\n if (res.status === 401 || res.status === 403) throw new SyncAuthError(res.status);\n } catch (err) {\n if (err instanceof SyncAuthError) {\n this.markUnauthenticated(err);\n this.abort?.abort();\n return;\n }\n if (!this.stopped) console.error('[cloud-sync] push failed for org %s:', this.link.orgId, (err as Error).message);\n }\n }\n\n /**\n * Long-lived SSE connection; reconnects on drop, and backs off to a slow\n * cadence while the cloud is rejecting our session.\n */\n private async streamLoop(): Promise<void> {\n while (!this.stopped) {\n try {\n // Catches up whatever changed locally while we were disconnected.\n if (this.needsPush) {\n await this.initialPush();\n this.needsPush = false;\n }\n this.state = 'connecting';\n await this.streamOnce();\n } catch (err) {\n if (err instanceof SyncAuthError) {\n this.markUnauthenticated(err);\n await this.delay(UNAUTHENTICATED_RETRY_MS);\n continue;\n }\n if (!this.stopped) console.error('[cloud-sync] stream error for org %s:', this.link.orgId, (err as Error).message);\n }\n await this.delay(RECONNECT_DELAY_MS);\n }\n }\n\n private async streamOnce(): Promise<void> {\n this.abort = new AbortController();\n const since = Buffer.from(Y.encodeStateVector(this.doc)).toString('base64');\n const res = await fetch(this.url(`/stream?conn=${this.conn}&since=${encodeURIComponent(since)}`), {\n headers: { Authorization: await this.authHeader() },\n signal: this.abort.signal,\n });\n if (res.status === 401 || res.status === 403) throw new SyncAuthError(res.status);\n if (!res.ok || !res.body) throw new Error(`stream HTTP ${res.status}`);\n this.state = 'live';\n\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n for (;;) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const frames = buffer.split('\\n\\n');\n buffer = frames.pop() ?? '';\n for (const frame of frames) {\n const line = frame.split('\\n').find((l) => l.startsWith('data: '));\n if (!line) continue;\n try {\n const payload = JSON.parse(line.slice(6)) as { type: string; update: string };\n const update = new Uint8Array(Buffer.from(payload.update, 'base64'));\n Y.applyUpdate(this.doc, update, REMOTE_ORIGIN);\n } catch {\n // Ignore malformed frames (comments/pings never carry `data:`).\n }\n }\n }\n }\n\n // ---- Local ↔ Doc reconciliation --------------------------------------\n\n private async applyDocEventsToStore(\n name: CollectionName,\n events: Y.YEvent<Y.AbstractType<unknown>>[],\n ): Promise<void> {\n const collection = this.collection(name);\n const deleted = new Set<string>();\n const affected = new Set<string>();\n for (const event of events) {\n if (event.target === collection) {\n for (const [key, change] of event.changes.keys) {\n if (change.action === 'delete') deleted.add(key);\n else affected.add(key);\n }\n } else {\n // A nested change (a field, an array element): the entity is the first\n // path segment.\n const topKey = event.path[0];\n if (typeof topKey === 'string') affected.add(topKey);\n }\n }\n\n for (const id of deleted) await this.deleteLocally(name, id);\n for (const id of affected) {\n if (deleted.has(id)) continue;\n const fields = readEntity(collection, id);\n if (!fields) continue;\n await this.upsertLocally(name, id, fields);\n }\n }\n\n private async upsertLocally(name: CollectionName, id: string, fields: unknown): Promise<void> {\n if (name === 'services') {\n await serviceStore.applyRemoteUpsert(id, fields);\n return;\n }\n if (name === 'environments') {\n await environmentStore.applyRemoteUpsert(id, fields);\n return;\n }\n const result = await projectStore.applyRemoteUpsert(id, fields);\n // A project created from a remote peer has no local environment yet;\n // bootstrap a default immutable \"local\" env so the UI is usable. Its own\n // environments may still be in flight, hence the check inside.\n if (result?.created) await this.bootstrapEnvironment(id);\n }\n\n private async deleteLocally(name: CollectionName, id: string): Promise<void> {\n if (name === 'services') await serviceStore.applyRemoteDelete(id);\n else if (name === 'environments') await environmentStore.applyRemoteDelete(id);\n else await projectStore.applyRemoteDelete(id);\n }\n\n private async bootstrapEnvironment(projectId: string): Promise<void> {\n try {\n const existing = await environmentStore.getByProjectId(projectId).catch(() => []);\n if (existing.length > 0) return;\n const localEnv = await environmentStore.create({\n projectId,\n name: 'local',\n description: 'Default local environment (immutable)',\n parentIds: [],\n immutable: true,\n });\n await projectStore.addEnvironment(projectId, localEnv.id);\n } catch (err) {\n console.error('[cloud-sync] env bootstrap failed for project %s:', projectId, (err as Error).message);\n }\n }\n\n /**\n * Mirror the org's local on-disk state into the doc.\n *\n * Membership follows the hierarchy: the org's projects, then their services\n * and environments.\n *\n * Deliberately additive for projects: a project that vanished locally is NOT\n * removed from the doc. Deleting files on one machine — or simply not having\n * pulled a project — must never wipe it for the whole organization. Removing a\n * project from the org is an explicit, admin-only action taken on the cloud,\n * which reaches every member as a remote deletion.\n *\n * Services and environments are different: they are the *contents* of a\n * project, so dropping one locally is an edit to that project and does\n * propagate — otherwise a service could never be removed.\n */\n private async reconcileLocalToDoc(): Promise<void> {\n if (this.stopped) return;\n const projects = await projectStore.listDiskFormByOrg(this.link.orgId);\n const projectIds = projects.map((p) => p.id);\n const serviceIds = [...new Set(projects.flatMap((p) => p.serviceIds ?? []))];\n const [services, environments] = await Promise.all([\n serviceStore.listSanitizedByIds(serviceIds),\n environmentStore.listEncryptedByProjectIds(projectIds),\n ]);\n if (this.stopped) return;\n\n const local: Record<CollectionName, { id: string }[]> = { projects, services, environments };\n // Contents of projects this machine actually holds: anything belonging to a\n // project we never pulled is none of our business to delete.\n const ownedProjectIds = new Set(projectIds);\n\n this.doc.transact(() => {\n for (const name of COLLECTIONS) {\n const collection = this.collection(name);\n const entities = local[name];\n const ids = new Set(entities.map((e) => e.id));\n for (const entity of entities) writeEntity(collection, entity.id, entity);\n if (name === 'projects') continue;\n for (const id of Array.from(collection.keys())) {\n if (ids.has(id)) continue;\n if (this.belongsToOwnedProject(name, id, ownedProjectIds)) collection.delete(id);\n }\n }\n }, LOCAL_ORIGIN);\n }\n\n /**\n * Whether a doc entity belongs to a project this machine holds — i.e. whether\n * its absence locally is a real removal rather than a project we never pulled.\n */\n private belongsToOwnedProject(\n name: CollectionName,\n id: string,\n ownedProjectIds: Set<string>,\n ): boolean {\n const fields = readEntity(this.collection(name), id);\n if (!fields) return false;\n if (name === 'environments') {\n const projectId = fields['projectId'];\n return typeof projectId === 'string' && ownedProjectIds.has(projectId);\n }\n // A service belongs to whichever projects list it in `serviceIds`.\n const projects = this.collection('projects');\n for (const projectId of projects.keys()) {\n const project = readEntity(projects, projectId);\n const serviceIds = project?.['serviceIds'];\n if (!Array.isArray(serviceIds) || !serviceIds.includes(id)) continue;\n if (!ownedProjectIds.has(projectId)) return false; // still used elsewhere\n }\n return true;\n }\n}\n\n/** Manages one sync connection per linked organization for the whole server. */\nclass CloudSyncBridge {\n private connections = new Map<string, OrgSyncConnection>();\n private started = false;\n\n /** Start syncing every organization already linked on disk. */\n async start(): Promise<void> {\n if (this.started) return;\n this.started = true;\n let links: CloudSyncLink[] = [];\n try {\n links = await cloudSyncStore.list();\n } catch (err) {\n console.error('[cloud-sync] could not load links:', (err as Error).message);\n return;\n }\n for (const link of links) await this.connect(link);\n if (links.length > 0) console.log(`[cloud-sync] syncing ${links.length} organization(s)`);\n }\n\n /**\n * Reconnect every link whose session had been rejected. Called after a cloud\n * sign-in, so sync resumes without restarting the server.\n */\n async resumeAll(): Promise<void> {\n const paused = Array.from(this.connections.values())\n .filter((c) => c.getState() === 'unauthenticated')\n .map((c) => c.getLink());\n for (const link of paused) await this.connect(link);\n }\n\n /** Per-org sync state, for the UI. */\n states(): { orgId: string; state: SyncState }[] {\n return Array.from(this.connections.entries()).map(([orgId, conn]) => ({ orgId, state: conn.getState() }));\n }\n\n /** Begin (or restart) syncing a single organization. */\n async connect(link: CloudSyncLink): Promise<void> {\n this.disconnect(link.orgId);\n const conn = new OrgSyncConnection(link);\n this.connections.set(link.orgId, conn);\n try {\n await conn.start();\n } catch (err) {\n console.error('[cloud-sync] failed to start org %s:', link.orgId, (err as Error).message);\n }\n }\n\n disconnect(orgId: string): void {\n const existing = this.connections.get(orgId);\n if (existing) {\n existing.stop();\n this.connections.delete(orgId);\n }\n }\n\n stopAll(): void {\n for (const conn of this.connections.values()) conn.stop();\n this.connections.clear();\n }\n}\n\nexport const cloudSyncBridge = new CloudSyncBridge();\n","import { randomBytes, createCipheriv, createDecipheriv } from 'node:crypto';\nimport { readFile, writeFile, chmod, stat, rename } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { Entry } from '@napi-rs/keyring';\nimport { hashRaw as argon2HashRaw } from '@node-rs/argon2';\n\nconst KEYRING_SERVICE = 'runeya';\nconst KEYRING_ACCOUNT = 'pepper';\nconst VERIFY_FILENAME = '.runeya-verify';\nconst ENCRYPTED_KEY_FILENAME = '.encryption.key.enc';\nconst PEPPER_FILENAME = '.pepper.private';\nconst CANARY_PLAINTEXT = 'runeya:v1:key-verification';\nconst MAX_KEY_FILE_SIZE = 1024; // 1 KB\nconst ARGON2_OPTIONS = { memoryCost: 65536, timeCost: 3, parallelism: 4, outputLen: 32 };\n\n// Helper: validate file size before reading\nasync function readKeyFile(filePath: string): Promise<Buffer> {\n const s = await stat(filePath);\n if (s.size > MAX_KEY_FILE_SIZE) throw new Error(`Fichier suspect : ${filePath} (${s.size} octets)`);\n return readFile(filePath);\n}\n\n// AES-256-GCM encrypt\nfunction aesEncrypt(key: Buffer, plaintext: Buffer): Buffer {\n const iv = randomBytes(12);\n const cipher = createCipheriv('aes-256-gcm', key, iv);\n const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()]);\n const authTag = cipher.getAuthTag();\n return Buffer.concat([iv, authTag, encrypted]); // 12 + 16 + N bytes\n}\n\n// AES-256-GCM decrypt — throws if authTag invalid\nfunction aesDecrypt(key: Buffer, data: Buffer): Buffer {\n const iv = data.subarray(0, 12);\n const authTag = data.subarray(12, 28);\n const ciphertext = data.subarray(28);\n const decipher = createDecipheriv('aes-256-gcm', key, iv, { authTagLength: 16 });\n decipher.setAuthTag(authTag);\n return Buffer.concat([decipher.update(ciphertext), decipher.final()]);\n}\n\n// Fallback: store pepper as a file in dataDir (chmod 600)\nasync function getPepperFromFile(dataDir: string): Promise<Buffer | null> {\n try {\n const raw = await readKeyFile(join(dataDir, PEPPER_FILENAME));\n const hex = raw.toString('utf-8').trim();\n if (/^[0-9a-f]{64}$/i.test(hex)) return Buffer.from(hex, 'hex');\n } catch { /* not found */ }\n return null;\n}\n\nasync function writePepperToFile(dataDir: string, pepper: Buffer): Promise<void> {\n const filePath = join(dataDir, PEPPER_FILENAME);\n const tmpPath = filePath + '.tmp';\n await writeFile(tmpPath, pepper.toString('hex'), 'utf-8');\n await chmod(tmpPath, 0o600);\n await rename(tmpPath, filePath);\n}\n\nfunction tryKeyringGet(): string | null {\n try { return new Entry(KEYRING_SERVICE, KEYRING_ACCOUNT).getPassword(); } catch { return null; }\n}\n\nfunction tryKeyringSet(value: string): boolean {\n try { new Entry(KEYRING_SERVICE, KEYRING_ACCOUNT).setPassword(value); return true; } catch { return false; }\n}\n\n// Get or generate pepper — keyring first, file fallback\nasync function getOrCreatePepper(dataDir: string): Promise<Buffer> {\n // Try keyring read\n const pepperHex = tryKeyringGet();\n if (pepperHex && /^[0-9a-f]{64}$/i.test(pepperHex)) {\n return Buffer.from(pepperHex, 'hex');\n }\n // Keyring failed or empty — try file fallback\n const filePepper = await getPepperFromFile(dataDir);\n if (filePepper) return filePepper;\n // Generate new pepper, persist in keyring if possible, else file\n const pepper = randomBytes(32);\n const saved = tryKeyringSet(pepper.toString('hex'));\n if (!saved) {\n console.warn('[master-password] Keyring unavailable, storing pepper in dataDir (fallback)');\n await writePepperToFile(dataDir, pepper);\n }\n return pepper;\n}\n\n// Derive key from master password + pepper using Argon2id\n// Returns 32-byte derived key (never stored)\nasync function deriveKey(masterPassword: string, pepper: Buffer, salt: Buffer): Promise<Buffer> {\n const combined = masterPassword + pepper.toString('hex');\n const derived = await argon2HashRaw(combined, {\n ...ARGON2_OPTIONS,\n salt,\n });\n return Buffer.from(derived);\n}\n\n// Encrypt encryption key and write to .encryption.key.enc\n// Format: base64(salt_16 + iv_12 + authTag_16 + ciphertext_32)\nexport async function writeEncryptedKey(dataDir: string, masterPassword: string, encryptionKey: Buffer): Promise<void> {\n const pepper = await getOrCreatePepper(dataDir);\n const salt = randomBytes(16);\n const derivedKey = await deriveKey(masterPassword, pepper, salt);\n const payload = aesEncrypt(derivedKey, encryptionKey); // iv(12) + authTag(16) + ciphertext(32)\n const fileContent = Buffer.concat([salt, payload]);\n const encoded = fileContent.toString('base64');\n const filePath = join(dataDir, ENCRYPTED_KEY_FILENAME);\n const tmpPath = filePath + '.tmp';\n await writeFile(tmpPath, encoded, 'utf-8');\n await chmod(tmpPath, 0o600);\n await rename(tmpPath, filePath);\n}\n\n// Read and decrypt .encryption.key.enc — throws on wrong password\nexport async function readEncryptedKey(dataDir: string, masterPassword: string): Promise<Buffer> {\n const filePath = join(dataDir, ENCRYPTED_KEY_FILENAME);\n const raw = await readKeyFile(filePath);\n const fileContent = Buffer.from(raw.toString('utf-8').trim(), 'base64');\n const salt = fileContent.subarray(0, 16);\n const payload = fileContent.subarray(16); // iv(12) + authTag(16) + ciphertext(32)\n const pepper = await getPepperFromKeychain(dataDir);\n const derivedKey = await deriveKey(masterPassword, pepper, salt);\n // throws if authTag invalid → wrong password\n return aesDecrypt(derivedKey, payload);\n}\n\n// Get pepper from keychain, file fallback (must exist — throws if not found anywhere)\nasync function getPepperFromKeychain(dataDir: string): Promise<Buffer> {\n const pepperHex = tryKeyringGet();\n if (pepperHex && /^[0-9a-f]{64}$/i.test(pepperHex)) {\n return Buffer.from(pepperHex, 'hex');\n }\n // Fallback to file\n const filePepper = await getPepperFromFile(dataDir);\n if (filePepper) return filePepper;\n throw new Error('Pepper introuvable (keyring et fichier). Re-setup requis.');\n}\n\n// Write canary file .runeya-verify\nexport async function writeVerifyFile(dataDir: string, encryptionKey: Buffer): Promise<void> {\n const payload = aesEncrypt(encryptionKey, Buffer.from(CANARY_PLAINTEXT, 'utf-8'));\n const filePath = join(dataDir, VERIFY_FILENAME);\n const tmpPath = filePath + '.tmp';\n await writeFile(tmpPath, payload.toString('base64'), 'utf-8');\n await rename(tmpPath, filePath);\n}\n\n// Verify encryption key against .runeya-verify — throws if wrong key\nexport async function verifyEncryptionKey(dataDir: string, encryptionKey: Buffer): Promise<void> {\n const filePath = join(dataDir, VERIFY_FILENAME);\n const raw = await readKeyFile(filePath);\n if (!matchesCanary(raw.toString('utf-8'), encryptionKey)) {\n throw new Error('Clé d\\'encryption incorrecte');\n }\n}\n\n/**\n * Whether a canary was produced by this key.\n *\n * Canaries cannot be compared to each other: `aesEncrypt` uses a random IV, so\n * the same key yields a different canary every time. The only test is to\n * decrypt — which is also why holding a canary reveals nothing about the key.\n *\n * Takes the canary value rather than a path, so the same check works on the\n * local `.runeya-verify` and on the one an organization publishes to the cloud.\n */\nexport function matchesCanary(canaryBase64: string, encryptionKey: Buffer): boolean {\n try {\n const payload = Buffer.from(canaryBase64.trim(), 'base64');\n return aesDecrypt(encryptionKey, payload).toString('utf-8') === CANARY_PLAINTEXT;\n } catch {\n // Wrong key => GCM auth failure. Indistinguishable from a corrupt canary,\n // and both mean the same thing here: this key does not open it.\n return false;\n }\n}\n\n/** This machine's canary, or null when setup has not written one yet. */\nexport async function readVerifyFile(dataDir: string): Promise<string | null> {\n try {\n return (await readKeyFile(join(dataDir, VERIFY_FILENAME))).toString('utf-8').trim();\n } catch {\n return null;\n }\n}\n\n// Check if .runeya-verify exists\nexport async function hasVerifyFile(dataDir: string): Promise<boolean> {\n try {\n await stat(join(dataDir, VERIFY_FILENAME));\n return true;\n } catch {\n return false;\n }\n}\n\n// Check if .encryption.key.enc exists\nexport async function hasEncryptedKeyFile(dataDir: string): Promise<boolean> {\n try {\n await stat(join(dataDir, ENCRYPTED_KEY_FILENAME));\n return true;\n } catch {\n return false;\n }\n}\n\n","import { router } from './trpc.js';\nimport { healthRouter } from './routers/health.js';\nimport { projectRouter } from './routers/project.js';\nimport { serviceRouter } from './routers/service.js';\nimport { agentRouter } from './routers/agent.js';\nimport { processRouter } from './routers/process.js';\nimport { auditRouter } from './routers/audit.js';\nimport { setupRouter } from './routers/setup.js';\nimport { environmentRouter } from './routers/environment.js';\nimport { settingsRouter } from './routers/settings.js';\nimport { editorRouter } from './routers/editor.js';\nimport { apiKeysRouter } from './routers/api-keys.js';\nimport { chatRouter } from './routers/chat.js';\nimport { gitRouter } from './routers/git.js';\nimport { scenarioRouter } from './routers/scenario.js';\nimport { debugRouter } from './routers/debug.js';\nimport { kanbanQueueRouter } from './routers/kanban-queue.js';\nimport { kanbanRouter } from './routers/kanban.js';\nimport { terminalRouter } from './routers/terminal.js';\nimport { utilityRouter } from './routers/utility.js';\nimport { wikiRouter } from './routers/wiki.js';\nimport { configRouter } from './routers/config.js';\nimport { cloudSyncRouter } from './routers/cloud-sync.js';\nimport { cloudAuthRouter } from './routers/cloud-auth.js';\n\n// Re-export server types used in AppRouter so consumers can name them (avoids TS4023)\nexport type { AuditEntry } from '../services/audit-service.js';\nexport type { CliUsageEntry } from '../services/claude-usage.js';\nexport type { Conversation } from '../services/conversation-store.js';\nexport type { KanbanQueueItem, KanbanQueueState } from '../services/kanban-queue.js';\nexport type { PersistedRunState, RunState } from '../services/scenario-run-store.js';\n\nexport const appRouter = router({\n health: healthRouter,\n project: projectRouter,\n service: serviceRouter,\n agent: agentRouter,\n process: processRouter,\n audit: auditRouter,\n setup: setupRouter,\n environment: environmentRouter,\n settings: settingsRouter,\n editor: editorRouter,\n apiKeys: apiKeysRouter,\n chat: chatRouter,\n scenario: scenarioRouter,\n git: gitRouter,\n debug: debugRouter,\n kanbanQueue: kanbanQueueRouter,\n kanban: kanbanRouter,\n terminal: terminalRouter,\n utility: utilityRouter,\n wiki: wikiRouter,\n config: configRouter,\n cloudSync: cloudSyncRouter,\n cloudAuth: cloudAuthRouter,\n});\n\nexport type AppRouter = typeof appRouter;\n","import { Request, Response, NextFunction } from 'express';\n\nexport function errorHandler(err: Error, _req: Request, res: Response, _next: NextFunction): void {\n console.error('[server] Unhandled error:', err);\n res.status(500).json({ error: 'Internal server error' });\n}\n","import { settingsManager } from './settings-manager.js';\n\n\ninterface Migration {\n version: number;\n name: string;\n up: () => Promise<void>;\n}\n\n// Migrations are registered here. Each adds a transform function.\nconst migrations: Migration[] = [\n];\n\nclass MigrationEngine {\n async run(): Promise<void> {\n const schemaVersion = await settingsManager.getSchemaVersion();\n const currentVersion = schemaVersion.version;\n const targetVersion = settingsManager.getCurrentSchemaVersion();\n\n if (currentVersion >= targetVersion) {\n console.log(`[migration] Schema is up to date (v${currentVersion})`);\n return;\n }\n\n console.log(`[migration] Migrating from v${currentVersion} to v${targetVersion}`);\n const pending = migrations.filter(m => m.version > currentVersion && m.version <= targetVersion);\n pending.sort((a, b) => a.version - b.version);\n\n for (const migration of pending) {\n console.log(`[migration] Running: ${migration.name} (v${migration.version})`);\n await migration.up();\n await settingsManager.saveSchemaVersion({ version: migration.version, migratedAt: new Date() });\n console.log(`[migration] Done: ${migration.name}`);\n }\n\n console.log(`[migration] All migrations complete. Now at v${targetVersion}`);\n }\n}\n\nexport const migrationEngine = new MigrationEngine();\n","import { chmod, stat } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { env } from '../config/env.js';\n\nconst SENSITIVE_FILES = [\n 'agents.json',\n 'settings.json',\n 'services.json',\n 'projects.json',\n 'deployments.json',\n 'schema-version.json',\n];\n\nconst SECURE_MODE = 0o600;\n\n/**\n * Ensure all sensitive data files have restrictive permissions (0600).\n * Logs warnings for files with overly permissive modes and auto-fixes them.\n */\nexport async function ensureFilePermissions(): Promise<void> {\n for (const filename of SENSITIVE_FILES) {\n const filepath = join(env.DATA_DIR, filename);\n try {\n const stats = await stat(filepath);\n const mode = stats.mode & 0o777;\n if (mode !== SECURE_MODE) {\n console.warn('[security] File', filename, 'has mode', mode.toString(8) + ', fixing to 600');\n await chmod(filepath, SECURE_MODE);\n }\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n console.warn('[security] Cannot check permissions for', filename + ':', err instanceof Error ? err.message : String(err));\n }\n // ENOENT is fine — file doesn't exist yet\n }\n }\n}\n","import { writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nconst GITIGNORE_CONTENT = `\n#################\n# Do not edit this file #\n#################\n\n\n# Encryption key (contains secrets — never commit)\n.encryption.key\n.encryption.key.enc\n\n\n# Key verification canary — MUST be committed so new team members can validate their encryption key\n!.runeya-verify\n\n# This machine's cloud session token (encrypted, and specific to this install)\ncloud-session.json\n\n# Backup in local only\nbackup-*\n\n# Per-user environment overrides (never commit — each dev has their own)\nenvironment-overrides.json\n\n# Private user data (conversations, personal state — never commit)\n*.private\n*.private.json*\nconversations/\nconversations.private.json\n\n\n\n# Runtime logs\n*.log\n*.log.*\n`;\n\n/**\n * Writes data/.gitignore on every startup to keep it in sync with the codebase.\n */\nexport async function ensureDataGitignore(dataDir: string): Promise<void> {\n const gitignorePath = join(dataDir, '.gitignore');\n await writeFile(gitignorePath, GITIGNORE_CONTENT, 'utf-8');\n}\n","/**\n * Legacy Runeya → Runeya migration\n *\n * Triggered automatically when DATA_DIR/.runeya/dbs/encryption-key.json is found.\n * Must run BEFORE any store initialisation (called at the top of createLocalServer).\n *\n * Steps:\n * 1. Backup existing DATA_DIR contents\n * 2. Extract legacy libsodium key → load in memory for re-encryption\n * 3. Decrypt all .encrypted.json files with libsodium crypto_secretbox\n * 4. Map legacy structures → Runeya JSON files\n * 5. Clear singleton, store key in pending holder → server enters setup state\n * 6. Rename .runeya → backup to prevent re-running\n */\n\nimport { createRequire } from 'module';\nimport { randomBytes, createCipheriv, createDecipheriv } from 'node:crypto';\nimport { randomUUID } from 'node:crypto';\nimport {\n readFile, writeFile, rename, mkdir, access, readdir,\n} from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { setEncryptionKey, getEncryptionKey, clearEncryptionKey, setPendingLegacyKey } from '../utils/encryption-key.js';\nimport type { Variable } from '@runeya/packages-shared';\nimport { env } from '../config/env.js';\n\n// CJS interop for libsodium-wrappers\nconst _require = createRequire(import.meta.url);\n\n/** Minimal type for the libsodium-wrappers API used in this migration */\ninterface Sodium {\n ready: Promise<void>;\n crypto_secretbox_NONCEBYTES: number;\n crypto_secretbox_open_easy(ciphertext: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array;\n from_base64(input: string): Uint8Array;\n}\n\n// Parser ID remapping\nconst PARSER_ID_MAP: Record<string, string> = {\n 'stack-monitor-parser-jsons': 'native:json',\n 'stack-monitor-parser-debug': 'native:debug',\n 'stack-monitor-parser-links': 'native:links',\n 'runeya-parser-jsons': 'native:json',\n 'runeya-parser-debug': 'native:debug',\n 'runeya-parser-links': 'native:links',\n};\n\n// ── Runeya AES-256-GCM encryption (matches service-store / environment-store) ──\n\nfunction encryptValue(plaintext: string): string {\n const key = getEncryptionKey();\n if (!key) throw new Error('[legacy-migration] Encryption key not loaded');\n const iv = randomBytes(16);\n const cipher = createCipheriv('aes-256-gcm', key, iv);\n let enc = cipher.update(plaintext, 'utf-8', 'hex');\n enc += cipher.final('hex');\n const authTag = cipher.getAuthTag().toString('hex');\n return `${iv.toString('hex')}:${authTag}:${enc}`;\n}\n\n/** Strip legacy suffixes from a variable key: _RUNEYA_OVERRIDE → _RUNEYA → base */\nfunction cleanVarKey(key: string): string {\n return key.replace(/_RUNEYA(?:_OVERRIDE)?$|_OVERRIDE$/, '');\n}\n\n/** Valid interpolation token: {{VAR_NAME}} or {{environment.VAR_NAME}} — simple identifiers only, no expressions */\nconst VALID_INTERP_RE = /^\\{\\{(?:environment\\.)?[A-Z_][A-Z0-9_]*\\}\\}$/i;\n\n/** Detect interpolation patterns like ${VAR}, $VAR, {{VAR}} */\nfunction hasInterpolation(value: string): boolean {\n return /\\$\\{[^}]+\\}|\\$[A-Z_][A-Z0-9_]*|\\{\\{[^}]+\\}\\}/.test(value);\n}\n\n/** Returns true only for simple variable references — rejects expressions, ternaries, nested accessors */\nfunction isValidInterpolation(token: string): boolean {\n return VALID_INTERP_RE.test(token.trim());\n}\n\n/** Returns true if the value contains any {{...}} token that is not a valid variable reference */\nfunction hasInvalidInterpolation(value: string): boolean {\n const tokens = value.matchAll(/\\{\\{[^}]+\\}\\}/g);\n for (const match of tokens) {\n if (!isValidInterpolation(match[0])) return true;\n }\n return false;\n}\n\n/**\n * Rewrite legacy {{KEY}} interpolation to Runeya's {{environment.KEY}} format.\n * Strips legacy suffixes (_RUNEYA, _OVERRIDE, _RUNEYA_OVERRIDE).\n * Leaves ${VAR} and $VAR patterns untouched (shell interpolation, handled at runtime).\n */\nfunction rewriteInterpolation(value: string): string {\n return value.replace(/\\{\\{(?!environment\\.)([^}]+)\\}\\}/g, (match, key: string) => {\n // Only rewrite simple variable references — leave expressions untouched (will be encrypted)\n if (!isValidInterpolation(match)) return match;\n return `{{environment.${cleanVarKey(key)}}}`;\n });\n}\n\n/**\n * Detect composite interpolation: a value that contains exactly one {{VAR}} token\n * with surrounding text (e.g. \"{{DATABASE_URL}}/onboarding?authSource=admin\").\n * Returns { pre, interp, post } if composite, null otherwise.\n * Values with multiple {{...}} tokens or $VAR/${{VAR}} patterns are left untouched.\n */\nfunction splitCompositeInterpolation(value: string): { pre: string; interp: string; post: string } | null {\n const tokens = [...value.matchAll(/\\{\\{[^}]+\\}\\}/g)];\n if (tokens.length !== 1) return null; // 0 or 2+ interpolations — skip\n if (/\\$\\{[^}]+\\}|\\$[A-Z_][A-Z0-9_]*/.test(value)) return null; // shell vars — skip\n const match = tokens[0];\n if (!isValidInterpolation(match[0])) return null; // expression/ternary — treat as literal\n const pre = value.slice(0, match.index);\n const post = value.slice((match.index ?? 0) + match[0].length);\n if (!pre && !post) return null; // pure interpolation — nothing to split\n return { pre, interp: match[0], post };\n}\n\n/** Decrypt a migration-encrypted value (same AES-256-GCM as encryptValue above) */\nfunction decryptMigrationValue(encrypted: string): string | null {\n try {\n const key = getEncryptionKey();\n if (!key) return null;\n const parts = encrypted.split(':');\n if (parts.length !== 3) return null;\n const [ivHex, authHex, ct] = parts;\n const dec = createDecipheriv('aes-256-gcm', key, Buffer.from(ivHex, 'hex'), { authTagLength: 16 });\n dec.setAuthTag(Buffer.from(authHex, 'hex'));\n return dec.update(ct, 'hex', 'utf-8') + dec.final('utf-8');\n } catch { return null; }\n}\n\n/**\n * Returns true if the override raw value is identical to the base variable's stored value.\n * Skips writing a redundant override when base and override resolve to the same thing.\n */\nfunction isSameAsBase(overrideRawValue: string, baseVar: Variable | undefined): boolean {\n if (!baseVar) return false;\n const baseSlot = baseVar.value;\n if (!baseSlot.isSecret) {\n return baseSlot.value === rewriteInterpolation(overrideRawValue);\n }\n const decrypted = decryptMigrationValue(baseSlot.value);\n return decrypted === overrideRawValue;\n}\n\n/** Build a Variable with key and value slot — encrypted if secret, plaintext (with rewritten interpolation) otherwise */\nfunction makeVariable(key: string, value: string, pre = '', post = ''): Variable {\n // Auto-detect composite interpolation and ventilate into pre/value/post\n const composite = splitCompositeInterpolation(value);\n if (composite) {\n return {\n key,\n value: {\n value: rewriteInterpolation(composite.interp),\n pre: rewriteInterpolation(pre + composite.pre),\n post: rewriteInterpolation(composite.post + post),\n isSecret: false,\n injectIntoAi: false,\n },\n };\n }\n\n const secret = !hasInterpolation(value);\n return {\n key,\n value: {\n value: secret ? encryptValue(value) : rewriteInterpolation(value),\n pre: rewriteInterpolation(pre),\n post: rewriteInterpolation(post),\n isSecret: secret,\n injectIntoAi: false,\n },\n };\n}\n\n// ── libsodium decryption ──────────────────────────────────────────────────────\n\nasync function getSodium(): Promise<Sodium> {\n const _sodium = _require('libsodium-wrappers') as Sodium;\n await _sodium.ready;\n return _sodium;\n}\n\nasync function decryptLegacyFile(\n filePath: string,\n key: Uint8Array,\n sodium: Sodium,\n): Promise<unknown> {\n const raw = (await readFile(filePath, 'utf-8')).trim();\n if (!raw || raw === '[]' || raw === '{}') {\n try { return JSON.parse(raw); } catch { return {}; }\n }\n\n const buf = Buffer.from(raw, 'base64');\n const nonce = buf.subarray(0, sodium.crypto_secretbox_NONCEBYTES as number);\n const ciphertext = buf.subarray(sodium.crypto_secretbox_NONCEBYTES as number);\n const decrypted = sodium.crypto_secretbox_open_easy(\n new Uint8Array(ciphertext),\n new Uint8Array(nonce),\n key,\n ) as Uint8Array;\n\n return JSON.parse(Buffer.from(decrypted).toString('utf-8'));\n}\n\n// ── Atomic write helper ───────────────────────────────────────────────────────\n\nasync function atomicWrite(path: string, data: unknown): Promise<void> {\n const tmp = path + '.tmp';\n await writeFile(tmp, JSON.stringify(data, null, 2), 'utf-8');\n await rename(tmp, path);\n}\n\n// ── Main migration entry point ────────────────────────────────────────────────\n\nexport async function runLegacyMigration(dataDir: string): Promise<boolean> {\n // Legacy .runeya sits in the working directory (apps/server/.runeya/)\n // We resolve dataDir to an absolute path to avoid false-positive overlap\n // oxlint-disable-next-line typescript/unbound-method -- resolve is a pure module function from node:path, not a class method\n const { resolve } = await import('node:path');\n const abCwd = resolve(process.cwd());\n const legacyRoot = join(abCwd, env.DATA_DIR);\n const legacyKeyPath = join(legacyRoot, 'dbs', 'encryption-key.json');\n\n // Detect legacy installation\n try {\n await access(legacyKeyPath);\n } catch {\n return false;\n }\n\n console.log('[legacy-migration] Legacy Runeya data detected, starting migration…');\n\n // ── 1. Move legacy .runeya → .runeya/backup-<date>, create fresh DATA_DIR ───\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-').substring(0, 19);\n const legacyTmp = join(abCwd, '.runeya-tmp');\n await rename(legacyRoot, legacyTmp); // free up the .runeya name\n await mkdir(dataDir, { recursive: true }); // create fresh .runeya/\n const legacyOld = join(dataDir, `backup-${timestamp}`);\n await rename(legacyTmp, legacyOld); // move into .runeya/backup-<date>\n console.log(`[legacy-migration] Legacy data backed up to ${legacyOld}`);\n\n // ── 2. Extract legacy key and initialise Runeya encryption ─────────────────\n const keyJson = JSON.parse(await readFile(join(legacyOld, 'dbs', 'encryption-key.json'), 'utf-8')) as { encryptionKey: string };\n const sodium = await getSodium();\n const sodiumKey = sodium.from_base64(keyJson.encryptionKey) as Uint8Array;\n\n // Load key into singleton temporarily — needed by encryptValue/makeVariable during re-encryption\n const keyBuffer = Buffer.from(sodiumKey);\n const runyeaKeyHex = keyBuffer.toString('hex');\n await setEncryptionKey(runyeaKeyHex);\n console.log('[legacy-migration] Encryption key loaded in memory (temporary)');\n\n // ── 3. Decrypt all legacy files ─────────────────────────────────────────────\n const dbsDir = join(legacyOld, 'dbs');\n\n async function readEncrypted(filePath: string): Promise<any> {\n try {\n return await decryptLegacyFile(filePath, sodiumKey, sodium);\n } catch (err: unknown) {\n console.warn(`[legacy-migration] Failed to decrypt ${filePath}: ${(err as Error).message}`);\n return null;\n }\n }\n\n // Environments\n const envsDir = join(dbsDir, 'envs');\n const envFiles = (await readdir(envsDir).catch(() => [] as string[]))\n .filter(f => f.endsWith('.encrypted.json'));\n\n const legacyEnvs: Record<string, any> = {};\n for (const file of envFiles) {\n const name = file.replace('.encrypted.json', '');\n legacyEnvs[name] = await readEncrypted(join(envsDir, file));\n }\n\n // Services\n const servicesDir = join(dbsDir, 'services');\n const serviceFiles = (await readdir(servicesDir).catch(() => [] as string[]))\n .filter(f => f.endsWith('.encrypted.json'));\n\n const legacyServices: Record<string, any> = {};\n for (const file of serviceFiles) {\n const name = file.replace('.encrypted.json', '');\n if (!name) continue; // skip empty default service\n const data = await readEncrypted(join(servicesDir, file));\n if (data?.label) legacyServices[name] = data;\n }\n\n // Overrides\n const overridesDir = join(dbsDir, 'overrides');\n const overrideFiles = (await readdir(overridesDir).catch(() => [] as string[]))\n .filter(f => f.endsWith('.encrypted.json'));\n\n const legacyServiceOverrides: Record<string, any> = {};\n const legacyEnvOverrides: Record<string, any> = {};\n\n for (const file of overrideFiles) {\n const baseName = file.replace('.encrypted.json', '');\n const data = await readEncrypted(join(overridesDir, file));\n if (!data) continue;\n\n if (baseName.endsWith('-envs')) {\n legacyServiceOverrides[baseName.slice(0, -5)] = data;\n } else if (baseName.endsWith('-environment')) {\n legacyEnvOverrides[baseName.slice(0, -12)] = data;\n }\n }\n\n // Custom parsers\n const parsersDir = join(dbsDir, 'parsers');\n const parserFiles = (await readdir(parsersDir).catch(() => [] as string[]))\n .filter(f => f.endsWith('.encrypted.json'));\n\n const legacyParsers: any[] = [];\n for (const file of parserFiles) {\n const data = await readEncrypted(join(parsersDir, file));\n if (data?.id) legacyParsers.push(data);\n }\n\n // ── 4. Build Runeya data structures ─────────────────────────────────────────\n\n // Projects\n const projectMonoId = randomUUID();\n\n // Environments — two-pass to resolve parentIds after all IDs are known\n // envIdMap keyed by filename (without extension) for ID lookup\n const envIdMap: Record<string, string> = {};\n // labelToKey maps label → filename key, for resolving extends references\n const labelToKey: Record<string, string> = {};\n for (const [name, legacyEnv] of Object.entries(legacyEnvs)) {\n envIdMap[name] = randomUUID();\n if (legacyEnv?.label) labelToKey[legacyEnv.label] = name;\n }\n\n const runeEnvs: any[] = [];\n const defaultEnvName = Object.entries(legacyEnvs).find(([, v]) => v?.default)?.[0];\n\n // Lookup map: `${envId}:${cleanedVarName}` → variableId (UUID)\n const varIdLookup = new Map<string, string>();\n\n for (const [name, legacyEnv] of Object.entries(legacyEnvs)) {\n if (!legacyEnv) continue;\n\n // Collect all variables inherited from parent envs (union, first-parent wins)\n const inheritedVars: Record<string, string> = {};\n for (const parentLabel of legacyEnv.extends || []) {\n const parentKey = labelToKey[parentLabel] ?? parentLabel;\n const parentEnv = legacyEnvs[parentKey];\n for (const [k, v] of Object.entries(parentEnv?.envs ?? {})) {\n if (typeof v === 'string') {\n const cleaned = cleanVarKey(k);\n if (!(cleaned in inheritedVars)) inheritedVars[cleaned] = v;\n }\n }\n }\n\n const variables: Record<string, Variable> = {};\n for (const [key, value] of Object.entries(legacyEnv.envs || {})) {\n if (typeof value === 'string') {\n if (hasInvalidInterpolation(value)) continue;\n const cleaned = cleanVarKey(key);\n // Skip if identical to inherited value — the child inherits it anyway\n if (inheritedVars[cleaned] === value) continue;\n const varId = randomUUID();\n variables[varId] = makeVariable(cleaned, value);\n varIdLookup.set(`${envIdMap[name]}:${cleaned}`, varId);\n }\n }\n\n runeEnvs.push({\n id: envIdMap[name],\n projectId: projectMonoId,\n name: legacyEnv.label || name,\n description: '',\n scope: 'global' as const,\n parentIds: (legacyEnv.extends || [])\n .map((p: string) => envIdMap[labelToKey[p] ?? p])\n .filter(Boolean),\n immutable: false,\n default: name === defaultEnvName,\n color: legacyEnv.bgColor || '#22c55e',\n variables,\n });\n }\n\n // Services\n const serviceIdMap: Record<string, string> = {};\n const runeServices: any[] = [];\n\n for (const [name, legacy] of Object.entries(legacyServices)) {\n const id = randomUUID();\n serviceIdMap[name] = id;\n\n // rootPath = legacy global working directory for this service\n const rootPath: string = legacy.rootPath || '';\n const rootPathCwd = rootPath && rootPath !== '.' ? rootPath : '';\n\n // Commands: spawnCmd + spawnArgs → single command string\n // Command cwd only set if the command has its own explicit cwd (not inherited from rootPath)\n const commands: any[] = [];\n for (const cmd of legacy.commands || []) {\n const parts = [cmd.spawnCmd, ...(cmd.spawnArgs || [])].filter(Boolean);\n if (!parts.length) continue;\n commands.push({\n id: cmd.id || randomUUID(),\n label: 'Launch',\n command: parts.join(' '),\n cwd: cmd.spawnOptions?.cwd || '',\n shell: false,\n });\n }\n\n // Parser IDs — deduplicated, remapped\n const effectiveParsers: any[] =\n legacy.commands?.[0]?.effectiveParsers\n ?? legacy.parsers\n ?? [];\n\n const parserIds: string[] = [];\n for (const parser of effectiveParsers) {\n const rawId: string = typeof parser === 'string' ? parser : (parser.id ?? '');\n const mapped = PARSER_ID_MAP[rawId] ?? rawId;\n if (mapped && !parserIds.includes(mapped)) {\n if (!PARSER_ID_MAP[rawId]) {\n console.warn(`[legacy-migration] Unknown parser \"${rawId}\" on service \"${name}\" — kept as-is`);\n }\n parserIds.push(mapped);\n }\n }\n\n // Health check — extract path from URL, rename returnCode → expectedStatus\n // Only migrate if explicitly enabled (or if enabled field absent, presence of URL implies intent)\n let healthCheck: any;\n if (legacy.health?.url && legacy.health?.enabled !== false) {\n try {\n const healthUrl = new URL(legacy.health.url);\n healthCheck = {\n path: healthUrl.pathname || '/',\n method: legacy.health.method || 'GET',\n ...(typeof legacy.health.interval === 'number' && { interval: legacy.health.interval }),\n expectedStatus: legacy.health.returnCode || 200,\n };\n } catch {\n // Invalid URL — skip health check\n }\n }\n\n // Docker config — map legacy container fields to DockerConfig\n // Legacy structure: container.build (Dockerfile content), container.bootstrap.commands,\n // container.volumes, container.ports, container.name, container.ignoreVolumes, etc.\n let dockerConfig: any;\n const container = legacy.container;\n if (container?.enabled) {\n dockerConfig = {\n volumes: container.volumes || [],\n ports: container.ports || [],\n networkMode: container.networkMode || 'host',\n };\n\n // Dockerfile — legacy uses \"build\" field (not \"dockerfile\")\n // buildContext defaults to \".\" (Docker needs a valid context for COPY/ADD)\n if (container.build) {\n dockerConfig.dockerfile = container.build;\n dockerConfig.buildContext = '.';\n }\n\n // Image (pull mode, mutually exclusive with Dockerfile in UI)\n // Legacy \"name\" field can serve as image if no explicit \"image\" field\n if (container.image) {\n dockerConfig.image = container.image;\n } else if (container.name && !container.build) {\n dockerConfig.image = container.name;\n }\n\n // Build args — legacy uses container.buildArgs (Record<string, string>)\n if (container.buildArgs && typeof container.buildArgs === 'object') {\n dockerConfig.buildArgs = container.buildArgs;\n }\n\n // Target stage — legacy uses container.targetStage\n if (container.targetStage) {\n dockerConfig.targetStage = container.targetStage;\n }\n\n // User — legacy uses container.user or bootstrap command user\n if (container.user) {\n dockerConfig.user = container.user;\n }\n\n // Bootstrap commands — legacy uses container.bootstrap.commands[]\n // Each entry has { entrypoint, cmd, user }\n // Migrate ALL commands as bootstrapCommands[] (structured array)\n const legacyBootstrapCmds: any[] = container.bootstrap?.commands || [];\n if (legacyBootstrapCmds.length > 0) {\n dockerConfig.bootstrapCommands = legacyBootstrapCmds\n .filter((bs: any) => bs.cmd || bs.entrypoint)\n .map((bs: any, idx: number) => ({\n id: bs.id || randomUUID(),\n label: bs.label || `Bootstrap ${idx + 1}`,\n command: bs.cmd || '',\n ...(bs.entrypoint ? { entrypoint: bs.entrypoint } : {}),\n ...(bs.user ? { user: bs.user } : {}),\n }));\n\n // Also set top-level entrypoint/command from first bootstrap for backwards compat\n const first = legacyBootstrapCmds[0];\n if (first?.entrypoint) dockerConfig.entrypoint = first.entrypoint;\n if (first?.cmd) dockerConfig.command = first.cmd;\n\n // Inherit user from first bootstrap if not set at container level\n if (!dockerConfig.user && first?.user) {\n dockerConfig.user = first.user;\n }\n }\n\n // ignoreVolumes → convert to real bind-mount volumes\n // Legacy used ignoreVolumes to mask container paths with a persistent host directory.\n // We convert each to ~/runeya/docker-persistence/<service-id>/<internal-path>:<internal-path>\n const sharedVolume: string = container.sharedVolume || '~/.runeya';\n const ignoreVolumes: string[] = (container.ignoreVolumes || [])\n .filter((v: string) => !v.startsWith(sharedVolume));\n if (ignoreVolumes.length > 0) {\n for (const ignoredPath of ignoreVolumes) {\n // Strip leading slash for the host sub-directory\n const subDir = ignoredPath.replace(/^\\/+/, '');\n const hostPath = `~/runeya/docker-persistence/${id}/${subDir}`;\n dockerConfig.volumes.push(`${hostPath}:${ignoredPath}`);\n }\n console.log(`[legacy-migration] Service \"${legacy.label}\": converted ${ignoreVolumes.length} ignoreVolumes to bind-mount volumes`);\n }\n\n // Native commands (spawnCmd) exist alongside Docker →\n // the service runs its native command inside the container\n if (commands.length > 0) {\n dockerConfig.useNativeCommand = true;\n dockerConfig.nativeCommandMode = 'isolated';\n }\n }\n\n // Port: extract from url (e.g. http://localhost:3034/... → 3034)\n let port: number | undefined;\n const serviceUrl: string = legacy.url || '';\n if (serviceUrl) {\n try {\n const parsed = new URL(serviceUrl);\n const p = Number.parseInt(parsed.port, 10);\n if (p > 0 && p <= 65535) port = p;\n } catch { /* invalid URL */ }\n }\n\n // Top-level cwd = legacy rootPath (global working directory for the service)\n const serviceCwd = rootPathCwd;\n\n const runeService: any = {\n id,\n orgId: null,\n agentId: 'local-agent',\n name: legacy.label,\n commands,\n cwd: serviceCwd,\n runner: dockerConfig ? 'docker' : 'native',\n shortcuts: (legacy.shortcuts || [])\n .filter((s: any) => s.spawnCmd || s.label)\n .map((s: any) => ({\n id: s.id || randomUUID(),\n label: s.label || s.spawnCmd || '',\n command: [s.spawnCmd, ...(s.spawnArgs || [])].filter(Boolean).join(' '),\n ...(s.spawnOptions?.cwd ? { cwd: s.spawnOptions.cwd } : {}),\n })),\n autoRestart: false,\n restartBackoffMs: 1000,\n groups: legacy.groups || [],\n description: legacy.description || '',\n url: legacy.url || '',\n openapiUrl: legacy.openapiURL || '',\n git: {\n remote: legacy.git?.remote || '',\n home: legacy.git?.home || '',\n },\n env: {},\n envSecrets: [],\n parserIds,\n meta: legacy.meta || {},\n ...(port !== undefined ? { ports: [port] } : {}),\n };\n\n if (healthCheck) runeService.healthCheck = healthCheck;\n if (dockerConfig) runeService.dockerConfig = dockerConfig;\n\n runeServices.push(runeService);\n }\n\n // Service inline envs → service-scoped environments (shared base variables)\n // Legacy stores per-service env vars as: service.envs = { \"LOCAL\": { \"KEY\": { value, key } }, ... }\n // These are the shared/committed base values — processed FIRST so overrides can reference their variableIds\n for (const [name, legacy] of Object.entries(legacyServices)) {\n const serviceId = serviceIdMap[name];\n if (!serviceId) continue;\n const service = runeServices.find((s: any) => s.id === serviceId);\n const svcEnvs: Record<string, Record<string, any>> = legacy.envs || {};\n\n for (const [envName, vars] of Object.entries(svcEnvs)) {\n if (!vars || typeof vars !== 'object' || Object.keys(vars).length === 0) continue;\n const globalEnvId = envIdMap[envName];\n const globalEnv = runeEnvs.find((e: any) => e.id === globalEnvId);\n if (!globalEnvId || !globalEnv) continue;\n\n let svcScopedEnv = runeEnvs.find(\n (e: any) => e.scope === 'service' && e.reference === serviceId && e.activateOn === globalEnvId,\n );\n\n if (!svcScopedEnv) {\n svcScopedEnv = {\n id: randomUUID(),\n projectId: projectMonoId,\n name: `${service?.name || name} (${globalEnv.name})`,\n scope: 'service' as const,\n reference: serviceId,\n activateOn: globalEnvId,\n parentIds: [],\n variables: {} as Record<string, Variable>,\n description: '',\n immutable: false,\n default: false,\n };\n runeEnvs.push(svcScopedEnv);\n }\n\n const existingKeys = new Set(\n Object.values(svcScopedEnv.variables as Record<string, Variable>).map((v: Variable) => v.key),\n );\n for (const [, varData] of Object.entries(vars as Record<string, any>)) {\n const varKey: string = typeof varData === 'object' ? String(varData.key ?? '') : '';\n const varValue: string = typeof varData === 'object' ? String(varData.value ?? '') : String(varData ?? '');\n const varPre: string = typeof varData === 'object' ? String(varData.prefix ?? '') : '';\n const varPost: string = typeof varData === 'object' ? String(varData.suffix ?? '') : '';\n if (!varKey || existingKeys.has(cleanVarKey(varKey))) continue;\n const cleaned = cleanVarKey(varKey);\n const varId = randomUUID();\n svcScopedEnv.variables[varId] = makeVariable(cleaned, varValue, varPre, varPost);\n existingKeys.add(cleaned);\n }\n }\n }\n\n // Service overrides → environment-overrides.json (personal/local overrides)\n // Legacy *-envs.encrypted.json files are per-user overrides of service-level env vars.\n // Service-scoped environments share the same override mechanism as global environments,\n // so these go into environment-overrides.json keyed by variableId.\n // If the base variable doesn't exist yet (no entry in service.envs), it is created with an\n // empty value so the override has something to reference.\n const svcFlatOverrides: Record<string, Variable> = {};\n for (const [serviceName, envOverrides] of Object.entries(legacyServiceOverrides)) {\n const serviceId = serviceIdMap[serviceName];\n if (!serviceId) continue;\n const service = runeServices.find((s: any) => s.id === serviceId);\n\n for (const [envName, vars] of Object.entries(envOverrides as Record<string, Record<string, string>>)) {\n const globalEnvId = envIdMap[envName];\n const globalEnv = runeEnvs.find((e: any) => e.id === globalEnvId);\n if (!globalEnv || !vars || typeof vars !== 'object') continue;\n\n // Find or create the service-scoped env for this (service, globalEnv) pair\n let svcScopedEnv = runeEnvs.find(\n (e: any) => e.scope === 'service' && e.reference === serviceId && e.activateOn === globalEnvId,\n );\n if (!svcScopedEnv) {\n svcScopedEnv = {\n id: randomUUID(),\n projectId: projectMonoId,\n name: `${service?.name || serviceName} (${globalEnv.name})`,\n scope: 'service' as const,\n reference: serviceId,\n activateOn: globalEnvId,\n parentIds: [],\n variables: {} as Record<string, Variable>,\n description: '',\n immutable: false,\n default: false,\n };\n runeEnvs.push(svcScopedEnv);\n }\n\n for (const [key, value] of Object.entries(vars)) {\n if (typeof value !== 'string') continue;\n if (hasInvalidInterpolation(value)) continue;\n const cleaned = cleanVarKey(key);\n\n // Find the base variable in the service-scoped env by key name\n const baseEntry = Object.entries(svcScopedEnv.variables as Record<string, Variable>)\n .find(([, v]) => v.key === cleaned);\n let varId = baseEntry?.[0];\n\n if (!varId) {\n // No base variable exists — create an empty base so the override has something to reference\n varId = randomUUID();\n svcScopedEnv.variables[varId] = {\n key: cleaned,\n value: { value: '', pre: '', post: '', isSecret: false, injectIntoAi: false },\n };\n }\n\n // Carry pre/post from the base variable — overrides only replace the value\n const basePre = baseEntry?.[1]?.value?.pre ?? '';\n const basePost = baseEntry?.[1]?.value?.post ?? '';\n // Skip redundant override — value identical to base\n if (isSameAsBase(value, baseEntry?.[1])) continue;\n svcFlatOverrides[varId] = makeVariable(cleaned, value, basePre, basePost);\n }\n }\n }\n\n // Environment overrides — from *-environment.encrypted.json files\n // Keys ending in _OVERRIDE → environment-overrides.json (flat Record<variableId, Variable>)\n // Other keys → merged into environment.variables (additional values)\n const flatOverrides: Record<string, Variable> = { ...svcFlatOverrides };\n for (const [envName, data] of Object.entries(legacyEnvOverrides)) {\n const envId = envIdMap[envName];\n const env = runeEnvs.find((e: any) => e.id === envId);\n if (!envId || !env || !data) continue;\n\n const envVars: Record<string, string> = (data as Record<string, unknown>).envs as Record<string, string> ?? {};\n\n for (const [key, value] of Object.entries(envVars)) {\n if (typeof value !== 'string') continue;\n\n if (key.endsWith('_OVERRIDE')) {\n // Strip all legacy suffixes → goes into environment-overrides.json\n const cleaned = cleanVarKey(key);\n const varId = varIdLookup.get(`${envId}:${cleaned}`);\n if (varId) {\n const baseVar = (env.variables as Record<string, Variable>)[varId];\n // Skip redundant override — value identical to base\n if (!isSameAsBase(value, baseVar)) {\n flatOverrides[varId] = makeVariable(cleaned, value);\n }\n } else {\n // Variable not found in env — create a new UUID entry\n flatOverrides[randomUUID()] = makeVariable(cleaned, value);\n }\n } else {\n // Regular variable → merge into environment.variables (with _RUNEYA stripped)\n const cleaned = cleanVarKey(key);\n // Check if this var already exists in env.variables (by key name)\n const existingVarId = Object.entries(env.variables as Record<string, Variable>)\n .find(([, v]) => v.key === cleaned)?.[0];\n if (!existingVarId) {\n const varId = randomUUID();\n env.variables[varId] = makeVariable(cleaned, value);\n varIdLookup.set(`${envId}:${cleaned}`, varId);\n }\n }\n }\n }\n\n // Projects — single project containing all services\n // Built AFTER service-scoped envs so allEnvIds includes them\n // Priority: explicit default flag → env named LOCAL → first env\n const localEnvName = Object.keys(legacyEnvs).find(n => n.toUpperCase() === 'LOCAL');\n const activeEnvId = defaultEnvName\n ? (envIdMap[defaultEnvName] ?? runeEnvs[0]?.id)\n : (localEnvName ? (envIdMap[localEnvName] ?? runeEnvs[0]?.id) : runeEnvs[0]?.id);\n const allEnvIds = runeEnvs.map(e => e.id);\n const allServiceIds = runeServices.map(s => s.id);\n\n const runeProjects: any[] = [];\n if (allServiceIds.length > 0 || allEnvIds.length > 0) {\n runeProjects.push({\n id: projectMonoId,\n orgId: null,\n name: 'Migrated Project',\n description: '',\n serviceIds: allServiceIds,\n environmentIds: allEnvIds,\n activeEnvironmentId: activeEnvId,\n });\n }\n\n const primaryProjectId = projectMonoId;\n for (const env of runeEnvs) {\n env.projectId = primaryProjectId;\n }\n\n // Settings — preserve existing + add migrated custom parsers\n let existingSettings: any = {};\n try {\n existingSettings = JSON.parse(await readFile(join(dataDir, 'settings.json'), 'utf-8'));\n } catch { /* first run */ }\n\n const migratedParsers = legacyParsers.map(p => ({\n id: p.id,\n name: p.label,\n // Legacy transform uses module.exports API — kept for reference, must be rewritten\n code: `// Migrated from legacy parser \"${p.label}\"\\n// TODO: rewrite using new API: (raw: string, stream: 'stdout'|'stderr') => ParseResult | null\\n// Legacy code (module.exports style — NOT compatible):\\n${p.transform ?? ''}`,\n enabled: false, // disabled until manually rewritten\n }));\n\n const newSettings = {\n ...existingSettings,\n logParsers: [\n ...(existingSettings.logParsers ?? []),\n ...migratedParsers,\n ],\n };\n\n // ── 5. Write output files ────────────────────────────────────────────────────\n await atomicWrite(join(dataDir, 'projects.json'), runeProjects);\n await atomicWrite(join(dataDir, 'services.json'), runeServices);\n await atomicWrite(join(dataDir, 'environments.json'), runeEnvs);\n await atomicWrite(join(dataDir, 'environment-overrides.json'), flatOverrides);\n await atomicWrite(join(dataDir, 'settings.json'), newSettings);\n\n const svcEnvCount = runeEnvs.filter((e: any) => e.scope === 'service').length;\n console.log(`[legacy-migration] Written: ${runeProjects.length} projects, ${runeServices.length} services, ${runeEnvs.length} environments (${svcEnvCount} service-scoped)`);\n console.log(`[legacy-migration] Overrides: ${Object.keys(flatOverrides).length}, custom parsers: ${migratedParsers.length} (all disabled — rewrite required)`);\n\n // Clear the main singleton so hasEncryptionKey() returns false → state = setup\n // Store the key in the pending holder for /api/setup to consume\n clearEncryptionKey();\n setPendingLegacyKey(keyBuffer);\n console.log('[legacy-migration] Done. Data migrated to .runeya — master password setup required');\n\n return true;\n}\n\n// ── Find legacy key in backup (restart between migration and setup) ─────────\n//\n// If the server restarts after runLegacyMigration but before /api/setup,\n// the pending key is lost (in-memory only). This function scans backup dirs\n// to recover the libsodium key so the user can still complete setup.\n\nexport async function findLegacyKeyInBackup(dataDir: string): Promise<Buffer | null> {\n try {\n const entries = await readdir(dataDir);\n // Comparateur par code-point (identique au tri par défaut) : on sélectionne\n // le backup le plus récent, l'ordre doit rester celui des noms backup-<ts>.\n const backupDirs = entries\n .filter(e => e.startsWith('backup-'))\n .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n .reverse();\n for (const dir of backupDirs) {\n const keyJsonPath = join(dataDir, dir, 'dbs', 'encryption-key.json');\n try {\n const raw = await readFile(keyJsonPath, 'utf-8');\n const parsed = JSON.parse(raw) as { encryptionKey?: string };\n if (!parsed.encryptionKey) continue;\n const sodium = await getSodium();\n const sodiumKey = sodium.from_base64(parsed.encryptionKey) as Uint8Array;\n const buf = Buffer.from(sodiumKey);\n if (buf.length === 32) {\n console.log(`[legacy-migration] Recovered legacy key from ${keyJsonPath}`);\n return buf;\n }\n } catch {\n // This backup dir doesn't have a valid key — try next\n }\n }\n } catch {\n // dataDir doesn't exist or isn't readable\n }\n return null;\n}\n\n// ── Override-only migration (User B scenario) ──────────────────────────────\n//\n// When the data dir is tracked by git and User A already ran the full migration:\n// - Git deleted dbs/encryption-key.json (was tracked)\n// - Git delivered the migrated JSON files (projects, services, environments…)\n// - But User B's dbs/overrides/*.encrypted.json are still on disk (gitignored)\n// - The full migration didn't trigger (no encryption-key.json)\n// - User B's overrides were never migrated → orphaned\n//\n// This function runs AFTER .encryption.key is available (same 32 bytes as\n// the legacy libsodium key, just in hex format). It decrypts User B's local\n// override files and writes environment-overrides.json.\n\nexport async function runOverrideOnlyMigration(dataDir: string): Promise<boolean> {\n // oxlint-disable-next-line typescript/unbound-method -- resolve is a pure module function from node:path, not a class method\n const { resolve } = await import('node:path');\n const abDataDir = resolve(dataDir);\n\n // Match the full migration: legacy data lives under cwd/.runeya, which may\n // differ from DATA_DIR. Check both locations; prefer cwd-based path (the\n // one git tracks), fall back to dataDir-based path.\n const abCwd = resolve(process.cwd());\n const candidateDirs = [\n join(abCwd, '.runeya', 'dbs', 'overrides'),\n join(abDataDir, 'dbs', 'overrides'),\n ];\n\n let overridesDir: string | null = null;\n let overrideFiles: string[] = [];\n for (const dir of candidateDirs) {\n try {\n const files = (await readdir(dir)).filter(f => f.endsWith('.encrypted.json'));\n if (files.length > 0) {\n overridesDir = dir;\n overrideFiles = files;\n break;\n }\n } catch { /* dir doesn't exist */ }\n }\n if (!overridesDir || overrideFiles.length === 0) return false;\n\n // If the full migration trigger still exists, let the full migration handle it\n const legacyKeyPath = join(overridesDir, '..', 'encryption-key.json');\n try {\n await access(legacyKeyPath);\n return false; // Full migration should run instead\n } catch {\n // Expected — key was deleted by git\n }\n\n // We need .encryption.key to decrypt (it's the same 32 bytes)\n const encKey = getEncryptionKey();\n if (!encKey) {\n console.warn('[override-migration] Cannot migrate overrides: encryption key not loaded yet');\n return false;\n }\n\n console.log(`[override-migration] Found ${overrideFiles.length} orphaned override file(s) in ${overridesDir}, migrating…`);\n\n const sodium = await getSodium();\n // .encryption.key is the same 32 bytes as the legacy libsodium key\n const sodiumKey = new Uint8Array(encKey);\n\n // Load existing environments.json to build lookups\n const varIdLookup = new Map<string, string>();\n const envNameToId: Record<string, string> = {};\n let envsRaw: unknown[];\n try {\n envsRaw = JSON.parse(await readFile(join(abDataDir, 'environments.json'), 'utf-8')) as unknown[];\n for (const _env of envsRaw) {\n const env = _env as Record<string, unknown>;\n if (env['name'] && env['id']) {\n envNameToId[env['name'] as string] = env['id'] as string;\n }\n if (env['variables'] && env['id']) {\n for (const [varId, variable] of Object.entries(env['variables'] as Record<string, Variable>)) {\n varIdLookup.set(`${env['id'] as string}:${variable.key}`, varId);\n }\n }\n }\n } catch {\n console.warn('[override-migration] Cannot read environments.json — skipping');\n return false;\n }\n\n // Load services.json for service-override matching (legacy fileName → service name)\n let servicesRaw: unknown[] = [];\n const serviceNameToId: Record<string, string> = {};\n try {\n servicesRaw = JSON.parse(await readFile(join(abDataDir, 'services.json'), 'utf-8')) as unknown[];\n for (const _svc of servicesRaw) {\n const svc = _svc as Record<string, unknown>;\n if (svc['name'] && svc['id']) serviceNameToId[svc['name'] as string] = svc['id'] as string;\n }\n } catch { /* services.json missing — service overrides won't match */ }\n\n // Helper: find env ID by name (exact or case-insensitive)\n function findEnvId(name: string): string | undefined {\n return envNameToId[name]\n ?? Object.entries(envNameToId).find(([n]) => n.toLowerCase() === name.toLowerCase())?.[1];\n }\n\n // ── 1. Environment overrides (*-environment.encrypted.json) → environment-overrides.json ──\n const flatOverrides: Record<string, Variable> = {};\n\n for (const file of overrideFiles) {\n const baseName = file.replace('.encrypted.json', '');\n if (!baseName.endsWith('-environment')) continue;\n const envName = baseName.slice(0, -'-environment'.length);\n\n let data: any;\n try {\n data = await decryptLegacyFile(join(overridesDir, file), sodiumKey, sodium);\n } catch (err: unknown) {\n console.warn(`[override-migration] Failed to decrypt ${file}: ${(err as Error).message}`);\n continue;\n }\n if (!data) continue;\n\n const envId = findEnvId(envName);\n if (!envId) {\n console.warn(`[override-migration] No matching environment for \"${envName}\" — skipping`);\n continue;\n }\n\n const envVars: Record<string, string> = data.envs ?? {};\n for (const [key, value] of Object.entries(envVars)) {\n if (typeof value !== 'string') continue;\n if (!key.endsWith('_OVERRIDE')) continue;\n\n const cleaned = cleanVarKey(key);\n const varId = varIdLookup.get(`${envId}:${cleaned}`);\n if (varId) {\n const baseVar = ((envsRaw as Record<string, unknown>[]).find((e) => e['id'] === envId)?.['variables'] as Record<string, Variable> | undefined)?.[varId];\n // Skip redundant override — value identical to base\n if (isSameAsBase(value, baseVar)) continue;\n flatOverrides[varId] = makeVariable(cleaned, value);\n } else {\n flatOverrides[randomUUID()] = makeVariable(cleaned, value);\n }\n }\n }\n\n if (Object.keys(flatOverrides).length > 0) {\n await atomicWrite(join(abDataDir, 'environment-overrides.json'), flatOverrides);\n console.log(`[override-migration] Written ${Object.keys(flatOverrides).length} override(s) to environment-overrides.json`);\n }\n\n // ── 2. Service overrides (*-envs.encrypted.json) → environment-overrides.json ──\n // Service-scoped environments share the same override mechanism as global environments.\n // Personal service variable overrides go into environment-overrides.json (keyed by variableId).\n // If the base variable doesn't exist in the service-scoped env, an empty base is created first.\n let envsModified = false;\n\n for (const file of overrideFiles) {\n const baseName = file.replace('.encrypted.json', '');\n if (!baseName.endsWith('-envs')) continue;\n const serviceName = baseName.slice(0, -'-envs'.length);\n\n let data: any;\n try {\n data = await decryptLegacyFile(join(overridesDir, file), sodiumKey, sodium);\n } catch (err: unknown) {\n console.warn(`[override-migration] Failed to decrypt ${file}: ${(err as Error).message}`);\n continue;\n }\n if (!data || typeof data !== 'object') continue;\n\n // Find service ID: try by legacy filename, then case-insensitive name match\n const serviceId = serviceNameToId[serviceName]\n ?? Object.entries(serviceNameToId).find(([n]) => n.toLowerCase() === serviceName.toLowerCase())?.[1];\n if (!serviceId) {\n console.warn(`[override-migration] No matching service for \"${serviceName}\" — skipping service overrides`);\n continue;\n }\n\n const service = (servicesRaw as Record<string, unknown>[]).find((s) => s['id'] === serviceId);\n\n for (const [envName, vars] of Object.entries(data as Record<string, Record<string, string>>)) {\n const globalEnvId = findEnvId(envName);\n if (!globalEnvId || !vars || typeof vars !== 'object') continue;\n const globalEnv = (envsRaw as Record<string, unknown>[]).find((e) => e['id'] === globalEnvId);\n if (!globalEnv) continue;\n\n // Find or create the service-scoped env for this (service, globalEnv) pair\n let svcScopedEnv = (envsRaw as Record<string, unknown>[]).find(\n (e) => e['scope'] === 'service' && e['reference'] === serviceId && e['activateOn'] === globalEnvId,\n );\n if (!svcScopedEnv) {\n svcScopedEnv = {\n id: randomUUID(),\n projectId: globalEnv['projectId'],\n name: `${(service?.['name'] as string | undefined) || serviceName} (${globalEnv['name'] as string})`,\n scope: 'service' as const,\n reference: serviceId,\n activateOn: globalEnvId,\n parentIds: [],\n variables: {} as Record<string, Variable>,\n description: '',\n immutable: false,\n default: false,\n };\n envsRaw.push(svcScopedEnv);\n envsModified = true;\n }\n\n for (const [key, value] of Object.entries(vars)) {\n if (typeof value !== 'string') continue;\n if (hasInvalidInterpolation(value)) continue;\n const cleaned = cleanVarKey(key);\n\n // Find the base variable in the service-scoped env by key name\n const baseEntry = Object.entries(svcScopedEnv['variables'] as Record<string, Variable>)\n .find(([, v]) => v.key === cleaned);\n let varId = baseEntry?.[0];\n\n if (!varId) {\n // No base variable — create an empty base so the override has something to reference\n varId = randomUUID();\n (svcScopedEnv['variables'] as Record<string, Variable>)[varId] = {\n key: cleaned,\n value: { value: '', pre: '', post: '', isSecret: false, injectIntoAi: false },\n };\n envsModified = true;\n }\n\n // Carry pre/post from the base variable — overrides only replace the value\n const basePre = baseEntry?.[1]?.value?.pre ?? '';\n const basePost = baseEntry?.[1]?.value?.post ?? '';\n // Skip redundant override — value identical to base\n if (isSameAsBase(value, baseEntry?.[1])) continue;\n flatOverrides[varId] = makeVariable(cleaned, value, basePre, basePost);\n }\n }\n }\n\n if (envsModified) {\n await atomicWrite(join(abDataDir, 'environments.json'), envsRaw);\n console.log('[override-migration] Merged service overrides into environments.json');\n }\n\n // Move dbs/overrides/ → dbs/overrides-migrated/ to prevent re-running\n const migratedDir = overridesDir.replace(/overrides$/, 'overrides-migrated');\n try {\n await rename(overridesDir, migratedDir);\n console.log(`[override-migration] Moved overrides/ → overrides-migrated/`);\n } catch (err: unknown) {\n console.warn(`[override-migration] Could not rename overrides dir: ${(err as Error).message}`);\n }\n\n console.log('[override-migration] Done');\n return true;\n}\n","import { join } from 'node:path';\nimport { stat } from 'node:fs/promises';\nimport { hasEncryptionKey, hasPendingLegacyKey } from '../utils/encryption-key.js';\nimport { env } from '../config/env.js';\n\nexport type ServerState = 'locked' | 'setup' | 'unlocked';\n\nconst ENCRYPTED_KEY_FILENAME = '.encryption.key.enc';\nconst VERIFY_FILENAME = '.runeya-verify';\n\nexport async function getServerState(): Promise<{ state: ServerState; hasVerifyFile: boolean; isLegacyMigration: boolean; hasExistingData: boolean }> {\n const dataDir = env.DATA_DIR;\n\n let hasEncFile = false;\n let hasVerify = false;\n let hasData = false;\n\n try { await stat(join(dataDir, ENCRYPTED_KEY_FILENAME)); hasEncFile = true; } catch {}\n try { await stat(join(dataDir, VERIFY_FILENAME)); hasVerify = true; } catch {}\n try { await stat(join(dataDir, 'projects.json')); hasData = true; } catch {}\n\n if (hasEncryptionKey()) {\n return { state: 'unlocked', hasVerifyFile: false, isLegacyMigration: false, hasExistingData: hasData };\n }\n\n if (hasEncFile) {\n return { state: 'locked', hasVerifyFile: hasVerify, isLegacyMigration: false, hasExistingData: hasData };\n }\n\n // SETUP state — legacy migration detected via in-memory pending key holder\n return {\n state: 'setup',\n hasVerifyFile: hasVerify,\n isLegacyMigration: hasPendingLegacyKey(),\n hasExistingData: hasData,\n };\n}\n","import { env } from '../config/env.js';\n\nconst BASE = `http://localhost:${env.PORT}/api/trpc`;\n\nexport function getOpenApiDocument() {\n return {\n openapi: '3.1.0',\n info: {\n title: 'Runeya API',\n version: '1.0.0',\n description: 'Runeya service management API — tRPC over HTTP.\\n\\n**Queries** use `GET /{procedure}?input={json}`.\\n**Mutations** use `POST /{procedure}` with a JSON body.\\n\\nAll protected routes require `Authorization: Bearer <jwt>` header.',\n },\n servers: [{ url: BASE }],\n paths: {\n '/health.check': {\n get: {\n tags: ['Health'],\n summary: 'Health check',\n operationId: 'health.check',\n responses: {\n '200': { description: 'Server is up', content: { 'application/json': { schema: { type: 'object', properties: { result: { type: 'object', properties: { data: { type: 'object', properties: { status: { type: 'string', example: 'ok' }, uptime: { type: 'number' } } } } } } } } } },\n },\n },\n },\n '/service.list': {\n get: {\n tags: ['Services'],\n summary: 'List all services',\n operationId: 'service.list',\n security: [{ BearerAuth: [] }],\n responses: {\n '200': { description: 'Array of services', content: { 'application/json': { schema: { type: 'object', properties: { result: { type: 'object', properties: { data: { type: 'array', items: { $ref: '#/components/schemas/Service' } } } } } } } } },\n },\n },\n },\n '/service.get': {\n get: {\n tags: ['Services'],\n summary: 'Get a service by ID',\n operationId: 'service.get',\n security: [{ BearerAuth: [] }],\n parameters: [{\n name: 'input',\n in: 'query',\n required: true,\n schema: { type: 'string' },\n example: '{\"id\":\"<serviceId>\"}',\n description: 'JSON-encoded input: `{\"id\":\"<serviceId>\"}`',\n }],\n responses: {\n '200': { description: 'Service object', content: { 'application/json': { schema: { type: 'object', properties: { result: { type: 'object', properties: { data: { $ref: '#/components/schemas/Service' } } } } } } } },\n },\n },\n },\n '/service.create': {\n post: {\n tags: ['Services'],\n summary: 'Create a new service',\n operationId: 'service.create',\n security: [{ BearerAuth: [] }],\n requestBody: {\n required: true,\n content: { 'application/json': { schema: { type: 'object', required: ['agentId', 'name'], properties: {\n agentId: { type: 'string' },\n name: { type: 'string' },\n commands: { type: 'array', items: { type: 'object' } },\n cwd: { type: 'string' },\n port: { type: 'integer' },\n description: { type: 'string' },\n url: { type: 'string' },\n runner: { type: 'string', enum: ['native', 'docker'], default: 'native' },\n } } } },\n },\n responses: {\n '200': { description: 'Created service', content: { 'application/json': { schema: { type: 'object', properties: { result: { type: 'object', properties: { data: { $ref: '#/components/schemas/Service' } } } } } } } },\n },\n },\n },\n '/service.update': {\n post: {\n tags: ['Services'],\n summary: 'Update a service',\n operationId: 'service.update',\n security: [{ BearerAuth: [] }],\n requestBody: {\n required: true,\n content: { 'application/json': { schema: { type: 'object', required: ['id'], properties: {\n id: { type: 'string' },\n name: { type: 'string' },\n commands: { type: 'array', items: { type: 'object' } },\n cwd: { type: 'string' },\n port: { type: 'integer' },\n description: { type: 'string' },\n url: { type: 'string' },\n } } } },\n },\n responses: {\n '200': { description: 'Updated service', content: { 'application/json': { schema: { type: 'object', properties: { result: { type: 'object', properties: { data: { $ref: '#/components/schemas/Service' } } } } } } } },\n },\n },\n },\n '/service.delete': {\n post: {\n tags: ['Services'],\n summary: 'Delete a service',\n operationId: 'service.delete',\n security: [{ BearerAuth: [] }],\n requestBody: {\n required: true,\n content: { 'application/json': { schema: { type: 'object', required: ['id'], properties: { id: { type: 'string' } } } } },\n },\n responses: {\n '200': { description: 'Deletion result', content: { 'application/json': { schema: { type: 'object', properties: { result: { type: 'object', properties: { data: { type: 'object', properties: { success: { type: 'boolean' } } } } } } } } } },\n },\n },\n },\n '/process.list': {\n get: {\n tags: ['Processes'],\n summary: 'List all processes across all connected agents',\n operationId: 'process.list',\n security: [{ BearerAuth: [] }],\n responses: {\n '200': { description: 'Array of processes', content: { 'application/json': { schema: { type: 'object', properties: { result: { type: 'object', properties: { data: { type: 'array', items: { $ref: '#/components/schemas/Process' } } } } } } } } },\n },\n },\n },\n '/process.get': {\n get: {\n tags: ['Processes'],\n summary: 'Get a process by agent and service ID',\n operationId: 'process.get',\n security: [{ BearerAuth: [] }],\n parameters: [{\n name: 'input',\n in: 'query',\n required: true,\n schema: { type: 'string' },\n example: '{\"agentId\":\"<agentId>\",\"id\":\"<serviceId>\"}',\n description: 'JSON-encoded input: `{\"agentId\":\"<agentId>\",\"id\":\"<serviceId>\"}`',\n }],\n responses: {\n '200': { description: 'Process object' },\n },\n },\n },\n '/process.logs': {\n get: {\n tags: ['Processes'],\n summary: 'Get buffered logs for a process',\n operationId: 'process.logs',\n security: [{ BearerAuth: [] }],\n parameters: [{\n name: 'input',\n in: 'query',\n required: true,\n schema: { type: 'string' },\n example: '{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}',\n description: 'JSON-encoded input: `{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}`',\n }],\n responses: {\n '200': { description: 'Array of log lines' },\n },\n },\n },\n '/process.start': {\n post: {\n tags: ['Processes'],\n summary: 'Start a process',\n operationId: 'process.start',\n security: [{ BearerAuth: [] }],\n requestBody: {\n required: true,\n content: { 'application/json': { schema: { type: 'object', required: ['agentId', 'processId'], properties: {\n agentId: { type: 'string' },\n processId: { type: 'string' },\n } } } },\n },\n responses: {\n '200': { description: 'Start result' },\n },\n },\n },\n '/process.stop': {\n post: {\n tags: ['Processes'],\n summary: 'Stop a process',\n operationId: 'process.stop',\n security: [{ BearerAuth: [] }],\n requestBody: {\n required: true,\n content: { 'application/json': { schema: { type: 'object', required: ['agentId', 'processId'], properties: {\n agentId: { type: 'string' },\n processId: { type: 'string' },\n } } } },\n },\n responses: {\n '200': { description: 'Stop result' },\n },\n },\n },\n '/process.restart': {\n post: {\n tags: ['Processes'],\n summary: 'Restart a process',\n operationId: 'process.restart',\n security: [{ BearerAuth: [] }],\n requestBody: {\n required: true,\n content: { 'application/json': { schema: { type: 'object', required: ['agentId', 'processId'], properties: {\n agentId: { type: 'string' },\n processId: { type: 'string' },\n } } } },\n },\n responses: {\n '200': { description: 'Restart result' },\n },\n },\n },\n '/environment.resolveFlat': {\n get: {\n tags: ['Environments'],\n summary: 'Resolve environment variables as a flat key-value map',\n operationId: 'environment.resolveFlat',\n security: [{ BearerAuth: [] }],\n parameters: [{\n name: 'input',\n in: 'query',\n required: true,\n schema: { type: 'string' },\n example: '{\"environmentId\":\"<environmentId>\"}',\n description: 'JSON-encoded input: `{\"environmentId\":\"<environmentId>\"}`',\n }],\n responses: {\n '200': { description: 'Flat key-value map of resolved variables', content: { 'application/json': { schema: { type: 'object', properties: { result: { type: 'object', properties: { data: { type: 'object', additionalProperties: { type: 'string' } } } } } } } } },\n },\n },\n },\n },\n components: {\n securitySchemes: {\n BearerAuth: { type: 'http', scheme: 'bearer', description: 'JWT token from /api/unlock or /api/setup' },\n },\n schemas: {\n Service: {\n type: 'object',\n properties: {\n id: { type: 'string' },\n name: { type: 'string' },\n agentId: { type: 'string' },\n commands: { type: 'array', items: { type: 'object' } },\n cwd: { type: 'string' },\n port: { type: 'integer' },\n description: { type: 'string' },\n url: { type: 'string' },\n runner: { type: 'string', enum: ['native', 'docker'] },\n },\n },\n Process: {\n type: 'object',\n properties: {\n id: { type: 'string' },\n agentId: { type: 'string' },\n state: { type: 'string', enum: ['stopped', 'starting', 'running', 'stopping', 'errored'] },\n pid: { type: 'integer', nullable: true },\n exitCode: { type: 'integer', nullable: true },\n },\n },\n },\n },\n };\n}\n","import { imageStorageService } from './image-storage.service.js';\n\nexport class ImageCleanupService {\n private timer: ReturnType<typeof setInterval> | null = null;\n\n async runCleanup(): Promise<{ deleted: number; errors: number }> {\n const expired = await imageStorageService.listExpiredImages();\n let deleted = 0;\n let errors = 0;\n await Promise.all(\n expired.map(async (img) => {\n try {\n await imageStorageService.deleteImage(img.imageId);\n deleted++;\n } catch {\n errors++;\n }\n }),\n );\n return { deleted, errors };\n }\n\n start(intervalMs = 60 * 60 * 1000): void {\n if (this.timer) return;\n this.runCleanup().catch((err) => console.error('[image-cleanup] error:', err));\n this.timer = setInterval(() => {\n this.runCleanup().catch((err) => console.error('[image-cleanup] error:', err));\n }, intervalMs);\n }\n\n stop(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n }\n}\n\nexport const imageCleanupService = new ImageCleanupService();\n","import type { Server } from 'node:http';\nimport type { WebSocketServer } from 'ws';\nimport { env } from './config/env.js';\nimport { createLocalServer } from './create-server.js';\nimport { shutdownCodexAppServer } from './services/ai-runners/codex-runner.js';\nimport { resolve as resolvePath } from 'node:path';\nimport dotenv from 'dotenv'\ndotenv.config({ quiet: true })\n\n// Align cwd with the parent of RUNEYA_DATA_DIR when set, so spawned services\n// resolve relative cwds against the user's stack root rather than the server's own dir.\nif (process.env['RUNEYA_DATA_DIR']) {\n const resolved = resolvePath(process.env['RUNEYA_DATA_DIR'], '..');\n process.chdir(resolved);\n console.log(`[server] Working directory: ${resolved} (from RUNEYA_DATA_DIR)`);\n}\n\n// Re-export for CLI usage\nexport { createLocalServer } from './create-server.js';\nexport type { ServerInstance } from './create-server.js';\nexport { pullEnv, PullEnvError } from './commands/pull-env.js';\n\n/**\n * Listen with retry for EADDRINUSE — handles the race condition when the CLI\n * restarts the server before the old process has fully released the port.\n *\n * The `wss` parameter is needed because the `ws` library re-emits HTTP server\n * errors on the WebSocketServer — without a handler the error becomes unhandled.\n */\nfunction listenWithRetry(\n server: Server,\n port: number,\n host: string,\n wss?: WebSocketServer,\n maxRetries = 20,\n delay = 500,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n let attempts = 0;\n\n // Absorb EADDRINUSE errors re-emitted by the ws library on the WSS\n // during the retry window. Without this, Node.js crashes on unhandled error.\n const wssErrorHandler = () => { /* absorbed — handled via server 'error' */ };\n wss?.on('error', wssErrorHandler);\n\n const tryListen = () => {\n const onError = (err: NodeJS.ErrnoException) => {\n // Clean up the 'listening' callback that server.listen() registered\n server.removeAllListeners('listening');\n\n if (err.code === 'EADDRINUSE' && attempts < maxRetries) {\n attempts++;\n console.log(`[server] Port ${port} in use, retrying in ${delay}ms (${attempts}/${maxRetries})...`);\n setTimeout(tryListen, delay);\n } else {\n wss?.removeListener('error', wssErrorHandler);\n reject(err);\n }\n };\n\n server.once('error', onError);\n server.listen(port, host, () => {\n server.removeListener('error', onError);\n wss?.removeListener('error', wssErrorHandler);\n resolve();\n });\n };\n\n tryListen();\n });\n}\n\nasync function main() {\n console.log('Hello World 2');\n // oxlint-disable-next-line typescript/unbound-method -- shutdown is a standalone closure returned by createLocalServer, not a class method\n const { server, wss, shutdown } = await createLocalServer();\n\n await listenWithRetry(server, env.PORT, env.HOST, wss);\n console.log(`[server] Local server listening on ${env.HOST}:${env.PORT}`);\n console.log(`[server] tRPC HTTP: http://${env.HOST}:${env.PORT}/api/trpc`);\n console.log(`[server] tRPC WS: ws://${env.HOST}:${env.PORT}`); // nosemgrep:javascript.lang.security.detect-insecure-websocket.detect-insecure-websocket\n console.log(`[server] Mode: ${env.MODE}`);\n if (env.RUNEYA_LAN_PROXY) {\n console.log('[server] LAN mode: server exposed on local network (0.0.0.0)');\n console.log('[server] LAN mode: {{service.HOST}} resolves to 0.0.0.0 — configure your services accordingly');\n }\n\n let shuttingDown = false;\n const gracefulShutdown = async (signal: string) => {\n if (shuttingDown) {\n console.log(`[server] Forced exit (second ${signal})`);\n process.exit(1);\n }\n shuttingDown = true;\n console.log(`[server] Received ${signal}, shutting down gracefully...`);\n\n // In dev, exit immediately — ports are freed on process death,\n // and the 'exit' handler in agent-spawner SIGKILLs the agent.\n if (process.env.NODE_ENV === 'development') {\n process.exit(0);\n }\n\n await shutdownCodexAppServer();\n await shutdown();\n process.exit(0);\n };\n\n process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));\n process.on('SIGINT', () => gracefulShutdown('SIGINT'));\n}\n\n// Only run main if this file is executed directly (not imported)\nif (import.meta.url === `file://${process.argv[1]}`) {\n main().catch((err) => {\n console.error('[server] Fatal error:', err);\n process.exit(1);\n });\n}\n","import { serviceStore } from '../services/service-store.js';\nimport { environmentStore } from '../services/environment-store.js';\nimport { environmentResolver } from '../services/environment-resolver.js';\nimport { ensureEncryptionKey, hasEncryptionKey, loadFromEnv, setEncryptionKeyInMemory } from '../utils/encryption-key.js';\nimport { readEncryptedKey, hasEncryptedKeyFile } from '../services/master-password.js';\nimport { env as serverEnv } from '../config/env.js';\n\nexport class PullEnvError extends Error {\n constructor(\n message: string,\n public readonly exitCode: number,\n ) {\n super(message);\n this.name = 'PullEnvError';\n }\n}\n\nasync function promptPassword(): Promise<string> {\n process.stderr.write('Master password: ');\n return new Promise((resolve) => {\n const stdin = process.stdin;\n const wasRaw = stdin.isRaw;\n if (stdin.isTTY) stdin.setRawMode(true);\n stdin.resume();\n stdin.setEncoding('utf-8');\n let input = '';\n const onData = (ch: string) => {\n if (ch === '\\r' || ch === '\\n') {\n if (stdin.isTTY) stdin.setRawMode(wasRaw ?? false);\n stdin.pause();\n stdin.removeListener('data', onData);\n process.stderr.write('\\n');\n resolve(input);\n } else if (ch === '\\u0003') {\n // Ctrl+C\n process.exit(1);\n } else if (ch === '\\u007f' || ch === '\\b') {\n input = input.slice(0, -1);\n } else {\n input += ch;\n }\n };\n stdin.on('data', onData);\n });\n}\n\nasync function unlockIfNeeded(): Promise<void> {\n // Call ensureEncryptionKey first (allows tests to mock it)\n await ensureEncryptionKey();\n if (hasEncryptionKey()) return;\n\n // CI mode: RUNEYA_ENCRYPTION_KEY env var\n if (await loadFromEnv()) return;\n\n // Check if encrypted key file exists (i.e. setup was completed)\n if (!(await hasEncryptedKeyFile(serverEnv.DATA_DIR))) {\n // No encryption key file — either fresh install or test environment; proceed without encryption\n return;\n }\n\n // Try RUNEYA_MASTER_PASSWORD env var, then prompt\n const masterPassword = process.env['RUNEYA_MASTER_PASSWORD'] || await promptPassword();\n if (!masterPassword) {\n throw new PullEnvError('Master password required to decrypt data', 1);\n }\n\n try {\n const encKey = await readEncryptedKey(serverEnv.DATA_DIR, masterPassword);\n setEncryptionKeyInMemory(encKey);\n } catch {\n throw new PullEnvError('Master password incorrect', 1);\n }\n}\n\n/**\n * Resolve env vars for a service+environment and return them as KEY=VALUE lines.\n * Throws PullEnvError if the service or environment is not found.\n */\nexport async function pullEnv(opts: { service: string; environment: string }): Promise<string> {\n await unlockIfNeeded();\n\n const services = await serviceStore.list();\n const service = services.find(\n (s) => s.id === opts.service || s.name === opts.service,\n );\n if (!service) {\n const available = services.map((s) => s.name).join(', ');\n throw new PullEnvError(`service \"${opts.service}\" not found. Available: ${available || '(none)'}`, 1);\n }\n\n const globalEnvs = await environmentStore.listAllGlobal();\n const globalEnv = globalEnvs.find(\n (e) => e.id === opts.environment || e.name === opts.environment,\n );\n if (!globalEnv) {\n const available = globalEnvs.map((e) => e.name).join(', ');\n throw new PullEnvError(`environment \"${opts.environment}\" not found. Available: ${available || '(none)'}`, 1);\n }\n\n const { env } = await environmentResolver.resolveForService({\n serviceId: service.id,\n activeEnvironmentId: globalEnv.id,\n });\n\n return Object.entries(env)\n .map(([key, value]) => `${key}=${value}`)\n .join('\\n');\n}\n"],"mappings":"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","names":["resolve","randomBytes","randomBytes","token","z","TRPCError","randomUUID","readFile","writeFile","rename","mkdir","chmod","join","join","mkdir","readFile","writeFile","rename","chmod","randomUUID","readFile","writeFile","rename","mkdir","chmod","join","FILENAME","join","mkdir","readFile","writeFile","rename","chmod","env","ctx","readFile","rename","mkdir","join","join","mkdir","readFile","rename","z","TRPCError","z","TRPCError","readFile","writeFile","rename","mkdir","chmod","join","mkdir","join","writeFile","rename","chmod","readFile","z","TRPCError","z","TRPCError","z","TRPCError","resolve","z","TRPCError","SUBSCRIPTION_QUEUE_MAX","resolve","z","TRPCError","z","z","z","z","z","TRPCError","z","env","TRPCError","z","TRPCError","maskApiKey","z","TRPCError","resolve","z","TRPCError","execFile","stat","resolve","join","homedir","readFile","writeFile","rename","mkdir","chmod","join","z","homedir","TRPCError","resolve","execFile","z","stat","join","z","TRPCError","mkdir","writeFile","join","z","TRPCError","join","mkdir","writeFile","z","Anthropic","OpenAI","execFile","promisify","readdir","readFile","homedir","join","randomUUID","readFile","writeFile","rename","mkdir","chmod","join","EventEmitter","FILENAME","EventEmitter","join","mkdir","readFile","writeFile","rename","chmod","randomUUID","join","homedir","readdir","readFile","t","readdir","homedir","join","TRPCError","z","t","resolve","env","pty","MONTHS","resolve","mkdir","readFile","join","chmod","mkdir","rename","writeFile","dirname","resolve","readFile","resolve","mkdir","dirname","writeFile","rename","chmod","mkdir","t","join","readFile","randomUUID","mkdir","writeFile","readFile","unlink","readdir","join","resolve","sep","randomUUID","z","TRPCError","readFile","writeFile","rename","mkdir","chmod","unlink","randomBytes","timingSafeEqual","join","FILENAME","join","readFile","randomBytes","timingSafeEqual","mkdir","writeFile","rename","chmod","unlink","TRPCError","z","randomUUID","spawn","randomUUID","watch","watch","resolve","agentManager","randomUUID","resolve","env","resolve","spawn","spawn","EventEmitter","resolve","getAgentManager","agentManager","resolve","execFileAsync","promisify","execFile","z","resolve","TRPCError","pty","Anthropic","OpenAI","startedAt","existsSync","z","TRPCError","Anthropic","OpenAI","z","TRPCError","Anthropic","OpenAI","resolve","randomUUID","TRPCError","z","TRPCError","TRPCError","Anthropic","OpenAI","Anthropic","OpenAI","TRPCError","mkdir","randomUUID","join","MAX_BUFFER","resolve","publish","t","randomUUID","buildSystemPrompt","result","join","mkdir","appendFile","isSubtreeComplete","startedAt","z","randomUUID","TRPCError","randomUUID","TRPCError","z","MAX_BUFFER","resolve","z","randomUUID","TRPCError","z","randomUUID","EventEmitter","EventEmitter","randomUUID","z","resolve","z","z","z","TRPCError","z","resolve","TRPCError","z","z","resolve","z","TRPCError","readFile","readdir","stat","writeFile","mkdir","rename","rm","join","sep","dirname","z","TRPCError","mkdir","dirname","sep","readdir","join","stat","readFile","writeFile","rename","rm","z","TRPCError","readFile","writeFile","rename","mkdir","chmod","join","FILENAME","join","readFile","mkdir","writeFile","rename","chmod","randomUUID","randomUUID","randomBytes","readFile","writeFile","chmod","stat","rename","join","TRPCError","z","chmod","stat","join","join","stat","chmod","writeFile","join","randomBytes","createCipheriv","createDecipheriv","randomUUID","readFile","writeFile","rename","mkdir","access","readdir","join","encryptValue","randomBytes","createCipheriv","createDecipheriv","readFile","writeFile","rename","resolve","join","access","mkdir","readdir","randomUUID","env","join","stat","ENCRYPTED_KEY_FILENAME","VERIFY_FILENAME","stat","join","existsSync","mkdir","existsSync","mkdir","resolve","randomBytes","resolvePath","resolve","env","resolvePath","resolve"]}
|