@runeya/runeya 2.0.94 → 2.0.95
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 +22 -1
- package/agent/index.js.map +1 -1
- package/agent-manager-QQPKKLKY.js +8 -0
- package/chat-LPMGV2VS.js +18 -0
- package/chat-LPMGV2VS.js.map +1 -0
- package/chunk-3MJLS5UY.js +1944 -0
- package/chunk-3MJLS5UY.js.map +1 -0
- package/chunk-72LQC3YC.js +152 -0
- package/chunk-72LQC3YC.js.map +1 -0
- package/{chunk-4PQXBTV6.js → chunk-HX3ZIWHM.js} +82 -1959
- package/chunk-HX3ZIWHM.js.map +1 -0
- package/chunk-MD3VW4HQ.js +160 -0
- package/chunk-MD3VW4HQ.js.map +1 -0
- package/chunk-R23UUB5R.js +7285 -0
- package/chunk-R23UUB5R.js.map +1 -0
- package/chunk-WAC56HS4.js +1842 -0
- package/chunk-WAC56HS4.js.map +1 -0
- package/codex-thread-db-LE5FYDDA.js +27 -0
- package/codex-thread-db-LE5FYDDA.js.map +1 -0
- package/companion-VPYVGTRU.js +42 -0
- package/companion-VPYVGTRU.js.map +1 -0
- package/index.js +1 -1
- package/package.json +1 -1
- package/settings-manager-6FKHBLIV.js +8 -0
- package/settings-manager-6FKHBLIV.js.map +1 -0
- package/src-NEPDGULO.js +10087 -0
- package/src-NEPDGULO.js.map +1 -0
- package/web/assets/AgentScalarChatInterface.vue-DCnwgzWk.js +13 -0
- package/web/assets/AgentTerminalPage-D6iEzvyz.js +1 -0
- package/web/assets/AiChatPage-DDr9XEv8.js +1 -0
- package/web/assets/AppLayout-B2mreJVA.js +1 -0
- package/web/assets/{AppLayout-Sk3Qnkr-.css → AppLayout-nrP0jOZ1.css} +1 -1
- package/web/assets/AuditPage-CSPHdf0m.js +1 -0
- package/web/assets/CloudAccountPage-BAkTRH4E.js +1 -0
- package/web/assets/CloudAccountPage-C35O8Pcb.js +1 -0
- package/web/assets/CloudMessagingPage-5KYELXQI.js +2 -0
- package/web/assets/DashboardPage-Dl9Sg1av.js +1 -0
- package/web/assets/DirectoryPickerDialog-DLL3-GoW.js +1 -0
- package/web/assets/{EditorIcon-CdvuLNAP.js → EditorIcon-CzgSjXLk.js} +2 -2
- package/web/assets/{EnvironmentForm-BiWvLVax.js → EnvironmentForm-DmdDIJHv.js} +2 -2
- package/web/assets/EnvironmentFormPage-CV7Uq6Ah.js +1 -0
- package/web/assets/EnvironmentListPage-Cfo9RA_g.js +1 -0
- package/web/assets/KanbanBoardPage-DL1WwMBP.js +4 -0
- package/web/assets/KanbanListPage-CSAnUfp3.js +1 -0
- package/web/assets/LaunchProjectPage-vNUoulGP.js +1 -0
- package/web/assets/LaunchServicesPage-CkWZxZ-v.js +1 -0
- package/web/assets/LogViewer-CW-bBjZF.js +3 -0
- package/web/assets/OrgKeyPrompt-CHoMbQhn.js +1 -0
- package/web/assets/ProcessControls-WS6BjS5H.js +1 -0
- package/web/assets/ProcessDetailPage-DEvZSNER.js +1 -0
- package/web/assets/{ProcessMetrics-_FGC-0hm.js → ProcessMetrics-DmhwoKrE.js} +2 -2
- package/web/assets/ProjectDetailPage-DanRrWb4.js +1 -0
- package/web/assets/ProjectListPage--l9HsQ9u.js +1 -0
- package/web/assets/RandomJobTestPage-BMatxc2G.js +2 -0
- package/web/assets/ScenarioEditorPage-D_rJyudb.js +14 -0
- package/web/assets/SendToChatDialog-D-pDvIjD.js +1 -0
- package/web/assets/ServiceControlsBar-BSU25sZZ.js +1 -0
- package/web/assets/ServiceDetailPage-B1oRlnId.js +2 -0
- package/web/assets/ServiceFormPage-D-DmI0fF.js +1 -0
- package/web/assets/SettingsPage-Bi72zdhb.js +2063 -0
- package/web/assets/{SettingsPage-CX1EAjNK.css → SettingsPage-D6-jpORY.css} +1 -1
- package/web/assets/UnlockPage-BtunlGnX.js +1 -0
- package/web/assets/VariablesTable-D3HpHlKY.js +1 -0
- package/web/assets/VaultMigrationPage-DrrFR1I-.js +1 -0
- package/web/assets/VersionBadge-DqcS34oJ.js +1 -0
- package/web/assets/WikiPage-BH8A-IB_.js +1 -0
- package/web/assets/WikiView-BasNZv2A.js +1 -0
- package/web/assets/add-scalar-classes-_PYrgVvq.js +387 -0
- package/web/assets/auth-errors-CwswzwYV.js +1 -0
- package/web/assets/{autocomplete-tNXsUW-e.js → autocomplete-B-t_B26t.js} +3 -3
- package/web/assets/{basic-shape-diamond.svg-BgNul67K.js → basic-shape-diamond.svg-BFWFQIZl.js} +1 -1
- package/web/assets/{basic-shape-hexagon.svg-CILNnZwG.js → basic-shape-hexagon.svg-CXsvZPky.js} +1 -1
- package/web/assets/{basic-shape-primary-circle-ellipse-round.svg-OXklrBAn.js → basic-shape-primary-circle-ellipse-round.svg-BVg6oDS7.js} +1 -1
- package/web/assets/{basic-shape-primary-square-rectangle.svg-DYF4zyUj.js → basic-shape-primary-square-rectangle.svg-jiLWQSQV.js} +1 -1
- package/web/assets/{basic-shape-shield.svg-CQbzQswT.js → basic-shape-shield.svg-CEybfnew.js} +1 -1
- package/web/assets/{browser-CDtVZzm0.js → browser-BfO6Jws3.js} +1 -1
- package/web/assets/{browser-CdTGBSDI.js → browser-C7Qh0u0N.js} +1 -1
- package/web/assets/card-CWgnvlKH.js +32 -0
- package/web/assets/{checkbox-CTopTVtp.js → checkbox-CKzrAJQv.js} +3 -3
- package/web/assets/{chip-Cw38kJ50.js → chip-Bu5HllmO.js} +2 -2
- package/web/assets/{client-Bjn9AL4v.js → client-CM-a2QU7.js} +2 -2
- package/web/assets/cloud-chat.store-Cjbzzy1s.js +1 -0
- package/web/assets/cloud-session-Bs6siQ-Y.js +1 -0
- package/web/assets/column-pXrOxKc1.js +907 -0
- package/web/assets/{computer-device-desktop-monitor.svg-ByBKx1CQ.js → computer-device-desktop-monitor.svg-DO-9EDqA.js} +1 -1
- package/web/assets/{computer-device-desktop.svg-BPvzT4sF.js → computer-device-desktop.svg-U_EIk7jo.js} +1 -1
- package/web/assets/{computer-device-laptop.svg-saGCSB2c.js → computer-device-laptop.svg-nvbz6sjk.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-android-samsung-back.svg-Bo-eisU4.js → computer-device-mobile-phone-android-samsung-back.svg-Cs34LunN.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-android-samsung.svg-Bavaieis.js → computer-device-mobile-phone-android-samsung.svg-CDJgG-4L.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-iphone-x-back.svg-BQK9BRXi.js → computer-device-mobile-phone-iphone-x-back.svg-Du0pDh9L.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-iphone-x.svg-C24hCDuI.js → computer-device-mobile-phone-iphone-x.svg-CUgXFf2r.js} +1 -1
- package/web/assets/{computer-device-mobile-tablet-touch.svg-CUHV3zSo.js → computer-device-mobile-tablet-touch.svg-CKdx-iUf.js} +1 -1
- package/web/assets/{computer-device-mobile-tablet.svg-C8SRYMmI.js → computer-device-mobile-tablet.svg-BTvPzs5h.js} +1 -1
- package/web/assets/{computer-device-network-ethernet-cat6.svg-Ds4kUid3.js → computer-device-network-ethernet-cat6.svg-Cway8Bfw.js} +1 -1
- package/web/assets/{computer-device-network-lan-www.svg-BwIieS6h.js → computer-device-network-lan-www.svg-iuTZVSKE.js} +1 -1
- package/web/assets/{computer-device-network-wifi-connection.svg-Q7Mxb3eP.js → computer-device-network-wifi-connection.svg-DEemVGZq.js} +1 -1
- package/web/assets/{computer-device-network-wifi-router.svg-B0PMuY1x.js → computer-device-network-wifi-router.svg-BH2ASeRD.js} +1 -1
- package/web/assets/{cssMode-8lAGHoa8.js → cssMode-BHBdzmoS.js} +1 -1
- package/web/assets/{divider-DRKb8XBY.js → divider-kwmULX2U.js} +2 -2
- package/web/assets/{docx-preview-K0JOmyAw.js → docx-preview-CxXKUxi7.js} +1 -1
- package/web/assets/{ecology-science-erlenmeyer-flask.svg-D5wbPwU2.js → ecology-science-erlenmeyer-flask.svg-9yLzulSu.js} +1 -1
- package/web/assets/{fieldset-jU8x6yyO.js → fieldset-DE0sJS29.js} +2 -2
- package/web/assets/{freemarker2-BmTZDOK9.js → freemarker2-CpcoAmNk.js} +1 -1
- package/web/assets/{handlebars-DM-mBhq3.js → handlebars-D6DR-MoZ.js} +1 -1
- package/web/assets/{html-BohxI4Ke.js → html-Dx3QwrZR.js} +1 -1
- package/web/assets/{htmlMode-vqRVK3v5.js → htmlMode-KSJ_gFzK.js} +1 -1
- package/web/assets/{image-flash-lightning.svg-s-LoyOp-.js → image-flash-lightning.svg-O9m-H64P.js} +1 -1
- package/web/assets/{image-picture-flower.svg-CofKZT5Q.js → image-picture-flower.svg--rWVVuqu.js} +1 -1
- package/web/assets/{index-Da38OOd8.css → index-B4UWj2Kz.css} +1 -1
- package/web/assets/{index-DHr5P6pq.js → index-pLefgbhx.js} +287 -287
- package/web/assets/{interface-alert-exclamation-diamond.svg-C4C4i4oQ.js → interface-alert-exclamation-diamond.svg-CVeV0ecY.js} +1 -1
- package/web/assets/{interface-alert-exclamation-triangle-warning.svg-C-ogsTXk.js → interface-alert-exclamation-triangle-warning.svg-MIboYRzH.js} +1 -1
- package/web/assets/{interface-alert-information-circle.svg-BFpBDkj5.js → interface-alert-information-circle.svg-BlkHMxfH.js} +1 -1
- package/web/assets/{interface-award-crown.svg-DfHdQ8rJ.js → interface-award-crown.svg-C_Z3sLuP.js} +1 -1
- package/web/assets/{interface-bookmark.svg-qCQ3v5rM.js → interface-bookmark-tag.svg-ClOZOhfV.js} +1 -1
- package/web/assets/{interface-bookmark-tag.svg-DkfXcRMe.js → interface-bookmark.svg-CVpTNe3u.js} +1 -1
- package/web/assets/{interface-calendar-date-one.svg-D2ssTK7X.js → interface-calendar-date-one.svg-BvG92AQi.js} +1 -1
- package/web/assets/{interface-content-book-open-pages.svg-CH1BmaVm.js → interface-content-book-open-pages.svg-aXXXkj7d.js} +1 -1
- package/web/assets/{interface-content-book-page.svg-BU6m1d9-.js → interface-content-book-page.svg-BE0nQJw_.js} +1 -1
- package/web/assets/{interface-content-file.svg-DbsUtWTI.js → interface-content-file.svg-DYonyE7J.js} +1 -1
- package/web/assets/{interface-content-folder.svg-8IvlkKzB.js → interface-content-folder.svg-DKc7vKrm.js} +1 -1
- package/web/assets/interface-content-folder.svg-FcNZvOjy.js +1 -0
- package/web/assets/{interface-copy-clipboard.svg-D8ev9OtX.js → interface-copy-clipboard.svg-sAixmHqz.js} +1 -1
- package/web/assets/{interface-edit-attachment.svg-dl-nfI3P.js → interface-edit-attachment.svg-DsSzCN6U.js} +1 -1
- package/web/assets/{interface-edit-binocular.svg-Box_OuXH.js → interface-edit-binocular.svg-Bheco9Gv.js} +1 -1
- package/web/assets/{interface-edit-magic-wand.svg-DIhMw--x.js → interface-edit-magic-wand.svg-C73TY2iI.js} +1 -1
- package/web/assets/{interface-edit-tool-paint-roller.svg-COUefijc.js → interface-edit-tool-paint-roller.svg-D2OSqY3g.js} +1 -1
- package/web/assets/{interface-edit-tool-pencil.svg-BNmSspcl.js → interface-edit-tool-pencil.svg-CdY316cw.js} +1 -1
- package/web/assets/{interface-favorite-award.svg-Cy-XeB8N.js → interface-favorite-award.svg-DfA-EhHI.js} +1 -1
- package/web/assets/{interface-favorite-flag.svg-BVBisei8.js → interface-favorite-flag.svg-BnmSaveE.js} +1 -1
- package/web/assets/{interface-favorite-heart.svg-BkVO2jBo.js → interface-favorite-heart.svg-28i7lMzG.js} +1 -1
- package/web/assets/{interface-favorite-star.svg-Bxe8dqRi.js → interface-favorite-star.svg-u8xOEB4S.js} +1 -1
- package/web/assets/{interface-favorite-stars-sparkles.svg-MkrYfhIz.js → interface-favorite-stars-sparkles.svg-D5UHf8ar.js} +1 -1
- package/web/assets/{interface-hierarchy-flowchart.svg-De7TQhr3.js → interface-hierarchy-flowchart.svg-BmjWTh4K.js} +1 -1
- package/web/assets/{interface-home-house.svg-D_qOil1N.js → interface-home-house.svg-DJ5Ae65N.js} +1 -1
- package/web/assets/{interface-hyperlink.svg-5S7ugTcP.js → interface-hyperlink.svg-HdHKY_g6.js} +1 -1
- package/web/assets/{interface-lighting-brightness.svg-vJA95mbx.js → interface-lighting-brightness.svg-BDELfqMb.js} +1 -1
- package/web/assets/{interface-lock-closed.svg-DVL32yBG.js → interface-lock-closed.svg-BcDwDHkS.js} +1 -1
- package/web/assets/{interface-lock-open-unlock.svg-C7DBYFPn.js → interface-lock-open-unlock.svg-DNESCRC1.js} +1 -1
- package/web/assets/{interface-login-key.svg-CEq51fI1.js → interface-login-key.svg-BOEot3yk.js} +1 -1
- package/web/assets/{interface-search.svg-CkP-JMXm.js → interface-search.svg-CFsy7ant.js} +1 -1
- package/web/assets/{interface-setting-cog.svg-CgR9wxJN.js → interface-setting-cog.svg-B7Zk0iyr.js} +1 -1
- package/web/assets/{interface-share-megaphone-bullhorn.svg-C_VIGsI0.js → interface-share-megaphone-bullhorn.svg-DvG0IjMM.js} +1 -1
- package/web/assets/{interface-share-rocket.svg-aseIyfXq.js → interface-share-rocket.svg-gvaeTB8G.js} +1 -1
- package/web/assets/{interface-share-satellite.svg-CzkX6PJ2.js → interface-share-satellite.svg-B5pXJ0kU.js} +1 -1
- package/web/assets/{interface-share-space-ship.svg-Df1jdZi5.js → interface-share-space-ship.svg-B0k0J-VQ.js} +1 -1
- package/web/assets/{interface-share.svg-CioS2p8V.js → interface-share.svg-ZDsCvjRe.js} +1 -1
- package/web/assets/{interface-signal-square.svg-VUtTXd8G.js → interface-signal-square.svg-DBkJ1ire.js} +1 -1
- package/web/assets/{interface-time-clock-circle.svg-DWh2OWyC.js → interface-time-clock-circle.svg-BheUirew.js} +1 -1
- package/web/assets/{interface-time-hour-glass.svg-BCqCfi9r.js → interface-time-hour-glass.svg-iORrebF8.js} +1 -1
- package/web/assets/{interface-users-multiple.svg-Edac3LOs.js → interface-users-multiple.svg-DMqedSUQ.js} +1 -1
- package/web/assets/{interface-weather-moon.svg-BrK0lmKX.js → interface-weather-moon.svg-DyPBHRw4.js} +1 -1
- package/web/assets/{javascript-ByDc_p54.js → javascript-B1Y6a5s6.js} +1 -1
- package/web/assets/{jsonMode-Cm2EOOd4.js → jsonMode-Vj2pUgcF.js} +2 -2
- package/web/assets/{liquid-z9Tc1tTM.js → liquid-lb0ImGEW.js} +1 -1
- package/web/assets/{lspLanguageFeatures-D6O0oAJj.js → lspLanguageFeatures-sh8ggL5N.js} +3 -3
- package/web/assets/{mail-chat-bubble-square.svg-obHuGV3I.js → mail-chat-bubble-square.svg-D_Lx6uBc.js} +1 -1
- package/web/assets/{mail-send-email-paper-airplane.svg-I-JVbCkD.js → mail-send-email-paper-airplane.svg-B6FGKBZu.js} +1 -1
- package/web/assets/{mail-send-envelope.svg-CcYcXCe5.js → mail-send-envelope.svg-Dtm4h_xw.js} +1 -1
- package/web/assets/{mdx-B8bePw34.js → mdx-BbFPcqiD.js} +1 -1
- package/web/assets/{minus-k3R4JOtO.js → minus-Bxw18Xk6.js} +2 -2
- package/web/assets/modal-D-InjkVP.js +1 -0
- package/web/assets/modal-DLY8nKW-.js +5 -0
- package/web/assets/{money-cashier-receipt.svg-BIKxMBIH.js → money-cashier-receipt.svg-VpEb8Ewv.js} +1 -1
- package/web/assets/{money-currency-dollar-pay.svg-B-HfkTCE.js → money-currency-dollar-pay.svg-vo8FP9z4.js} +1 -1
- package/web/assets/{money-graph-arrow-increase.svg-CnXoTtSD.js → money-graph-arrow-increase.svg-CNcLQGOf.js} +1 -1
- package/web/assets/{money-graph-bar-chart-increase.svg-Dt7ly9Tz.js → money-graph-bar-chart-increase.svg-BHAccBVA.js} +1 -1
- package/web/assets/multiselect-Crs0miOE.js +251 -0
- package/web/assets/{nature-ecology-leaf.svg-TjKZfobq.js → nature-ecology-leaf.svg-0y4pBUlD.js} +1 -1
- package/web/assets/{password-dyrMCyHO.js → password-TyT4zuky.js} +4 -4
- package/web/assets/{phone-telephone.svg-CCMqAIP_.js → phone-telephone.svg-BdWhV2vz.js} +1 -1
- package/web/assets/{plus-Dg2E4ggP.js → plus-4Z2iFfO2.js} +6 -6
- package/web/assets/process.store-DsGpeQnV.js +1 -0
- package/web/assets/{programming-bug.svg-yyshFuq4.js → programming-bug.svg-DXDJVNeQ.js} +1 -1
- package/web/assets/{programming-cloud.svg-DPyoJVZM.js → programming-cloud.svg-qWtq6fXG.js} +1 -1
- package/web/assets/{programming-computer-database-server.svg-D7pShcvh.js → programming-computer-database-server.svg-DnlJHfH5.js} +1 -1
- package/web/assets/{programming-computer-database.svg-CErKDQrw.js → programming-computer-database.svg-Bl73TDXc.js} +1 -1
- package/web/assets/{programming-module-four-layout.svg-B26pG3Bb.js → programming-module-four-layout.svg-CGkj0OdH.js} +1 -1
- package/web/assets/{programming-module-three.svg-CnoN59HX.js → programming-module-three.svg-Bsk_vaHc.js} +1 -1
- package/web/assets/{programming-module.svg-C02rn1I7.js → programming-module.svg-D0Yng9wS.js} +1 -1
- package/web/assets/{programming-script-code.svg-D0sPjoPV.js → programming-script-code.svg-DTHMCNnF.js} +1 -1
- package/web/assets/{python-1623Ut7s.js → python-HImlMuYG.js} +1 -1
- package/web/assets/{razor-CyTiWHYX.js → razor-CTFKddzv.js} +1 -1
- package/web/assets/router-DTzqrUba.js +1 -0
- package/web/assets/settings-scope-CdxhnRbI.js +1 -0
- package/web/assets/{settings.store-BPAoJA_7.js → settings.store-CZ9jrl3S.js} +1 -1
- package/web/assets/{shopping-cart.svg-Cusya5ZE.js → shopping-cart.svg-Cx50mrFm.js} +1 -1
- package/web/assets/{shopping-gift-present.svg-DuhD1jDX.js → shopping-gift-present.svg-DGOO6qNg.js} +1 -1
- package/web/assets/{shopping-shipping-box-parcel-package.svg-mUJnCOxq.js → shopping-shipping-box-parcel-package.svg-C96i4g3q.js} +1 -1
- package/web/assets/src-DRjytMUo.js +1 -0
- package/web/assets/{src-HsHwQ5rW.js → src-DzMKqnGu.js} +13 -13
- package/web/assets/{tabpanel-D-R0gqbm.js → tabpanel-BW8I76pY.js} +3 -3
- package/web/assets/{tag-new-circle.svg-DFYYOM3s.js → tag-new-circle.svg-CV5DN0Db.js} +1 -1
- package/web/assets/{toggleswitch-Bv2Y60nl.js → toggleswitch-D4Evlg2b.js} +2 -2
- package/web/assets/{travel-map-earth-globe.svg-D1KtAG5P.js → travel-map-earth-globe.svg-CWvuO_Hb.js} +1 -1
- package/web/assets/trpc-BbC62Ymt.js +1 -0
- package/web/assets/{tsMode-DarxEDX3.js → tsMode-BqKPHyIc.js} +6 -6
- package/web/assets/{typescript-Bp83QY3R.js → typescript-Bme6ns4u.js} +1 -1
- package/web/assets/useAiChatDrawer-BG8t5Thc.js +1 -0
- package/web/assets/useCloudOrg-D2LTbk-G.js +572 -0
- package/web/assets/{useProjectCatalog-ClgttEEn.js → useProjectCatalog-nlAZuu5X.js} +1 -1
- package/web/assets/{xml-CieK61bI.js → xml-zsImRVNc.js} +1 -1
- package/web/assets/{yaml-Dd4h-bcV.js → yaml-VubzWJpP.js} +1 -1
- package/web/index.html +2 -2
- package/agent-manager-3KSS7BHP.js +0 -7
- package/chunk-4PQXBTV6.js.map +0 -1
- package/src-GGPKDQGD.js +0 -18433
- package/src-GGPKDQGD.js.map +0 -1
- package/web/assets/AgentScalarChatInterface.vue-CR0iWJNr.js +0 -13
- package/web/assets/AgentTerminalPage-DZj9UulV.js +0 -1
- package/web/assets/AiChatPage-D4h76hus.js +0 -1
- package/web/assets/AppLayout-DusPXiZn.js +0 -1
- package/web/assets/AuditPage-BBEa6MYr.js +0 -1
- package/web/assets/CloudAccountPage-DKgXvPS1.js +0 -1
- package/web/assets/CloudAccountPage-DopITrxL.js +0 -1
- package/web/assets/CloudMessagingPage-BNIbysEO.js +0 -2
- package/web/assets/DashboardPage-CTGAGY7X.js +0 -1
- package/web/assets/DirectoryPickerDialog-BKI9vxkG.js +0 -1
- package/web/assets/EnvironmentFormPage-RReX9Ijr.js +0 -1
- package/web/assets/EnvironmentListPage-BW5PlOxl.js +0 -1
- package/web/assets/KanbanBoardPage-BFYgHGl0.js +0 -4
- package/web/assets/KanbanListPage-BAcgRh8Z.js +0 -1
- package/web/assets/LaunchProjectPage-CpiyvCBv.js +0 -1
- package/web/assets/LaunchServicesPage-ChEXnYIi.js +0 -1
- package/web/assets/LogViewer-iTxXl8YQ.js +0 -3
- package/web/assets/OrgKeyPrompt-KRyXRMw7.js +0 -1
- package/web/assets/ProcessControls-DynA7Ock.js +0 -1
- package/web/assets/ProcessDetailPage-BpgGTkXx.js +0 -1
- package/web/assets/ProjectDetailPage-B49_-83N.js +0 -1
- package/web/assets/ProjectListPage-CFoEPT2F.js +0 -1
- package/web/assets/RandomJobTestPage-CALSR3WS.js +0 -2
- package/web/assets/ScenarioEditorPage-DxyzCjhy.js +0 -14
- package/web/assets/SendToChatDialog-CeFdMciG.js +0 -1
- package/web/assets/ServiceControlsBar-CI1_piqu.js +0 -1
- package/web/assets/ServiceDetailPage-CVT68kTt.js +0 -2
- package/web/assets/ServiceFormPage-nLRxtrOu.js +0 -1
- package/web/assets/SettingsPage-DDYegVxd.js +0 -2063
- package/web/assets/UnlockPage-D9_ZbMR_.js +0 -1
- package/web/assets/VariablesTable-ClL6KuSo.js +0 -1
- package/web/assets/VaultMigrationPage-rc5OA9Xt.js +0 -1
- package/web/assets/VersionBadge-K5UQnfc6.js +0 -1
- package/web/assets/WikiPage-VeQCqO9Z.js +0 -1
- package/web/assets/WikiView-XCwSa_R7.js +0 -1
- package/web/assets/add-scalar-classes-CvhyJKCs.js +0 -387
- package/web/assets/auth-errors-Cmx-4mn3.js +0 -1
- package/web/assets/card-BfEdnBhU.js +0 -32
- package/web/assets/cloud-chat.store-BPoTzBeD.js +0 -1
- package/web/assets/cloud-session-D0ue5Z97.js +0 -1
- package/web/assets/column-BtLe8qbf.js +0 -907
- package/web/assets/interface-content-folder.svg-nRYFY3NY.js +0 -1
- package/web/assets/modal-CVWJd9ZI.js +0 -5
- package/web/assets/modal-Ccn3uciU.js +0 -1
- package/web/assets/multiselect-BsCXwmy0.js +0 -251
- package/web/assets/process.store-CHdSS5Et.js +0 -1
- package/web/assets/router-DWhykW-F.js +0 -1
- package/web/assets/settings-scope-9i3_Io9Z.js +0 -1
- package/web/assets/src-BiD62eGr.js +0 -1
- package/web/assets/trpc-4Nls70HO.js +0 -1
- package/web/assets/useAiChatDrawer-BYR24v6F.js +0 -1
- package/web/assets/useCloudOrg-B1BakNYp.js +0 -572
- /package/{agent-manager-3KSS7BHP.js.map → agent-manager-QQPKKLKY.js.map} +0 -0
|
@@ -0,0 +1,1944 @@
|
|
|
1
|
+
// ../server/src/config/env.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { resolve as resolvePath } from "path";
|
|
4
|
+
var serverPort = z.coerce.number().int().min(1).max(65535).default(4e3).parse(process.env.RUNEYA_HTTP_PORT);
|
|
5
|
+
var defaultAgentPort = process.env.RUNEYA_AGENT_PORT ? z.coerce.number().int().min(1).max(65535).parse(process.env.RUNEYA_AGENT_PORT) : serverPort + 1;
|
|
6
|
+
var EnvSchema = z.object({
|
|
7
|
+
RUNEYA_HTTP_PORT: z.coerce.number().int().min(1).max(65535).default(4e3),
|
|
8
|
+
RUNEYA_HOST: z.string().default("127.0.0.1"),
|
|
9
|
+
RUNEYA_AGENT_PORT: z.coerce.number().int().min(1).max(65535).default(defaultAgentPort),
|
|
10
|
+
RUNEYA_AGENT_HOST: z.string().default("127.0.0.1"),
|
|
11
|
+
RUNEYA_AGENT_BINARY_PATH: z.string().nullable().default(null),
|
|
12
|
+
RUNEYA_DATA_DIR: z.preprocess((v) => typeof v === "string" && v.length > 0 ? v : void 0, z.string().default(".runeya")),
|
|
13
|
+
// Home holding the cloud vaults (`<home>/.runeya/orgs/...`). Defaults to the
|
|
14
|
+
// user's home directory; overridden by tests so they never write to the real
|
|
15
|
+
// one, and usable to relocate the vaults on a shared machine.
|
|
16
|
+
RUNEYA_HOME: z.preprocess((v) => typeof v === "string" && v.length > 0 ? v : void 0, z.string().nullable().default(null)),
|
|
17
|
+
RUNEYA_CLOUD_URL: z.string().url().nullable().default(null),
|
|
18
|
+
// Cloud front-end (landing) URL — used by the web app for the registration /
|
|
19
|
+
// onboarding flow. Configured on the server at launch; the web fetches it.
|
|
20
|
+
RUNEYA_CLOUD_APP_URL: z.string().url().nullable().default(null),
|
|
21
|
+
RUNEYA_MODE: z.enum(["local-simple", "cloud"]).default("local-simple"),
|
|
22
|
+
RUNEYA_CORS_ORIGIN: z.string().nullable().default(null),
|
|
23
|
+
RUNEYA_LAN_PROXY: z.preprocess((v) => v === "true" || v === "1", z.boolean()).default(false),
|
|
24
|
+
// Set by the CLI when it was started from a desktop launcher rather than a
|
|
25
|
+
// terminal. The web app surfaces it so the user knows which Runeya they are
|
|
26
|
+
// looking at when several are running.
|
|
27
|
+
RUNEYA_FROM_DESKTOP: z.preprocess((v) => v === "true" || v === "1", z.boolean()).default(false),
|
|
28
|
+
// Label shown for this machine in the cloud's "linked machines" screen.
|
|
29
|
+
// Defaults to the hostname (see `getDeviceName`); set it explicitly when a
|
|
30
|
+
// single host runs several instances and you want to tell them apart.
|
|
31
|
+
RUNEYA_DEVICE_NAME: z.preprocess(
|
|
32
|
+
(v) => typeof v === "string" && v.trim().length > 0 ? v.trim() : void 0,
|
|
33
|
+
z.string().max(64).nullable().default(null)
|
|
34
|
+
)
|
|
35
|
+
}).transform((data) => ({
|
|
36
|
+
...data,
|
|
37
|
+
// Short aliases used throughout the server code
|
|
38
|
+
PORT: data.RUNEYA_HTTP_PORT,
|
|
39
|
+
HOST: data.RUNEYA_HOST,
|
|
40
|
+
MODE: data.RUNEYA_MODE,
|
|
41
|
+
/**
|
|
42
|
+
* Absolute from the start, resolved once against the launch directory.
|
|
43
|
+
*
|
|
44
|
+
* It defaults to a relative `.runeya`, and every caller used to re-resolve it
|
|
45
|
+
* against whatever the process's cwd happened to be. A vault that moves when
|
|
46
|
+
* the process changes directory is a vault that can be silently written to the
|
|
47
|
+
* wrong place — so the answer is fixed here, at boot, and never recomputed.
|
|
48
|
+
*/
|
|
49
|
+
DATA_DIR: resolvePath(data.RUNEYA_DATA_DIR),
|
|
50
|
+
HOME_DIR: data.RUNEYA_HOME,
|
|
51
|
+
CLOUD_URL: data.RUNEYA_CLOUD_URL,
|
|
52
|
+
CLOUD_APP_URL: data.RUNEYA_CLOUD_APP_URL,
|
|
53
|
+
CORS_ORIGIN: data.RUNEYA_CORS_ORIGIN,
|
|
54
|
+
AGENT_BINARY_PATH: data.RUNEYA_AGENT_BINARY_PATH,
|
|
55
|
+
DEVICE_NAME: data.RUNEYA_DEVICE_NAME,
|
|
56
|
+
FROM_DESKTOP: data.RUNEYA_FROM_DESKTOP
|
|
57
|
+
}));
|
|
58
|
+
var env = EnvSchema.parse(process.env);
|
|
59
|
+
|
|
60
|
+
// ../server/src/services/vault-resolver.ts
|
|
61
|
+
import { join, sep } from "path";
|
|
62
|
+
import { homedir } from "os";
|
|
63
|
+
import { readdir, mkdir, access, readFile, writeFile, unlink } from "fs/promises";
|
|
64
|
+
import { existsSync } from "fs";
|
|
65
|
+
var SAFE_ID = /^[A-Za-z0-9._-]{1,128}$/;
|
|
66
|
+
function assertSafeId(kind, id) {
|
|
67
|
+
if (!SAFE_ID.test(id) || id === "." || id === "..") {
|
|
68
|
+
throw new Error(`Invalid ${kind} id for a vault path: ${JSON.stringify(id)}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function machineRoot() {
|
|
72
|
+
const override = process.env["RUNEYA_HOME"];
|
|
73
|
+
return join(override && override.length > 0 ? override : homedir(), ".runeya");
|
|
74
|
+
}
|
|
75
|
+
function localVaultRoot() {
|
|
76
|
+
return env.DATA_DIR;
|
|
77
|
+
}
|
|
78
|
+
function orgVaultRoot(orgId) {
|
|
79
|
+
assertSafeId("organization", orgId);
|
|
80
|
+
return join(machineRoot(), "orgs", orgId);
|
|
81
|
+
}
|
|
82
|
+
function projectVaultRoot(orgId, projectId) {
|
|
83
|
+
assertSafeId("project", projectId);
|
|
84
|
+
return join(orgVaultRoot(orgId), "projects", projectId);
|
|
85
|
+
}
|
|
86
|
+
function orgIdOfRoot(root) {
|
|
87
|
+
const marker = join(machineRoot(), "orgs") + sep;
|
|
88
|
+
if (!root.startsWith(marker)) return null;
|
|
89
|
+
const [orgId] = root.slice(marker.length).split(sep);
|
|
90
|
+
return orgId && SAFE_ID.test(orgId) ? orgId : null;
|
|
91
|
+
}
|
|
92
|
+
function vaultIdOfRoot(root) {
|
|
93
|
+
return orgIdOfRoot(root) ?? void 0;
|
|
94
|
+
}
|
|
95
|
+
function vaultFor(target) {
|
|
96
|
+
if (!target.orgId) return { root: localVaultRoot() };
|
|
97
|
+
return { root: projectVaultRoot(target.orgId, target.id) };
|
|
98
|
+
}
|
|
99
|
+
var ORG_CLOUD_FILE = "cloud.json";
|
|
100
|
+
async function stampOrgCloud(orgId, cloudUrl, name) {
|
|
101
|
+
const root = orgVaultRoot(orgId);
|
|
102
|
+
await mkdir(root, { recursive: true });
|
|
103
|
+
const known = name ?? (await readOrgNames())[orgId];
|
|
104
|
+
const stamp = known ? { cloudUrl, name: known } : { cloudUrl };
|
|
105
|
+
await writeFile(join(root, ORG_CLOUD_FILE), JSON.stringify(stamp, null, 2), "utf-8");
|
|
106
|
+
}
|
|
107
|
+
async function rememberOrgName(orgId, name) {
|
|
108
|
+
const root = orgVaultRoot(orgId);
|
|
109
|
+
if (!existsSync(root)) return;
|
|
110
|
+
const file = join(root, ORG_CLOUD_FILE);
|
|
111
|
+
let stamp = {};
|
|
112
|
+
try {
|
|
113
|
+
stamp = JSON.parse(await readFile(file, "utf-8"));
|
|
114
|
+
} catch {
|
|
115
|
+
}
|
|
116
|
+
if (stamp["name"] === name) return;
|
|
117
|
+
await writeFile(file, JSON.stringify({ ...stamp, name }, null, 2), "utf-8");
|
|
118
|
+
}
|
|
119
|
+
async function readOrgNames() {
|
|
120
|
+
const out = {};
|
|
121
|
+
for (const orgId of await listOrgVaults()) {
|
|
122
|
+
try {
|
|
123
|
+
const raw = await readFile(join(orgVaultRoot(orgId), ORG_CLOUD_FILE), "utf-8");
|
|
124
|
+
const name = JSON.parse(raw).name;
|
|
125
|
+
if (typeof name === "string" && name) out[orgId] = name;
|
|
126
|
+
} catch {
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return out;
|
|
130
|
+
}
|
|
131
|
+
var ORG_LOGO_FILE = "logo.json";
|
|
132
|
+
var LOGO_TYPES = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/webp", "image/gif"]);
|
|
133
|
+
async function rememberOrgLogo(orgId, contentType, base64) {
|
|
134
|
+
if (!LOGO_TYPES.has(contentType)) return;
|
|
135
|
+
const root = orgVaultRoot(orgId);
|
|
136
|
+
const stored = { contentType, base64, fetchedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
137
|
+
await mkdir(root, { recursive: true });
|
|
138
|
+
await writeFile(join(root, ORG_LOGO_FILE), JSON.stringify(stored), "utf-8");
|
|
139
|
+
}
|
|
140
|
+
async function forgetOrgLogo(orgId) {
|
|
141
|
+
try {
|
|
142
|
+
await unlink(join(orgVaultRoot(orgId), ORG_LOGO_FILE));
|
|
143
|
+
} catch {
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
async function readOrgLogos() {
|
|
147
|
+
const out = {};
|
|
148
|
+
for (const orgId of await listOrgVaults()) {
|
|
149
|
+
try {
|
|
150
|
+
const raw = await readFile(join(orgVaultRoot(orgId), ORG_LOGO_FILE), "utf-8");
|
|
151
|
+
const { contentType, base64 } = JSON.parse(raw);
|
|
152
|
+
if (typeof contentType !== "string" || !LOGO_TYPES.has(contentType)) continue;
|
|
153
|
+
if (typeof base64 !== "string" || !base64) continue;
|
|
154
|
+
out[orgId] = `data:${contentType};base64,${base64}`;
|
|
155
|
+
} catch {
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return out;
|
|
159
|
+
}
|
|
160
|
+
async function readOrgClouds() {
|
|
161
|
+
const orgsDir = join(machineRoot(), "orgs");
|
|
162
|
+
const out = {};
|
|
163
|
+
let orgIds;
|
|
164
|
+
try {
|
|
165
|
+
orgIds = (await readdir(orgsDir, { withFileTypes: true })).filter((e) => e.isDirectory() && SAFE_ID.test(e.name)).map((e) => e.name);
|
|
166
|
+
} catch {
|
|
167
|
+
return out;
|
|
168
|
+
}
|
|
169
|
+
for (const orgId of orgIds) {
|
|
170
|
+
try {
|
|
171
|
+
const raw = await readFile(join(orgsDir, orgId, ORG_CLOUD_FILE), "utf-8");
|
|
172
|
+
const url = JSON.parse(raw).cloudUrl;
|
|
173
|
+
if (typeof url === "string" && url) out[orgId] = url;
|
|
174
|
+
} catch {
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return out;
|
|
178
|
+
}
|
|
179
|
+
async function listOrgVaults() {
|
|
180
|
+
const orgsDir = join(machineRoot(), "orgs");
|
|
181
|
+
try {
|
|
182
|
+
return (await readdir(orgsDir, { withFileTypes: true })).filter((e) => e.isDirectory() && SAFE_ID.test(e.name)).map((e) => e.name);
|
|
183
|
+
} catch {
|
|
184
|
+
return [];
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
async function listCloudVaults() {
|
|
188
|
+
const orgsDir = join(machineRoot(), "orgs");
|
|
189
|
+
const found = [];
|
|
190
|
+
let orgIds;
|
|
191
|
+
try {
|
|
192
|
+
orgIds = (await readdir(orgsDir, { withFileTypes: true })).filter((e) => e.isDirectory() && SAFE_ID.test(e.name)).map((e) => e.name);
|
|
193
|
+
} catch {
|
|
194
|
+
return found;
|
|
195
|
+
}
|
|
196
|
+
for (const orgId of orgIds) {
|
|
197
|
+
const projectsDir = join(orgsDir, orgId, "projects");
|
|
198
|
+
try {
|
|
199
|
+
for (const entry of await readdir(projectsDir, { withFileTypes: true })) {
|
|
200
|
+
if (!entry.isDirectory() || !SAFE_ID.test(entry.name)) continue;
|
|
201
|
+
const root = join(projectsDir, entry.name);
|
|
202
|
+
if (!await access(join(root, "project.json")).then(() => true, () => false)) continue;
|
|
203
|
+
found.push({ orgId, projectId: entry.name, root });
|
|
204
|
+
}
|
|
205
|
+
} catch {
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return found;
|
|
209
|
+
}
|
|
210
|
+
async function allVaultRoots() {
|
|
211
|
+
const cloud = await listCloudVaults();
|
|
212
|
+
return [localVaultRoot(), ...cloud.map((v) => v.root)];
|
|
213
|
+
}
|
|
214
|
+
function machineFilePath(filename) {
|
|
215
|
+
return join(machineRoot(), filename);
|
|
216
|
+
}
|
|
217
|
+
async function keyedFilePath(filename) {
|
|
218
|
+
return join(await keyRoot(), filename);
|
|
219
|
+
}
|
|
220
|
+
function legacyMachineFilePath(filename) {
|
|
221
|
+
return join(localVaultRoot(), filename);
|
|
222
|
+
}
|
|
223
|
+
async function ensureLocalVault() {
|
|
224
|
+
const root = localVaultRoot();
|
|
225
|
+
await mkdir(root, { recursive: true });
|
|
226
|
+
return root;
|
|
227
|
+
}
|
|
228
|
+
var KEY_FILES = [".encryption.key.enc", ".runeya-verify"];
|
|
229
|
+
var keyRootPromise = null;
|
|
230
|
+
async function holdsKey(root) {
|
|
231
|
+
for (const filename of KEY_FILES) {
|
|
232
|
+
try {
|
|
233
|
+
await access(join(root, filename));
|
|
234
|
+
return true;
|
|
235
|
+
} catch {
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
function keyRoot() {
|
|
241
|
+
keyRootPromise ??= (async () => {
|
|
242
|
+
if (await holdsKey(machineRoot())) return machineRoot();
|
|
243
|
+
return await holdsKey(localVaultRoot()) ? localVaultRoot() : machineRoot();
|
|
244
|
+
})();
|
|
245
|
+
return keyRootPromise;
|
|
246
|
+
}
|
|
247
|
+
async function legacyVaultRoot() {
|
|
248
|
+
const local = localVaultRoot();
|
|
249
|
+
if (await keyRoot() === local) return null;
|
|
250
|
+
return await holdsKey(local) ? local : null;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// ../../packages/shared/src/schemas/settings.schema.ts
|
|
254
|
+
import { z as z3 } from "zod";
|
|
255
|
+
|
|
256
|
+
// ../../packages/shared/src/schemas/scenario.schema.ts
|
|
257
|
+
import { z as z2 } from "zod";
|
|
258
|
+
var PositionSchema = z2.object({
|
|
259
|
+
x: z2.number(),
|
|
260
|
+
y: z2.number()
|
|
261
|
+
});
|
|
262
|
+
var ScenarioGroupSchema = z2.object({
|
|
263
|
+
id: z2.string().min(1).max(128),
|
|
264
|
+
name: z2.string().min(1).max(200),
|
|
265
|
+
description: z2.string().max(1e3).optional(),
|
|
266
|
+
color: z2.string().max(32).optional(),
|
|
267
|
+
position: PositionSchema.default({ x: 0, y: 0 }),
|
|
268
|
+
width: z2.number().default(300),
|
|
269
|
+
height: z2.number().default(200)
|
|
270
|
+
});
|
|
271
|
+
var ScenarioPresetRoleSchema = z2.object({
|
|
272
|
+
id: z2.string().min(1).max(64),
|
|
273
|
+
name: z2.string().min(1).max(200),
|
|
274
|
+
systemPrompt: z2.string().max(1e4).default(""),
|
|
275
|
+
prompt: z2.string().max(1e4).default("")
|
|
276
|
+
});
|
|
277
|
+
var ScenarioPresetInitialDataSchema = z2.object({
|
|
278
|
+
leaderId: z2.string().min(1).max(128),
|
|
279
|
+
groups: z2.array(z2.object({
|
|
280
|
+
id: z2.string().min(1).max(128),
|
|
281
|
+
name: z2.string().min(1).max(200),
|
|
282
|
+
description: z2.string().max(1e3).optional(),
|
|
283
|
+
color: z2.string().max(32).optional(),
|
|
284
|
+
position: z2.object({ x: z2.number(), y: z2.number() }).default({ x: 0, y: 0 }),
|
|
285
|
+
width: z2.number().default(300),
|
|
286
|
+
height: z2.number().default(200)
|
|
287
|
+
})).max(100).default([]),
|
|
288
|
+
nodes: z2.array(z2.object({
|
|
289
|
+
id: z2.string().min(1).max(128),
|
|
290
|
+
type: z2.enum(["ai", "ask"]).default("ai"),
|
|
291
|
+
parentIds: z2.array(z2.string().max(128)).default([]),
|
|
292
|
+
groupId: z2.string().max(128).nullable().default(null),
|
|
293
|
+
label: z2.string().max(240).default(""),
|
|
294
|
+
role: z2.string().max(64).default("other"),
|
|
295
|
+
prompt: z2.string().max(5e4).default(""),
|
|
296
|
+
question: z2.string().max(2e3).default(""),
|
|
297
|
+
autoGenerated: z2.boolean().default(true),
|
|
298
|
+
canAddNode: z2.boolean().default(false),
|
|
299
|
+
aiCli: z2.enum(["claude-code", "codex"]).default("claude-code"),
|
|
300
|
+
model: z2.string().max(128).default("sonnet"),
|
|
301
|
+
position: z2.object({ x: z2.number(), y: z2.number() }).default({ x: 0, y: 0 })
|
|
302
|
+
})).min(1).max(500)
|
|
303
|
+
});
|
|
304
|
+
var LocalizedStringSchema = z2.record(z2.string(), z2.string().max(100));
|
|
305
|
+
var ScenarioPresetLabelsSchema = z2.object({
|
|
306
|
+
group: LocalizedStringSchema.optional(),
|
|
307
|
+
node: LocalizedStringSchema.optional(),
|
|
308
|
+
role: LocalizedStringSchema.optional(),
|
|
309
|
+
leader: LocalizedStringSchema.optional()
|
|
310
|
+
});
|
|
311
|
+
var ScenarioPresetSchema = z2.object({
|
|
312
|
+
id: z2.string().min(1).max(128),
|
|
313
|
+
name: z2.string().min(1).max(200),
|
|
314
|
+
icon: z2.string().max(64).optional(),
|
|
315
|
+
defaultTraversalMode: z2.enum(["hierarchical", "topological"]).optional(),
|
|
316
|
+
canChangeTraversalMode: z2.boolean().default(true),
|
|
317
|
+
roles: z2.array(ScenarioPresetRoleSchema).min(1).max(100),
|
|
318
|
+
initialData: ScenarioPresetInitialDataSchema.optional(),
|
|
319
|
+
labels: ScenarioPresetLabelsSchema.optional()
|
|
320
|
+
});
|
|
321
|
+
var ScenarioNodeSchema = z2.object({
|
|
322
|
+
id: z2.string().min(1).max(128),
|
|
323
|
+
type: z2.enum(["ai", "ask"]).default("ai"),
|
|
324
|
+
parentIds: z2.array(z2.string().max(128)).default([]),
|
|
325
|
+
groupId: z2.string().max(128).nullable().default(null),
|
|
326
|
+
label: z2.string().max(240).default(""),
|
|
327
|
+
role: z2.string().max(64).default("other"),
|
|
328
|
+
prompt: z2.string().max(5e4).default(""),
|
|
329
|
+
question: z2.string().max(2e3).default(""),
|
|
330
|
+
autoGenerated: z2.boolean().default(true),
|
|
331
|
+
canAddNode: z2.boolean().default(false),
|
|
332
|
+
aiCli: z2.enum(["claude-code", "codex"]).default("claude-code"),
|
|
333
|
+
model: z2.string().max(128).default("sonnet"),
|
|
334
|
+
position: PositionSchema.default({ x: 0, y: 0 }),
|
|
335
|
+
injectParentOutputs: z2.boolean().default(false),
|
|
336
|
+
injectedAncestorIds: z2.array(z2.string().max(128)).default([])
|
|
337
|
+
});
|
|
338
|
+
var ScenarioSchema = z2.object({
|
|
339
|
+
id: z2.string().min(1).max(128),
|
|
340
|
+
name: z2.string().min(1).max(200),
|
|
341
|
+
icon: z2.string().max(64).optional(),
|
|
342
|
+
description: z2.string().max(2e3).optional(),
|
|
343
|
+
leaderId: z2.string().min(1).max(128),
|
|
344
|
+
groups: z2.array(ScenarioGroupSchema).max(100).default([]),
|
|
345
|
+
nodes: z2.array(ScenarioNodeSchema).min(1).max(500),
|
|
346
|
+
traversalMode: z2.enum(["hierarchical", "topological"]).default("hierarchical"),
|
|
347
|
+
presetId: z2.string().max(128).optional(),
|
|
348
|
+
isPublished: z2.boolean().default(false),
|
|
349
|
+
createdAt: z2.number(),
|
|
350
|
+
updatedAt: z2.number()
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
// ../../packages/shared/src/schemas/settings.schema.ts
|
|
354
|
+
var AI_PROVIDERS = ["anthropic", "openai", "mistral", "groq", "ollama"];
|
|
355
|
+
var AIProviderSchema = z3.object({
|
|
356
|
+
id: z3.string().min(1).max(128),
|
|
357
|
+
name: z3.string().min(1).max(200),
|
|
358
|
+
provider: z3.enum(AI_PROVIDERS),
|
|
359
|
+
encryptedApiKey: z3.string().max(2e3).default(""),
|
|
360
|
+
model: z3.string().max(200).optional(),
|
|
361
|
+
active: z3.boolean().default(false),
|
|
362
|
+
createdAt: z3.coerce.date(),
|
|
363
|
+
updatedAt: z3.coerce.date()
|
|
364
|
+
});
|
|
365
|
+
var JSLogParserSchema = z3.object({
|
|
366
|
+
id: z3.string().min(1).max(128),
|
|
367
|
+
name: z3.string().min(1).max(200),
|
|
368
|
+
description: z3.string().max(2e3).optional(),
|
|
369
|
+
code: z3.string().min(1).max(5e4).refine(
|
|
370
|
+
(s) => !s.includes("require(") && !s.includes("import ") && !s.includes("eval("),
|
|
371
|
+
{ message: "Code must not contain require, import, or eval patterns" }
|
|
372
|
+
),
|
|
373
|
+
enabled: z3.boolean().default(true),
|
|
374
|
+
builtin: z3.boolean().optional(),
|
|
375
|
+
createdAt: z3.coerce.date(),
|
|
376
|
+
updatedAt: z3.coerce.date()
|
|
377
|
+
});
|
|
378
|
+
var NotificationPreferencesSchema = z3.object({
|
|
379
|
+
scenario_waiting_input: z3.boolean().default(true),
|
|
380
|
+
ai_conversation_complete: z3.boolean().default(true),
|
|
381
|
+
ai_conversation_error: z3.boolean().default(true),
|
|
382
|
+
service_error_log: z3.boolean().default(true),
|
|
383
|
+
service_status_changed: z3.boolean().default(true),
|
|
384
|
+
service_health_changed: z3.boolean().default(true),
|
|
385
|
+
/** Service IDs excluded from error-log notifications */
|
|
386
|
+
service_error_log_excluded: z3.array(z3.string().max(100)).max(500).default([]),
|
|
387
|
+
/** Service IDs excluded from status-change notifications */
|
|
388
|
+
service_status_changed_excluded: z3.array(z3.string().max(100)).max(500).default([]),
|
|
389
|
+
/** Service IDs excluded from health-change notifications */
|
|
390
|
+
service_health_changed_excluded: z3.array(z3.string().max(100)).max(500).default([])
|
|
391
|
+
});
|
|
392
|
+
var CompanionSettingsSchema = z3.object({
|
|
393
|
+
/** Activer le compagnon d'office sur les conversations créées ensuite. */
|
|
394
|
+
enabledByDefault: z3.boolean().default(false),
|
|
395
|
+
/**
|
|
396
|
+
* Consignes envoyées au compagnon, à la place des nôtres.
|
|
397
|
+
*
|
|
398
|
+
* Vide — l'absence — signifie « celles de Runeya ». On ne recopie pas le
|
|
399
|
+
* texte par défaut dans le réglage : figé le jour où il est enregistré, il ne
|
|
400
|
+
* profiterait plus jamais des corrections apportées au nôtre.
|
|
401
|
+
*
|
|
402
|
+
* Rejeté au-delà de la borne plutôt que tronqué (§1) : un prompt coupé en
|
|
403
|
+
* plein milieu produirait des relectures incohérentes sans rien signaler.
|
|
404
|
+
*/
|
|
405
|
+
prompt: z3.string().max(2e4).optional()
|
|
406
|
+
});
|
|
407
|
+
var SettingsSchema = z3.object({
|
|
408
|
+
mode: z3.enum(["local-simple", "cloud"]),
|
|
409
|
+
cloudUrl: z3.string().url().max(2048).nullable().optional(),
|
|
410
|
+
logParsers: z3.array(JSLogParserSchema).max(100).default([]),
|
|
411
|
+
scenarios: z3.array(ScenarioSchema).max(100).default([]),
|
|
412
|
+
/** Absolute path to the folder where the global wiki/docs markdown files live. Optional. */
|
|
413
|
+
globalDocsPath: z3.string().max(4096).optional(),
|
|
414
|
+
/**
|
|
415
|
+
* Optionnel plutôt que défauté : un réglage absent est un réglage jamais
|
|
416
|
+
* touché, et le rendre obligatoire dans le type forcerait chaque appelant qui
|
|
417
|
+
* construit un objet de réglages à inventer une valeur.
|
|
418
|
+
*/
|
|
419
|
+
companion: CompanionSettingsSchema.optional()
|
|
420
|
+
});
|
|
421
|
+
var TraefikConfigSchema = z3.object({
|
|
422
|
+
enabled: z3.boolean().default(false),
|
|
423
|
+
acmeEmail: z3.string().email().max(256).optional(),
|
|
424
|
+
wildcardDomain: z3.string().max(253).optional(),
|
|
425
|
+
httpPort: z3.number().int().min(1).max(65535).default(80),
|
|
426
|
+
httpsPort: z3.number().int().min(1).max(65535).default(443),
|
|
427
|
+
dnsProvider: z3.string().max(64).optional(),
|
|
428
|
+
dnsCredentials: z3.record(z3.string().max(64), z3.string().max(2048)).default({}),
|
|
429
|
+
acmeStaging: z3.boolean().default(false),
|
|
430
|
+
encryptedCert: z3.string().max(65536).optional(),
|
|
431
|
+
encryptedCertKey: z3.string().max(65536).optional()
|
|
432
|
+
});
|
|
433
|
+
var SettingsPrivateSchema = z3.object({
|
|
434
|
+
aiProviders: z3.array(AIProviderSchema).max(50).default([]),
|
|
435
|
+
scenarios: z3.array(ScenarioSchema).max(100).default([]),
|
|
436
|
+
notifications: NotificationPreferencesSchema.default(() => ({
|
|
437
|
+
scenario_waiting_input: true,
|
|
438
|
+
ai_conversation_complete: true,
|
|
439
|
+
ai_conversation_error: true,
|
|
440
|
+
service_error_log: true,
|
|
441
|
+
service_status_changed: true,
|
|
442
|
+
service_health_changed: true,
|
|
443
|
+
service_error_log_excluded: [],
|
|
444
|
+
service_status_changed_excluded: [],
|
|
445
|
+
service_health_changed_excluded: []
|
|
446
|
+
})),
|
|
447
|
+
traefikConfig: TraefikConfigSchema.optional()
|
|
448
|
+
});
|
|
449
|
+
var SchemaVersionSchema = z3.object({
|
|
450
|
+
version: z3.number().int().positive(),
|
|
451
|
+
migratedAt: z3.coerce.date()
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
// ../../packages/shared/src/utils/companion-markers.ts
|
|
455
|
+
var COMPANION_RELAY_OPEN = "[RUNEYA_COMPAGNON_RESPONSE]";
|
|
456
|
+
var COMPANION_RELAY_CLOSE = "[/RUNEYA_COMPAGNON_RESPONSE]";
|
|
457
|
+
function extractCompanionRelay(raw) {
|
|
458
|
+
const text = (raw ?? "").trim();
|
|
459
|
+
const open = text.lastIndexOf(COMPANION_RELAY_OPEN);
|
|
460
|
+
if (open === -1) return null;
|
|
461
|
+
const after = text.slice(open + COMPANION_RELAY_OPEN.length);
|
|
462
|
+
const close = after.indexOf(COMPANION_RELAY_CLOSE);
|
|
463
|
+
const inner = (close === -1 ? after : after.slice(0, close)).trim();
|
|
464
|
+
return inner || null;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// ../../packages/shared/src/constants/intervals.ts
|
|
468
|
+
var AGENT_HEALTH_POLL_INTERVAL = 15e3;
|
|
469
|
+
|
|
470
|
+
// ../../packages/shared/src/constants/timeouts.ts
|
|
471
|
+
var GRACE_PERIOD = 1e4;
|
|
472
|
+
var AGENT_FETCH_TIMEOUT = 1e4;
|
|
473
|
+
var AGENT_LONG_FETCH_TIMEOUT = 6e5;
|
|
474
|
+
var AGENT_STOP_FETCH_TIMEOUT = GRACE_PERIOD + 15e3;
|
|
475
|
+
var PASSPHRASE_TIMEOUT = 3e4;
|
|
476
|
+
var WS_RECONNECT_MIN = 1e3;
|
|
477
|
+
var WS_RECONNECT_MAX = 15e3;
|
|
478
|
+
|
|
479
|
+
// ../../packages/shared/src/schemas/user.schema.ts
|
|
480
|
+
import { z as z4 } from "zod";
|
|
481
|
+
var UserSchema = z4.object({
|
|
482
|
+
id: z4.string().max(128),
|
|
483
|
+
email: z4.string().email().max(320),
|
|
484
|
+
name: z4.string().min(1).max(500),
|
|
485
|
+
avatar: z4.string().url().max(2048).nullable().optional()
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
// ../../packages/shared/src/schemas/org.schema.ts
|
|
489
|
+
import { z as z5 } from "zod";
|
|
490
|
+
var OrgSchema = z5.object({
|
|
491
|
+
id: z5.string().max(128),
|
|
492
|
+
name: z5.string().min(1).max(100),
|
|
493
|
+
slug: z5.string().min(1).max(100).regex(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/),
|
|
494
|
+
ownerId: z5.string().max(128)
|
|
495
|
+
});
|
|
496
|
+
var OrgMemberSchema = z5.object({
|
|
497
|
+
id: z5.string().max(128),
|
|
498
|
+
orgId: z5.string().max(128),
|
|
499
|
+
userId: z5.string().max(128),
|
|
500
|
+
globalRole: z5.enum(["owner", "admin", "member"]),
|
|
501
|
+
invitedAt: z5.coerce.date(),
|
|
502
|
+
joinedAt: z5.coerce.date().nullable().optional()
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
// ../../packages/shared/src/schemas/project.schema.ts
|
|
506
|
+
import { z as z6 } from "zod";
|
|
507
|
+
var ProjectSchema = z6.object({
|
|
508
|
+
id: z6.string().max(128),
|
|
509
|
+
orgId: z6.string().max(128).nullable().optional(),
|
|
510
|
+
name: z6.string().min(1).max(200),
|
|
511
|
+
description: z6.string().max(1e4).optional().default(""),
|
|
512
|
+
serviceIds: z6.array(z6.string().max(128)).max(1e4).default([]),
|
|
513
|
+
// Environment support
|
|
514
|
+
// NOTE: activeEnvironmentId is runtime-only (not persisted to JSON)
|
|
515
|
+
// It's initialized to 'local' by default at load time
|
|
516
|
+
activeEnvironmentId: z6.string().max(128).optional(),
|
|
517
|
+
environmentIds: z6.array(z6.string().max(128)).max(100).default([]),
|
|
518
|
+
// Ordre d'affichage des groupes de services dans la sidebar (noms de groupes).
|
|
519
|
+
// Les groupes absents de cette liste sont affichés après, par ordre alphabétique.
|
|
520
|
+
groupOrder: z6.array(z6.string().max(200)).max(100).default([])
|
|
521
|
+
});
|
|
522
|
+
var CreateProjectSchema = ProjectSchema.omit({ id: true }).partial().required({ name: true });
|
|
523
|
+
var UpdateProjectSchema = ProjectSchema.partial().required({ id: true });
|
|
524
|
+
|
|
525
|
+
// ../../packages/shared/src/schemas/service.schema.ts
|
|
526
|
+
import { z as z8 } from "zod";
|
|
527
|
+
|
|
528
|
+
// ../../packages/shared/src/schemas/log-source.schema.ts
|
|
529
|
+
import { z as z7 } from "zod";
|
|
530
|
+
var safePath = z7.string().min(1).max(4096).refine(
|
|
531
|
+
(p) => !p.includes("\0"),
|
|
532
|
+
{ message: "path must not contain null bytes" }
|
|
533
|
+
).refine(
|
|
534
|
+
(p) => !/(^|[/\\])\.\.([/\\]|$)/.test(p),
|
|
535
|
+
{ message: "path must not contain path-traversal sequences (..)" }
|
|
536
|
+
);
|
|
537
|
+
var ConsoleLogSourceSchema = z7.object({
|
|
538
|
+
type: z7.literal("console")
|
|
539
|
+
});
|
|
540
|
+
var FileLogSourceSchema = z7.object({
|
|
541
|
+
type: z7.literal("file"),
|
|
542
|
+
path: safePath,
|
|
543
|
+
encoding: z7.string().max(32).default("utf-8"),
|
|
544
|
+
startFromEnd: z7.boolean().default(true),
|
|
545
|
+
createIfNotExists: z7.boolean().default(false)
|
|
546
|
+
});
|
|
547
|
+
var MongoLogSourceSchema = z7.object({
|
|
548
|
+
type: z7.literal("mongo"),
|
|
549
|
+
/** @sensitive — stored encrypted (AES-256-GCM) on disk */
|
|
550
|
+
connectionString: z7.string().min(1).max(2048),
|
|
551
|
+
database: z7.string().min(1).max(256),
|
|
552
|
+
collection: z7.string().min(1).max(256),
|
|
553
|
+
filter: z7.record(z7.string(), z7.unknown()).optional(),
|
|
554
|
+
timestampField: z7.string().max(128).default("timestamp"),
|
|
555
|
+
messageField: z7.string().max(128).default("message"),
|
|
556
|
+
levelField: z7.string().max(128).optional()
|
|
557
|
+
});
|
|
558
|
+
var MySQLLogSourceSchema = z7.object({
|
|
559
|
+
type: z7.literal("mysql"),
|
|
560
|
+
host: z7.string().min(1).max(253),
|
|
561
|
+
port: z7.number().int().min(1).max(65535).default(3306),
|
|
562
|
+
user: z7.string().min(1).max(256),
|
|
563
|
+
/** @sensitive — stored encrypted (AES-256-GCM) on disk */
|
|
564
|
+
password: z7.string().max(2048),
|
|
565
|
+
database: z7.string().min(1).max(256),
|
|
566
|
+
table: z7.string().min(1).max(256),
|
|
567
|
+
query: z7.string().max(8192).optional(),
|
|
568
|
+
timestampColumn: z7.string().max(128).default("created_at"),
|
|
569
|
+
messageColumn: z7.string().max(128).default("message"),
|
|
570
|
+
levelColumn: z7.string().max(128).optional(),
|
|
571
|
+
pollIntervalMs: z7.number().int().min(500).max(6e4).default(2e3)
|
|
572
|
+
});
|
|
573
|
+
var LogSourceConfigSchema = z7.discriminatedUnion("type", [
|
|
574
|
+
ConsoleLogSourceSchema,
|
|
575
|
+
FileLogSourceSchema,
|
|
576
|
+
MongoLogSourceSchema,
|
|
577
|
+
MySQLLogSourceSchema
|
|
578
|
+
]);
|
|
579
|
+
|
|
580
|
+
// ../../packages/shared/src/schemas/service.schema.ts
|
|
581
|
+
var HealthCheckSchema = z8.object({
|
|
582
|
+
type: z8.enum(["http", "command"]).default("http"),
|
|
583
|
+
// HTTP-specific (required when type=http)
|
|
584
|
+
path: z8.string().min(1).max(500).startsWith("/").optional(),
|
|
585
|
+
method: z8.enum(["GET", "HEAD", "POST", "PUT"]).optional().default("GET"),
|
|
586
|
+
expectedStatus: z8.number().int().min(100).max(599).optional().default(200),
|
|
587
|
+
// Command-specific (required when type=command)
|
|
588
|
+
command: z8.string().min(1).max(4096).optional(),
|
|
589
|
+
// Shared
|
|
590
|
+
interval: z8.number().int().positive().default(1e3),
|
|
591
|
+
timeout: z8.number().int().positive().default(1e3),
|
|
592
|
+
retries: z8.number().int().nonnegative().default(3),
|
|
593
|
+
initialDelay: z8.number().int().nonnegative().optional().default(0)
|
|
594
|
+
}).refine(
|
|
595
|
+
(data) => data.type === "http" ? !!data.path : !!data.command,
|
|
596
|
+
{ message: "HTTP type requires path; command type requires command" }
|
|
597
|
+
);
|
|
598
|
+
var BootstrapCommandSchema = z8.object({
|
|
599
|
+
id: z8.string().min(1).max(64),
|
|
600
|
+
label: z8.string().max(200).default(""),
|
|
601
|
+
entrypoint: z8.string().max(4096).optional(),
|
|
602
|
+
command: z8.string().max(4096).default(""),
|
|
603
|
+
user: z8.string().max(256).optional()
|
|
604
|
+
});
|
|
605
|
+
var DockerConfigSchema = z8.object({
|
|
606
|
+
// Image mode (pull from registry) — mutually exclusive with build mode in UI
|
|
607
|
+
image: z8.string().min(1).max(1024).optional(),
|
|
608
|
+
// Build mode — Dockerfile stored inline in services.json
|
|
609
|
+
dockerfile: z8.string().max(65536).optional(),
|
|
610
|
+
buildContext: z8.string().max(4096).optional(),
|
|
611
|
+
buildArgs: z8.record(z8.string().max(256), z8.string().max(4096)).default({}).refine(
|
|
612
|
+
(obj) => Object.keys(obj).length <= 50,
|
|
613
|
+
{ message: "Max 50 build args" }
|
|
614
|
+
),
|
|
615
|
+
targetStage: z8.string().max(256).optional(),
|
|
616
|
+
// Runtime config
|
|
617
|
+
networkMode: z8.enum(["host", "bridge"]).default("host"),
|
|
618
|
+
ports: z8.array(z8.string().max(64)).max(100).default([]),
|
|
619
|
+
volumes: z8.array(z8.string().max(1024)).max(100).default([]),
|
|
620
|
+
mountRootpath: z8.boolean().default(false),
|
|
621
|
+
entrypoint: z8.string().max(4096).optional(),
|
|
622
|
+
command: z8.string().max(4096).optional(),
|
|
623
|
+
user: z8.string().max(256).optional(),
|
|
624
|
+
useNativeCommand: z8.boolean().default(false),
|
|
625
|
+
nativeCommandMode: z8.enum(["shared", "isolated"]).default("isolated"),
|
|
626
|
+
nativeShell: z8.string().max(256).default("sh"),
|
|
627
|
+
bootstrapCommands: z8.array(BootstrapCommandSchema).max(20).default([])
|
|
628
|
+
});
|
|
629
|
+
var RestartStrategySchema = z8.enum(["none", "on-failure", "always", "unless-stopped"]).default("none");
|
|
630
|
+
var ServiceShortcutSchema = z8.object({
|
|
631
|
+
id: z8.string().min(1).max(64),
|
|
632
|
+
label: z8.string().max(200).default(""),
|
|
633
|
+
command: z8.string().max(4096).default(""),
|
|
634
|
+
cwd: z8.string().max(4096).optional()
|
|
635
|
+
});
|
|
636
|
+
var ServiceCommandSchema = z8.object({
|
|
637
|
+
id: z8.string().min(1).max(64),
|
|
638
|
+
label: z8.string().max(200).default(""),
|
|
639
|
+
command: z8.string().max(4096).default(""),
|
|
640
|
+
cwd: z8.string().max(4096).optional(),
|
|
641
|
+
shell: z8.boolean().optional().default(true)
|
|
642
|
+
});
|
|
643
|
+
var VariableSlotSchema = z8.object({
|
|
644
|
+
value: z8.string().max(8192).default(""),
|
|
645
|
+
pre: z8.string().max(8192).default(""),
|
|
646
|
+
post: z8.string().max(8192).default(""),
|
|
647
|
+
isSecret: z8.boolean().default(false),
|
|
648
|
+
// When true, this variable is injected into the process environment of AI
|
|
649
|
+
// agents (Claude Code, Codex, …) spawned while this environment is active.
|
|
650
|
+
// Opt-in: defaults to false so secrets are never leaked to AI agents by default.
|
|
651
|
+
injectIntoAi: z8.boolean().default(false)
|
|
652
|
+
});
|
|
653
|
+
var VariableSchema = z8.object({
|
|
654
|
+
key: z8.string().min(1).max(256),
|
|
655
|
+
value: VariableSlotSchema
|
|
656
|
+
});
|
|
657
|
+
var VariablesRecordSchema = z8.record(
|
|
658
|
+
z8.string().max(128),
|
|
659
|
+
VariableSchema
|
|
660
|
+
).refine(
|
|
661
|
+
(obj) => Object.keys(obj).length <= 200,
|
|
662
|
+
{ message: "Max 200 variables" }
|
|
663
|
+
);
|
|
664
|
+
var VariableSlotsRecordSchema = z8.record(
|
|
665
|
+
z8.string().max(256),
|
|
666
|
+
VariableSlotSchema
|
|
667
|
+
).refine(
|
|
668
|
+
(obj) => Object.keys(obj).length <= 200,
|
|
669
|
+
{ message: "Max 200 variable slots" }
|
|
670
|
+
);
|
|
671
|
+
var ServiceConfigSchema = z8.object({
|
|
672
|
+
id: z8.string().max(128),
|
|
673
|
+
orgId: z8.string().max(128).nullable().optional(),
|
|
674
|
+
agentId: z8.string().max(128).optional(),
|
|
675
|
+
// Optional: if absent, inherited from active environment's agentId
|
|
676
|
+
name: z8.string().min(1).max(200),
|
|
677
|
+
commands: z8.array(ServiceCommandSchema).max(50).optional().default([]),
|
|
678
|
+
cwd: z8.string().max(4096).optional(),
|
|
679
|
+
ports: z8.array(z8.number().int().positive().max(65535)).max(20).optional().default([]),
|
|
680
|
+
// Metadata fields (migration from old Runeya)
|
|
681
|
+
groups: z8.array(z8.string().max(200)).max(20).optional().default([]),
|
|
682
|
+
description: z8.string().max(2e3).optional(),
|
|
683
|
+
/** Path (relative to service.cwd or absolute) where the service's docs/wiki markdown files live. Optional — defaults to service.cwd. */
|
|
684
|
+
docsPath: z8.string().max(4096).optional(),
|
|
685
|
+
url: z8.string().max(2048).optional(),
|
|
686
|
+
localUrls: z8.array(z8.object({
|
|
687
|
+
url: z8.string().max(253).regex(/^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$/),
|
|
688
|
+
port: z8.number().int().min(1).max(65535)
|
|
689
|
+
})).max(20).optional().default([]),
|
|
690
|
+
openapiUrl: z8.string().max(2048).optional(),
|
|
691
|
+
git: z8.object({
|
|
692
|
+
remote: z8.string().max(2048).optional(),
|
|
693
|
+
home: z8.string().max(2048).optional()
|
|
694
|
+
}).optional(),
|
|
695
|
+
meta: z8.record(z8.string().max(256), z8.string().max(2e3)).optional().refine((obj) => !obj || Object.keys(obj).length <= 100, { message: "Too many meta keys (max 100)" }),
|
|
696
|
+
// Transient env dict (resolved by server before deployment, used directly by agent runner — NOT persisted)
|
|
697
|
+
env: z8.record(z8.string().max(256), z8.string().max(8192)).default({}).refine(
|
|
698
|
+
(obj) => Object.keys(obj).length <= 200,
|
|
699
|
+
{ message: "Too many env vars (max 200)" }
|
|
700
|
+
),
|
|
701
|
+
envSecrets: z8.array(z8.string().max(256)).max(200).default([]),
|
|
702
|
+
// Transient: resolved JS log parsers (from parserIds, resolved by server before deployment — NOT persisted)
|
|
703
|
+
resolvedLogParsers: z8.array(JSLogParserSchema).default([]).optional(),
|
|
704
|
+
// Transient: resolved working directory (cwd with env vars expanded — NOT persisted)
|
|
705
|
+
resolvedCwd: z8.string().optional(),
|
|
706
|
+
runner: z8.enum(["native", "docker"]).optional().default("native"),
|
|
707
|
+
dockerConfig: DockerConfigSchema.optional(),
|
|
708
|
+
healthCheck: HealthCheckSchema.optional(),
|
|
709
|
+
parserIds: z8.array(z8.string().max(128)).max(50).default([]),
|
|
710
|
+
shortcuts: z8.array(ServiceShortcutSchema).max(50).optional().default([]),
|
|
711
|
+
autoRestart: z8.boolean().optional().default(false),
|
|
712
|
+
clearLogsOnStart: z8.boolean().optional().default(false),
|
|
713
|
+
restartStrategy: RestartStrategySchema.optional(),
|
|
714
|
+
maxRestarts: z8.number().int().nonnegative().optional(),
|
|
715
|
+
restartBackoffMs: z8.number().int().positive().optional().default(1e3),
|
|
716
|
+
// Log sources additionnelles (au-delà du stdout/stderr console par défaut)
|
|
717
|
+
logSources: z8.array(LogSourceConfigSchema).max(20).optional().default([])
|
|
718
|
+
});
|
|
719
|
+
var CreateServiceSchema = ServiceConfigSchema.omit({ id: true }).partial().required({ name: true });
|
|
720
|
+
var UpdateServiceSchema = ServiceConfigSchema.partial().required({ id: true }).extend({
|
|
721
|
+
agentId: z8.string().max(128).nullable().optional(),
|
|
722
|
+
// null = clear (inherit from env), undefined = no change
|
|
723
|
+
cwd: z8.string().max(4096).nullable().optional(),
|
|
724
|
+
git: z8.object({ remote: z8.string().max(2048).optional(), home: z8.string().max(2048).optional() }).nullable().optional(),
|
|
725
|
+
meta: z8.record(z8.string().max(256), z8.string().max(2e3)).nullable().optional().refine((obj) => !obj || Object.keys(obj).length <= 100, { message: "Too many meta keys (max 100)" }),
|
|
726
|
+
healthCheck: HealthCheckSchema.nullable().optional()
|
|
727
|
+
});
|
|
728
|
+
|
|
729
|
+
// ../../packages/shared/src/schemas/process.schema.ts
|
|
730
|
+
import { z as z9 } from "zod";
|
|
731
|
+
var ProcessStateSchema = z9.enum(["starting", "running", "stopped", "errored"]);
|
|
732
|
+
var HealthStatusSchema = z9.enum(["healthy", "unhealthy", "unknown"]);
|
|
733
|
+
var ProcessStatusSchema = z9.object({
|
|
734
|
+
id: z9.string().max(128),
|
|
735
|
+
serviceId: z9.string().max(128),
|
|
736
|
+
agentId: z9.string().max(128),
|
|
737
|
+
state: ProcessStateSchema,
|
|
738
|
+
pid: z9.number().int().nullable().optional(),
|
|
739
|
+
pids: z9.array(z9.number().int()).optional().default([]),
|
|
740
|
+
exitCode: z9.number().int().nullable().optional(),
|
|
741
|
+
startedAt: z9.coerce.date().nullable().optional(),
|
|
742
|
+
restartCount: z9.number().int().nonnegative().default(0),
|
|
743
|
+
uptime: z9.number().nonnegative().default(0),
|
|
744
|
+
healthStatus: HealthStatusSchema.default("unknown"),
|
|
745
|
+
/**
|
|
746
|
+
* Le répertoire où le processus s'exécute VRAIMENT, absolutisé par l'agent.
|
|
747
|
+
*
|
|
748
|
+
* Rapporté par l'agent plutôt que déduit de la config : entre le `cwd` de la
|
|
749
|
+
* commande, celui du service, l'ancrage sur le projet et les variables que
|
|
750
|
+
* l'agent étend lui-même, la valeur affichée n'aurait rien prouvé. Ce qui
|
|
751
|
+
* intéresse quand un service tourne contre le mauvais dépôt, c'est le chemin
|
|
752
|
+
* final — y compris quand il retombe sur le répertoire de l'agent.
|
|
753
|
+
*/
|
|
754
|
+
cwd: z9.string().max(4096).nullable().optional()
|
|
755
|
+
});
|
|
756
|
+
|
|
757
|
+
// ../../packages/shared/src/schemas/log.schema.ts
|
|
758
|
+
import { z as z10 } from "zod";
|
|
759
|
+
var LogLevelSchema = z10.enum(["debug", "info", "warn", "error", "fatal"]);
|
|
760
|
+
var LogLineSchema = z10.object({
|
|
761
|
+
/** Raw log line as received from the process (immutable context) */
|
|
762
|
+
raw: z10.string(),
|
|
763
|
+
/** Source stream (immutable context) */
|
|
764
|
+
stream: z10.enum(["stdout", "stderr"]),
|
|
765
|
+
/** Severity level */
|
|
766
|
+
level: LogLevelSchema,
|
|
767
|
+
/** Parsed/enriched message to display */
|
|
768
|
+
message: z10.string(),
|
|
769
|
+
/** When true, the line is hidden from the log view */
|
|
770
|
+
hidden: z10.boolean(),
|
|
771
|
+
/** Arbitrary key/value pairs shown in the detail panel */
|
|
772
|
+
metadata: z10.record(z10.string().max(256), z10.unknown()).refine(
|
|
773
|
+
(obj) => Object.keys(obj).length <= 100,
|
|
774
|
+
{ message: "Too many metadata keys (max 100)" }
|
|
775
|
+
),
|
|
776
|
+
/** Full parsed JSON object when the line is JSON */
|
|
777
|
+
json: z10.record(z10.string(), z10.unknown()).optional(),
|
|
778
|
+
/** Custom header for the JSON log card (supports HTML, sanitized before display) */
|
|
779
|
+
jsonHeader: z10.string().max(256).optional()
|
|
780
|
+
});
|
|
781
|
+
var LogCardDirectiveSchema = z10.object({
|
|
782
|
+
id: z10.string().max(128),
|
|
783
|
+
type: z10.string().max(64),
|
|
784
|
+
header: z10.string().max(256),
|
|
785
|
+
collapsable: z10.boolean().optional(),
|
|
786
|
+
collapsed: z10.boolean().optional(),
|
|
787
|
+
state: z10.enum(["open", "append", "close", "self"])
|
|
788
|
+
});
|
|
789
|
+
var ParsedLogSchema = z10.object({
|
|
790
|
+
id: z10.string().max(128),
|
|
791
|
+
processId: z10.string().max(128),
|
|
792
|
+
pid: z10.number().int().nullable().optional(),
|
|
793
|
+
timestamp: z10.coerce.date(),
|
|
794
|
+
level: LogLevelSchema.default("info"),
|
|
795
|
+
message: z10.string().max(16384),
|
|
796
|
+
raw: z10.string().max(16384),
|
|
797
|
+
stream: z10.enum(["stdout", "stderr"]).default("stdout"),
|
|
798
|
+
hidden: z10.boolean().optional().default(false),
|
|
799
|
+
metadata: z10.record(z10.string().max(256), z10.unknown()).optional().refine(
|
|
800
|
+
(obj) => !obj || Object.keys(obj).length <= 100,
|
|
801
|
+
{ message: "Too many metadata keys (max 100)" }
|
|
802
|
+
),
|
|
803
|
+
json: z10.record(z10.string(), z10.unknown()).optional(),
|
|
804
|
+
logCard: LogCardDirectiveSchema.optional(),
|
|
805
|
+
sourceType: z10.enum(["console", "file", "mongo", "mysql"]).optional(),
|
|
806
|
+
sourcePath: z10.string().max(4096).optional()
|
|
807
|
+
});
|
|
808
|
+
|
|
809
|
+
// ../../packages/shared/src/schemas/agent.schema.ts
|
|
810
|
+
import { z as z11 } from "zod";
|
|
811
|
+
var ENV_VAR_NAME_REGEX = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
812
|
+
var AgentConfigSchema = z11.object({
|
|
813
|
+
id: z11.string().max(128),
|
|
814
|
+
name: z11.string().min(1).max(100),
|
|
815
|
+
url: z11.string().url().max(2048),
|
|
816
|
+
passphrase: z11.string().min(1).max(1024),
|
|
817
|
+
passthroughEnv: z11.array(
|
|
818
|
+
z11.string().regex(ENV_VAR_NAME_REGEX).max(256)
|
|
819
|
+
).max(100).default([])
|
|
820
|
+
});
|
|
821
|
+
var AgentStatusSchema = z11.object({
|
|
822
|
+
connected: z11.boolean(),
|
|
823
|
+
lastSeen: z11.string().nullable().optional(),
|
|
824
|
+
uptime: z11.number().nonnegative().default(0),
|
|
825
|
+
runnersAvailable: z11.array(z11.enum(["native", "docker"])).default(["native"]),
|
|
826
|
+
lanIp: z11.string().optional(),
|
|
827
|
+
/**
|
|
828
|
+
* Ce que la machine de l'agent vaut pour les builtins de portée `agent`.
|
|
829
|
+
* Sert à PRÉVISUALISER — la valeur injectée reste calculée au lancement, par
|
|
830
|
+
* l'agent lui-même : une IP change, un agent se déconnecte, et un statut
|
|
831
|
+
* n'est qu'un cliché.
|
|
832
|
+
*/
|
|
833
|
+
os: z11.string().max(64).optional(),
|
|
834
|
+
home: z11.string().max(4096).optional(),
|
|
835
|
+
cwd: z11.string().max(4096).optional()
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
// ../../packages/shared/src/schemas/permission.schema.ts
|
|
839
|
+
import { z as z12 } from "zod";
|
|
840
|
+
var GlobalRoleSchema = z12.enum(["owner", "admin", "member"]);
|
|
841
|
+
var ProjectRoleSchema = z12.enum(["admin", "editor", "viewer"]);
|
|
842
|
+
var ProjectMemberRoleSchema = z12.object({
|
|
843
|
+
id: z12.string().max(128),
|
|
844
|
+
projectId: z12.string().max(128),
|
|
845
|
+
userId: z12.string().max(128),
|
|
846
|
+
role: ProjectRoleSchema
|
|
847
|
+
});
|
|
848
|
+
|
|
849
|
+
// ../../packages/shared/src/schemas/sync.schema.ts
|
|
850
|
+
import { z as z13 } from "zod";
|
|
851
|
+
var ConfigVersionSchema = z13.object({
|
|
852
|
+
id: z13.string().max(128),
|
|
853
|
+
entityType: z13.enum(["project", "service"]),
|
|
854
|
+
entityId: z13.string().max(128),
|
|
855
|
+
version: z13.string().max(128),
|
|
856
|
+
parentVersion: z13.string().max(128),
|
|
857
|
+
data: z13.record(z13.string(), z13.unknown()).refine(
|
|
858
|
+
(obj) => Object.keys(obj).length <= 1e3,
|
|
859
|
+
"Too many data keys (max 1000)"
|
|
860
|
+
),
|
|
861
|
+
patch: z13.array(z13.record(z13.string(), z13.unknown())).max(1e3),
|
|
862
|
+
userId: z13.string().max(128),
|
|
863
|
+
timestamp: z13.coerce.date(),
|
|
864
|
+
resolved: z13.boolean().default(false)
|
|
865
|
+
});
|
|
866
|
+
var ConfigChangeSchema = z13.object({
|
|
867
|
+
entityType: z13.enum(["project", "service"]),
|
|
868
|
+
entityId: z13.string().max(128),
|
|
869
|
+
version: z13.string().max(128),
|
|
870
|
+
parentVersion: z13.string().max(128),
|
|
871
|
+
data: z13.record(z13.string(), z13.unknown()).refine(
|
|
872
|
+
(obj) => Object.keys(obj).length <= 1e3,
|
|
873
|
+
"Too many data keys (max 1000)"
|
|
874
|
+
),
|
|
875
|
+
patch: z13.array(z13.record(z13.string(), z13.unknown())).max(1e3)
|
|
876
|
+
});
|
|
877
|
+
var SyncStatusSchema = z13.object({
|
|
878
|
+
connected: z13.boolean(),
|
|
879
|
+
lastSync: z13.coerce.date().nullable().optional(),
|
|
880
|
+
pendingChanges: z13.number().int().nonnegative().default(0),
|
|
881
|
+
conflicts: z13.number().int().nonnegative().default(0)
|
|
882
|
+
});
|
|
883
|
+
|
|
884
|
+
// ../../packages/shared/src/schemas/audit.schema.ts
|
|
885
|
+
import { z as z14 } from "zod";
|
|
886
|
+
var AuditActionSchema = z14.enum([
|
|
887
|
+
"create",
|
|
888
|
+
"update",
|
|
889
|
+
"delete",
|
|
890
|
+
"invite",
|
|
891
|
+
"remove",
|
|
892
|
+
"deploy",
|
|
893
|
+
"start",
|
|
894
|
+
"stop",
|
|
895
|
+
"roleChange"
|
|
896
|
+
]);
|
|
897
|
+
var AuditEntityTypeSchema = z14.enum([
|
|
898
|
+
"org",
|
|
899
|
+
"project",
|
|
900
|
+
"service",
|
|
901
|
+
"member",
|
|
902
|
+
"permission"
|
|
903
|
+
]);
|
|
904
|
+
var AuditLogSchema = z14.object({
|
|
905
|
+
id: z14.string().max(128),
|
|
906
|
+
orgId: z14.string().max(128),
|
|
907
|
+
userId: z14.string().max(128),
|
|
908
|
+
action: AuditActionSchema,
|
|
909
|
+
entityType: AuditEntityTypeSchema,
|
|
910
|
+
entityId: z14.string().max(128),
|
|
911
|
+
metadata: z14.record(z14.string().max(256), z14.unknown()).default({}).refine(
|
|
912
|
+
(obj) => Object.keys(obj).length <= 100,
|
|
913
|
+
{ message: "Too many metadata keys (max 100)" }
|
|
914
|
+
),
|
|
915
|
+
timestamp: z14.coerce.date()
|
|
916
|
+
});
|
|
917
|
+
|
|
918
|
+
// ../../packages/shared/src/schemas/metrics.schema.ts
|
|
919
|
+
import { z as z15 } from "zod";
|
|
920
|
+
var ProcessMetricsSchema = z15.object({
|
|
921
|
+
processId: z15.string().max(128),
|
|
922
|
+
cpu: z15.number().nonnegative(),
|
|
923
|
+
memory: z15.number().int().nonnegative(),
|
|
924
|
+
timestamp: z15.string()
|
|
925
|
+
});
|
|
926
|
+
|
|
927
|
+
// ../../packages/shared/src/schemas/environment.schema.ts
|
|
928
|
+
import { z as z16 } from "zod";
|
|
929
|
+
var EnvironmentVariablesSchema = z16.record(
|
|
930
|
+
z16.string().max(256),
|
|
931
|
+
VariableSchema
|
|
932
|
+
).refine(
|
|
933
|
+
(obj) => Object.keys(obj).length <= 200,
|
|
934
|
+
{ message: "Max 200 variables" }
|
|
935
|
+
);
|
|
936
|
+
var EnvironmentSchema = z16.object({
|
|
937
|
+
id: z16.string().max(128),
|
|
938
|
+
projectId: z16.string().max(128),
|
|
939
|
+
name: z16.string().min(1).max(200),
|
|
940
|
+
description: z16.string().max(2e3).optional().default(""),
|
|
941
|
+
parentIds: z16.array(z16.string().max(128)).max(10).default([]),
|
|
942
|
+
variables: EnvironmentVariablesSchema.default({}),
|
|
943
|
+
// Scope: 'global' = project-level env, 'service' = per-service env
|
|
944
|
+
scope: z16.enum(["global", "service"]).default("global"),
|
|
945
|
+
// When scope='service': the serviceId this env belongs to
|
|
946
|
+
reference: z16.string().max(128).optional(),
|
|
947
|
+
// When scope='service': the globalEnvId this env activates on
|
|
948
|
+
activateOn: z16.string().max(128).optional(),
|
|
949
|
+
immutable: z16.boolean().default(false),
|
|
950
|
+
default: z16.boolean().optional().default(false),
|
|
951
|
+
color: z16.string().max(20).optional(),
|
|
952
|
+
bgColor: z16.string().max(20).optional(),
|
|
953
|
+
// When scope='global': the default agent used by services that don't have an explicit agentId
|
|
954
|
+
agentId: z16.string().max(128).optional()
|
|
955
|
+
});
|
|
956
|
+
var ResolvedEnvironmentSchema = z16.object({
|
|
957
|
+
variables: z16.record(z16.string().max(256), VariableSchema).refine((obj) => Object.keys(obj).length <= 500, { message: "Max 500 resolved variables" }),
|
|
958
|
+
env: z16.record(z16.string().max(256), z16.string().max(8192)).refine((obj) => Object.keys(obj).length <= 500, { message: "Max 500 resolved env vars" }),
|
|
959
|
+
envSecrets: z16.array(z16.string().max(256)).max(500),
|
|
960
|
+
sources: z16.record(z16.string().max(256), z16.object({
|
|
961
|
+
environmentId: z16.string().max(128),
|
|
962
|
+
environmentName: z16.string().max(200),
|
|
963
|
+
overridden: z16.boolean(),
|
|
964
|
+
resolvedFrom: z16.object({
|
|
965
|
+
environmentId: z16.string().max(128),
|
|
966
|
+
environmentName: z16.string().max(200)
|
|
967
|
+
}).optional(),
|
|
968
|
+
// Set when a machine-local override was applied to this variable, pointing
|
|
969
|
+
// at the environment that carries the winning override. Distinct from
|
|
970
|
+
// `overridden`, which also covers "shadows an inherited variable".
|
|
971
|
+
overriddenBy: z16.object({
|
|
972
|
+
environmentId: z16.string().max(128),
|
|
973
|
+
environmentName: z16.string().max(200)
|
|
974
|
+
}).optional()
|
|
975
|
+
})).refine((obj) => Object.keys(obj).length <= 500, { message: "Max 500 source entries" })
|
|
976
|
+
});
|
|
977
|
+
var CreateEnvironmentSchema = EnvironmentSchema.omit({ id: true }).extend({
|
|
978
|
+
description: z16.string().max(2e3).optional().default(""),
|
|
979
|
+
parentIds: z16.array(z16.string().max(128)).max(10).optional().default([]),
|
|
980
|
+
variables: EnvironmentVariablesSchema.optional().default({}),
|
|
981
|
+
scope: z16.enum(["global", "service"]).optional().default("global"),
|
|
982
|
+
reference: z16.string().max(128).optional(),
|
|
983
|
+
activateOn: z16.string().max(128).optional(),
|
|
984
|
+
immutable: z16.boolean().optional().default(false)
|
|
985
|
+
});
|
|
986
|
+
var UpdateEnvironmentSchema = EnvironmentSchema.partial().required({ id: true }).extend({
|
|
987
|
+
description: z16.string().max(2e3).optional(),
|
|
988
|
+
parentIds: z16.array(z16.string().max(128)).max(10).optional(),
|
|
989
|
+
variables: EnvironmentVariablesSchema.optional(),
|
|
990
|
+
scope: z16.enum(["global", "service"]).optional(),
|
|
991
|
+
immutable: z16.boolean().optional(),
|
|
992
|
+
default: z16.boolean().optional(),
|
|
993
|
+
agentId: z16.string().max(128).nullable().optional()
|
|
994
|
+
// null = clear (no default agent)
|
|
995
|
+
});
|
|
996
|
+
|
|
997
|
+
// ../../packages/shared/src/schemas/environment-overrides.schema.ts
|
|
998
|
+
import { z as z17 } from "zod";
|
|
999
|
+
var VariableOverrideSchema = z17.object({
|
|
1000
|
+
value: VariableSlotSchema
|
|
1001
|
+
});
|
|
1002
|
+
var EnvironmentOverridesSchema = z17.record(
|
|
1003
|
+
z17.string().max(128),
|
|
1004
|
+
VariableOverrideSchema
|
|
1005
|
+
).refine(
|
|
1006
|
+
(obj) => Object.keys(obj).length <= 5e3,
|
|
1007
|
+
{ message: "Max 5000 overrides" }
|
|
1008
|
+
);
|
|
1009
|
+
|
|
1010
|
+
// ../../packages/shared/src/schemas/api-key.schema.ts
|
|
1011
|
+
import { z as z18 } from "zod";
|
|
1012
|
+
var ApiServiceActionSchema = z18.enum([
|
|
1013
|
+
"service:read",
|
|
1014
|
+
"service:start",
|
|
1015
|
+
"service:stop",
|
|
1016
|
+
"service:restart",
|
|
1017
|
+
"service:healthcheck",
|
|
1018
|
+
"service:status",
|
|
1019
|
+
"logs:read"
|
|
1020
|
+
]);
|
|
1021
|
+
var ApiEnvActionSchema = z18.enum(["env:read", "env:write"]);
|
|
1022
|
+
var ApiEnvPermSchema = z18.object({
|
|
1023
|
+
environmentId: z18.string().max(128),
|
|
1024
|
+
actions: z18.array(ApiEnvActionSchema).max(10).default(["env:read"]),
|
|
1025
|
+
includeSecrets: z18.boolean().default(false)
|
|
1026
|
+
});
|
|
1027
|
+
var ApiServicePermSchema = z18.object({
|
|
1028
|
+
serviceId: z18.string().max(128),
|
|
1029
|
+
actions: z18.array(ApiServiceActionSchema).max(10).default(["service:read"]),
|
|
1030
|
+
environments: z18.array(ApiEnvPermSchema).max(100).default([])
|
|
1031
|
+
});
|
|
1032
|
+
var ApiKeyScopeSchema = z18.object({
|
|
1033
|
+
services: z18.array(ApiServicePermSchema).max(500).default([])
|
|
1034
|
+
});
|
|
1035
|
+
var ApiKeySchema = z18.object({
|
|
1036
|
+
id: z18.string().max(128),
|
|
1037
|
+
name: z18.string().min(1).max(200),
|
|
1038
|
+
key: z18.string().regex(/^[0-9a-f]{64}$/i),
|
|
1039
|
+
scopes: ApiKeyScopeSchema,
|
|
1040
|
+
createdAt: z18.string().max(64),
|
|
1041
|
+
isPublic: z18.boolean().default(false)
|
|
1042
|
+
});
|
|
1043
|
+
var PersistedApiKeySchema = ApiKeySchema.extend({
|
|
1044
|
+
key: z18.string().min(1).max(4096)
|
|
1045
|
+
});
|
|
1046
|
+
var ApiKeysFileSchema = z18.object({
|
|
1047
|
+
keys: z18.array(PersistedApiKeySchema).max(100)
|
|
1048
|
+
});
|
|
1049
|
+
var MaskedApiKeySchema = ApiKeySchema.omit({ key: true }).extend({
|
|
1050
|
+
/** Last 4 characters of the secret, for recognising a key in a list. */
|
|
1051
|
+
keyPreview: z18.string().max(8)
|
|
1052
|
+
});
|
|
1053
|
+
|
|
1054
|
+
// ../../packages/shared/src/schemas/image.schema.ts
|
|
1055
|
+
import { z as z19 } from "zod";
|
|
1056
|
+
var ALLOWED_IMAGE_MIME_TYPES = ["image/png", "image/jpeg", "image/webp", "image/gif"];
|
|
1057
|
+
var ImagePartSchema = z19.object({
|
|
1058
|
+
type: z19.literal("image"),
|
|
1059
|
+
imageId: z19.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "Must be a valid UUID"),
|
|
1060
|
+
url: z19.string().min(1),
|
|
1061
|
+
mimeType: z19.enum(ALLOWED_IMAGE_MIME_TYPES),
|
|
1062
|
+
altText: z19.string().max(500).optional()
|
|
1063
|
+
});
|
|
1064
|
+
var ImageUploadResponseSchema = z19.object({
|
|
1065
|
+
imageId: z19.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "Must be a valid UUID"),
|
|
1066
|
+
url: z19.string().min(1),
|
|
1067
|
+
mimeType: z19.enum(ALLOWED_IMAGE_MIME_TYPES),
|
|
1068
|
+
originalName: z19.string()
|
|
1069
|
+
});
|
|
1070
|
+
var ImageMetaSchema = z19.object({
|
|
1071
|
+
imageId: z19.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "Must be a valid UUID"),
|
|
1072
|
+
filePath: z19.string().min(1),
|
|
1073
|
+
mimeType: z19.enum(ALLOWED_IMAGE_MIME_TYPES),
|
|
1074
|
+
originalName: z19.string().min(1),
|
|
1075
|
+
createdAt: z19.number().positive(),
|
|
1076
|
+
size: z19.number().positive().optional()
|
|
1077
|
+
});
|
|
1078
|
+
|
|
1079
|
+
// ../../packages/shared/src/schemas/kanban.schema.ts
|
|
1080
|
+
import { z as z20 } from "zod";
|
|
1081
|
+
var KanbanAttachmentSchema = z20.object({
|
|
1082
|
+
/** Server-issued id, also the storage key. */
|
|
1083
|
+
id: z20.string().max(128),
|
|
1084
|
+
name: z20.string().max(255),
|
|
1085
|
+
size: z20.number().int().nonnegative(),
|
|
1086
|
+
contentType: z20.string().max(128)
|
|
1087
|
+
});
|
|
1088
|
+
var KanbanCardEventSchema = z20.object({
|
|
1089
|
+
type: z20.enum(["created", "edited", "moved", "image_added", "image_removed", "title_changed", "conversation_started", "scenario_started", "comment", "archived", "unarchived"]),
|
|
1090
|
+
timestamp: z20.string(),
|
|
1091
|
+
/** Extra context: old/new column name, old/new title, comment text, etc. */
|
|
1092
|
+
/**
|
|
1093
|
+
* Le texte de l'entrée : le corps d'un commentaire, ou le contexte du geste.
|
|
1094
|
+
*
|
|
1095
|
+
* Borné comme le corps d'une carte (100 000), et non plus à 5 000 : un
|
|
1096
|
+
* commentaire est de la prose comme une description, et rien de technique ne
|
|
1097
|
+
* justifiait un écart de vingt fois. La borne étroite s'est vue à l'import
|
|
1098
|
+
* d'un Kanbanize, où des commentaires de 12 000 caractères passaient par
|
|
1099
|
+
* l'API publique — bornée, elle, à 20 000 — pour écrire en base une donnée que
|
|
1100
|
+
* ce schéma déclarait invalide, et qu'aucune reprise depuis l'interface
|
|
1101
|
+
* n'aurait ensuite pu enregistrer.
|
|
1102
|
+
*/
|
|
1103
|
+
detail: z20.string().max(1e5).optional(),
|
|
1104
|
+
/**
|
|
1105
|
+
* Stable identity of the event, used to tell an edit from an insertion when a
|
|
1106
|
+
* whole history is written back. Absent on events recorded before the field
|
|
1107
|
+
* existed; those fall back to (type, timestamp).
|
|
1108
|
+
*/
|
|
1109
|
+
id: z20.string().max(128).optional(),
|
|
1110
|
+
/** Who authored this event — 'ai' or 'user'. Only set for comment events. */
|
|
1111
|
+
author: z20.enum(["ai", "user"]).optional(),
|
|
1112
|
+
/**
|
|
1113
|
+
* Qui est derrière l'événement, estampillé par le serveur — jamais pris du
|
|
1114
|
+
* client, sans quoi n'importe qui pourrait signer au nom d'un autre.
|
|
1115
|
+
*
|
|
1116
|
+
* Posé sur les commentaires (c'est ce qui rend « mon propre commentaire »
|
|
1117
|
+
* répondable ; `author` ne sépare que l'IA de l'humain) et sur les
|
|
1118
|
+
* déplacements. Absent des événements écrits avant qu'on l'estampille : un
|
|
1119
|
+
* lecteur doit donc afficher « on ne sait pas », pas un nom vide.
|
|
1120
|
+
*
|
|
1121
|
+
* Pour une clé d'API, c'est le nom de la clé et non son porteur : la clé
|
|
1122
|
+
* emprunte les droits de son créateur, pas son identité — personne ne doit
|
|
1123
|
+
* croire qu'un humain a déplacé ce qu'un robot de CI a déplacé.
|
|
1124
|
+
*/
|
|
1125
|
+
authorUser: z20.object({ id: z20.string().max(128), name: z20.string().max(200) }).optional(),
|
|
1126
|
+
/** Set when the author amended their comment, so the UI can say so. */
|
|
1127
|
+
editedAt: z20.string().optional(),
|
|
1128
|
+
/** Files attached to a comment — same storage as a card's own attachments. */
|
|
1129
|
+
attachments: z20.array(KanbanAttachmentSchema).max(20).optional(),
|
|
1130
|
+
/** Conversation that produced this event (comments only). Used to navigate back to the conversation. */
|
|
1131
|
+
conversationId: z20.string().optional()
|
|
1132
|
+
});
|
|
1133
|
+
var KanbanCardSchema = z20.object({
|
|
1134
|
+
id: z20.string(),
|
|
1135
|
+
title: z20.string().min(1).max(500),
|
|
1136
|
+
markdown: z20.string().max(1e5).default(""),
|
|
1137
|
+
/**
|
|
1138
|
+
* Legacy inline images, kept so boards written before object storage still
|
|
1139
|
+
* render. New uploads go to `attachments` instead.
|
|
1140
|
+
*/
|
|
1141
|
+
images: z20.array(z20.string()).default([]),
|
|
1142
|
+
/** Files attached to the card — stored out of band, referenced here. */
|
|
1143
|
+
attachments: z20.array(KanbanAttachmentSchema).max(50).default([]),
|
|
1144
|
+
order: z20.number().int(),
|
|
1145
|
+
/**
|
|
1146
|
+
* La priorité de la carte, de 1 à 10 — 10 étant le plus urgent.
|
|
1147
|
+
*
|
|
1148
|
+
* Facultative, et absente veut dire « pas de priorité », pas « la plus
|
|
1149
|
+
* basse » : une carte qu'on n'a pas encore arbitrée ne doit pas se ranger
|
|
1150
|
+
* d'office au fond de la pile.
|
|
1151
|
+
*/
|
|
1152
|
+
priority: z20.number().int().min(1).max(10).optional(),
|
|
1153
|
+
/**
|
|
1154
|
+
* Les groupes de la carte — des étiquettes libres, posées par l'équipe.
|
|
1155
|
+
*
|
|
1156
|
+
* Rien ne les déclare ailleurs : un groupe existe parce qu'une carte le
|
|
1157
|
+
* porte, et disparaît avec la dernière qui le portait. C'est ce qui permet
|
|
1158
|
+
* d'en créer un en le tapant, sans passer par un écran d'administration.
|
|
1159
|
+
*/
|
|
1160
|
+
groups: z20.array(z20.string().min(1).max(60)).max(30).optional(),
|
|
1161
|
+
/**
|
|
1162
|
+
* L'échéance de la carte : le jour où elle est attendue, `AAAA-MM-JJ`.
|
|
1163
|
+
*
|
|
1164
|
+
* Un jour, pas un instant, et c'est une décision : une équipe se dit « pour
|
|
1165
|
+
* vendredi », jamais « pour vendredi 23:59:59 UTC ». Stocker un instant
|
|
1166
|
+
* ferait afficher une échéance au 4 mars comme le 3 mars à qui travaille à
|
|
1167
|
+
* l'ouest de Greenwich — la carte serait en retard d'un jour pour la moitié
|
|
1168
|
+
* de l'équipe, et personne ne saurait pourquoi.
|
|
1169
|
+
*
|
|
1170
|
+
* Facultative, et absente veut dire « pas d'échéance », pas « en retard » :
|
|
1171
|
+
* une carte qu'on n'a pas datée ne doit pas s'annoncer comme urgente.
|
|
1172
|
+
*/
|
|
1173
|
+
deadline: z20.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
|
|
1174
|
+
/**
|
|
1175
|
+
* La couleur de la carte, en hexadécimal (`#RRGGBB`) — un liseré en haut de
|
|
1176
|
+
* la carte, et rien d'autre : ce qu'elle veut dire appartient à l'équipe.
|
|
1177
|
+
*
|
|
1178
|
+
* Bornée à une notation stricte plutôt qu'à une chaîne libre : cette valeur
|
|
1179
|
+
* finit dans un attribut `style`, et une couleur ne doit pouvoir contenir
|
|
1180
|
+
* qu'une couleur. Absente sur les cartes sans couleur.
|
|
1181
|
+
*/
|
|
1182
|
+
color: z20.string().regex(/^#[0-9a-fA-F]{6}$/).optional(),
|
|
1183
|
+
/**
|
|
1184
|
+
* Le journal de la carte — commentaires compris.
|
|
1185
|
+
*
|
|
1186
|
+
* Optionnel, et c'est tout l'intérêt : c'est la partie qui grossit sans fin
|
|
1187
|
+
* (une IA bavarde y écrit des pages), alors les lectures de tableau ne le
|
|
1188
|
+
* transportent plus. `undefined` veut dire « pas chargé », et une écriture
|
|
1189
|
+
* qui l'omet laisse au serveur celui qu'il a en base — à ne pas confondre
|
|
1190
|
+
* avec `[]`, qui demanderait bel et bien de le vider.
|
|
1191
|
+
*/
|
|
1192
|
+
history: z20.array(KanbanCardEventSchema).optional(),
|
|
1193
|
+
/**
|
|
1194
|
+
* Ce que le journal absent laisse quand même dire : combien de commentaires,
|
|
1195
|
+
* et quand fut le dernier. Posés par le serveur en lecture, ignorés en
|
|
1196
|
+
* écriture — la carte ne les stocke pas, ils se déduisent de `history`.
|
|
1197
|
+
*/
|
|
1198
|
+
commentCount: z20.number().int().nonnegative().optional(),
|
|
1199
|
+
lastCommentAt: z20.string().optional(),
|
|
1200
|
+
/**
|
|
1201
|
+
* Les entrées de journal qui ouvrent une conversation IA. Elles restent dans
|
|
1202
|
+
* la lecture allégée — il y en a une poignée par carte, et l'hôte s'en sert
|
|
1203
|
+
* pour dire, sans ouvrir la carte, qu'une IA y travaille.
|
|
1204
|
+
*/
|
|
1205
|
+
conversationEvents: z20.array(KanbanCardEventSchema).optional(),
|
|
1206
|
+
createdAt: z20.string(),
|
|
1207
|
+
updatedAt: z20.string(),
|
|
1208
|
+
/**
|
|
1209
|
+
* Quand la carte a été archivée — absente tant qu'elle est au tableau.
|
|
1210
|
+
*
|
|
1211
|
+
* Une carte archivée reste dans sa colonne en base : c'est la lecture qui la
|
|
1212
|
+
* retire du tableau, jamais une écriture qui la déplace. Rien à recoller donc
|
|
1213
|
+
* au désarchivage, et aucun cimetière où une carte pourrait se perdre.
|
|
1214
|
+
*/
|
|
1215
|
+
archivedAt: z20.string().optional(),
|
|
1216
|
+
/**
|
|
1217
|
+
* La colonne d'où la carte a été archivée, telle qu'elle s'appelait alors.
|
|
1218
|
+
*
|
|
1219
|
+
* L'identifiant sert à l'y remettre, le titre à le dire dans l'archive même
|
|
1220
|
+
* quand la colonne a disparu depuis — auquel cas le désarchivage repose la
|
|
1221
|
+
* carte dans la première colonne, sans se taire sur son origine.
|
|
1222
|
+
*/
|
|
1223
|
+
archivedFrom: z20.object({ columnId: z20.string().max(128), columnTitle: z20.string().max(200) }).optional(),
|
|
1224
|
+
/**
|
|
1225
|
+
* Quand la carte a été supprimée. Rien n'est effacé : la carte reste en base,
|
|
1226
|
+
* et toutes les lectures l'écartent.
|
|
1227
|
+
*
|
|
1228
|
+
* Une suppression est le seul geste que rien ne rattrape — sauf à ne pas
|
|
1229
|
+
* l'exécuter vraiment. La colonne et le tableau portent le même champ, pour
|
|
1230
|
+
* que supprimer l'un n'emporte jamais les cartes de l'autre.
|
|
1231
|
+
*/
|
|
1232
|
+
deletedAt: z20.string().optional(),
|
|
1233
|
+
/**
|
|
1234
|
+
* People assigned to the card. Names are denormalized for display; the server
|
|
1235
|
+
* keeps only members of the owning organization, and notifies newcomers.
|
|
1236
|
+
*/
|
|
1237
|
+
assignees: z20.array(z20.object({ id: z20.string().max(128), name: z20.string().max(200) })).max(20).default([]),
|
|
1238
|
+
/**
|
|
1239
|
+
* Who first created the card. Stamped by the server the first time a card id
|
|
1240
|
+
* appears in a board write, never taken from the client — a member could
|
|
1241
|
+
* otherwise claim any authorship. Absent on cards created before this field
|
|
1242
|
+
* existed, so readers must treat it as unknown rather than assume.
|
|
1243
|
+
*/
|
|
1244
|
+
createdBy: z20.object({ id: z20.string().max(128), name: z20.string().max(200) }).optional()
|
|
1245
|
+
});
|
|
1246
|
+
var KanbanColumnSchema = z20.object({
|
|
1247
|
+
id: z20.string(),
|
|
1248
|
+
title: z20.string().min(1).max(200),
|
|
1249
|
+
order: z20.number().int(),
|
|
1250
|
+
cards: z20.array(KanbanCardSchema).default([]),
|
|
1251
|
+
/**
|
|
1252
|
+
* Le regroupement auquel la colonne appartient, s'il y en a un.
|
|
1253
|
+
*
|
|
1254
|
+
* Un pointeur vers le parent, et rien dans l'autre sens : le groupe ne tient
|
|
1255
|
+
* pas la liste de ses membres. Deux listes qui prétendent dire qui contient
|
|
1256
|
+
* quoi finissent par se contredire, et un déplacement devient alors deux
|
|
1257
|
+
* écritures au lieu d'une.
|
|
1258
|
+
*/
|
|
1259
|
+
groupId: z20.string().optional(),
|
|
1260
|
+
/** Supprimée, mais conservée — voir `deletedAt` sur la carte. */
|
|
1261
|
+
deletedAt: z20.string().optional()
|
|
1262
|
+
});
|
|
1263
|
+
var KanbanColumnGroupSchema = z20.object({
|
|
1264
|
+
id: z20.string(),
|
|
1265
|
+
title: z20.string().min(1).max(200),
|
|
1266
|
+
/** La couleur du bandeau, en hexadécimal — l'interface décide du défaut. */
|
|
1267
|
+
color: z20.string().regex(/^#[0-9a-fA-F]{6}$/).optional(),
|
|
1268
|
+
/** Le groupe parent, pour les regroupements imbriqués. */
|
|
1269
|
+
parentId: z20.string().optional(),
|
|
1270
|
+
/** Supprimé, mais conservé — comme une colonne. */
|
|
1271
|
+
deletedAt: z20.string().optional()
|
|
1272
|
+
});
|
|
1273
|
+
var KanbanBoardSchema = z20.object({
|
|
1274
|
+
id: z20.string(),
|
|
1275
|
+
name: z20.string().min(1).max(200),
|
|
1276
|
+
description: z20.string().max(1e4).default(""),
|
|
1277
|
+
/**
|
|
1278
|
+
* Le mode d'emploi du tableau, en texte libre : ce que veulent dire ses
|
|
1279
|
+
* colonnes, quand une carte a le droit d'avancer, les conventions de
|
|
1280
|
+
* l'équipe. Écrit par les humains, lu surtout par l'IA — il est injecté dans
|
|
1281
|
+
* le prompt des agents pour qu'ils travaillent selon les règles du tableau
|
|
1282
|
+
* plutôt que selon les leurs.
|
|
1283
|
+
*/
|
|
1284
|
+
instructions: z20.string().max(2e4).default(""),
|
|
1285
|
+
columns: z20.array(KanbanColumnSchema).default([]),
|
|
1286
|
+
/** Les regroupements de colonnes — vide sur un tableau qui n'en a jamais eu. */
|
|
1287
|
+
columnGroups: z20.array(KanbanColumnGroupSchema).default([]),
|
|
1288
|
+
archived: z20.boolean().default(false),
|
|
1289
|
+
/** Supprimé, mais conservé avec ses cartes — voir `deletedAt` sur la carte. */
|
|
1290
|
+
deletedAt: z20.string().optional(),
|
|
1291
|
+
createdAt: z20.string(),
|
|
1292
|
+
updatedAt: z20.string()
|
|
1293
|
+
});
|
|
1294
|
+
var CreateKanbanBoardInput = z20.object({
|
|
1295
|
+
name: z20.string().min(1).max(200),
|
|
1296
|
+
description: z20.string().max(1e4).optional(),
|
|
1297
|
+
instructions: z20.string().max(2e4).optional()
|
|
1298
|
+
});
|
|
1299
|
+
var UpdateKanbanBoardInput = z20.object({
|
|
1300
|
+
id: z20.string(),
|
|
1301
|
+
name: z20.string().min(1).max(200).optional(),
|
|
1302
|
+
description: z20.string().max(1e4).optional(),
|
|
1303
|
+
instructions: z20.string().max(2e4).optional(),
|
|
1304
|
+
columns: z20.array(KanbanColumnSchema).optional(),
|
|
1305
|
+
archived: z20.boolean().optional()
|
|
1306
|
+
});
|
|
1307
|
+
var KanbanCardLinkSchema = z20.object({
|
|
1308
|
+
id: z20.string().max(128),
|
|
1309
|
+
/** Le tableau et la carte qui *dépendent* de l'autre. */
|
|
1310
|
+
childBoardId: z20.string().max(64),
|
|
1311
|
+
childCardId: z20.string().max(128),
|
|
1312
|
+
/** Le tableau et la carte *dont* on dépend. */
|
|
1313
|
+
parentBoardId: z20.string().max(64),
|
|
1314
|
+
parentCardId: z20.string().max(128),
|
|
1315
|
+
createdAt: z20.string(),
|
|
1316
|
+
createdBy: z20.object({ id: z20.string().max(128), name: z20.string().max(200) }).optional()
|
|
1317
|
+
});
|
|
1318
|
+
var KanbanCardRefSchema = z20.object({
|
|
1319
|
+
cardId: z20.string().max(128),
|
|
1320
|
+
boardId: z20.string().max(64),
|
|
1321
|
+
boardName: z20.string().max(200),
|
|
1322
|
+
columnId: z20.string().max(128),
|
|
1323
|
+
columnTitle: z20.string().max(200),
|
|
1324
|
+
title: z20.string().max(500),
|
|
1325
|
+
/** Les mêmes informations qu'une ligne de tableau montre d'une carte d'ici. */
|
|
1326
|
+
assignees: z20.array(z20.object({ id: z20.string().max(128), name: z20.string().max(200) })).default([]),
|
|
1327
|
+
commentCount: z20.number().int().nonnegative().default(0)
|
|
1328
|
+
});
|
|
1329
|
+
|
|
1330
|
+
// ../../packages/shared/src/schemas/cloud-api-key.schema.ts
|
|
1331
|
+
import { z as z21 } from "zod";
|
|
1332
|
+
var CloudApiScopeSchema = z21.enum([
|
|
1333
|
+
"kanban:read",
|
|
1334
|
+
"kanban:write",
|
|
1335
|
+
"kanban:comment",
|
|
1336
|
+
"kanban:delete"
|
|
1337
|
+
]);
|
|
1338
|
+
var CloudApiKeySecretSchema = z21.string().regex(/^rk_[0-9a-f]{64}$/);
|
|
1339
|
+
var CloudApiKeySchema = z21.object({
|
|
1340
|
+
id: z21.string().max(128),
|
|
1341
|
+
organizationId: z21.string().max(128),
|
|
1342
|
+
name: z21.string().min(1).max(200),
|
|
1343
|
+
scopes: z21.array(CloudApiScopeSchema).min(1).max(10),
|
|
1344
|
+
/**
|
|
1345
|
+
* Les tableaux que la clé peut atteindre, ou `null` pour « tous ceux de
|
|
1346
|
+
* l'organisation ».
|
|
1347
|
+
*
|
|
1348
|
+
* `null` et `[]` ne sont pas la même chose : la liste vide n'ouvre rien, et
|
|
1349
|
+
* c'est délibéré — un tableau supprimé ne doit pas élargir une clé qui ne le
|
|
1350
|
+
* nommait plus que lui.
|
|
1351
|
+
*/
|
|
1352
|
+
boards: z21.array(z21.string().max(64)).max(200).nullable(),
|
|
1353
|
+
createdAt: z21.string().max(64),
|
|
1354
|
+
/** Dernier usage constaté, pour reconnaître une clé oubliée. */
|
|
1355
|
+
lastUsedAt: z21.string().max(64).nullable(),
|
|
1356
|
+
/** Qui l'a émise — une clé sans visage ne se révoque jamais sereinement. */
|
|
1357
|
+
createdBy: z21.object({ id: z21.string().max(128), name: z21.string().max(200) }),
|
|
1358
|
+
/** Les 4 derniers caractères du secret, pour reconnaître une clé dans une liste. */
|
|
1359
|
+
keyPreview: z21.string().max(8)
|
|
1360
|
+
});
|
|
1361
|
+
var CreatedCloudApiKeySchema = z21.object({
|
|
1362
|
+
key: CloudApiKeySchema,
|
|
1363
|
+
secret: CloudApiKeySecretSchema
|
|
1364
|
+
});
|
|
1365
|
+
var CreateCloudApiKeyInput = z21.object({
|
|
1366
|
+
organizationId: z21.string().min(1).max(128),
|
|
1367
|
+
name: z21.string().min(1).max(200),
|
|
1368
|
+
scopes: z21.array(CloudApiScopeSchema).min(1).max(10),
|
|
1369
|
+
boards: z21.array(z21.string().max(64)).max(200).nullable().default(null)
|
|
1370
|
+
});
|
|
1371
|
+
var UpdateCloudApiKeyInput = z21.object({
|
|
1372
|
+
id: z21.string().min(1).max(128),
|
|
1373
|
+
name: z21.string().min(1).max(200).optional(),
|
|
1374
|
+
scopes: z21.array(CloudApiScopeSchema).min(1).max(10).optional(),
|
|
1375
|
+
boards: z21.array(z21.string().max(64)).max(200).nullable().optional()
|
|
1376
|
+
});
|
|
1377
|
+
|
|
1378
|
+
// ../../packages/shared/src/schemas/changelog.schema.ts
|
|
1379
|
+
import { z as z22 } from "zod";
|
|
1380
|
+
var ChangelogSurfaceSchema = z22.enum(["app", "cloud"]);
|
|
1381
|
+
var ChangelogChangeKindSchema = z22.enum(["feature", "improvement", "fix", "breaking"]);
|
|
1382
|
+
var ChangelogTextSchema = z22.object({
|
|
1383
|
+
fr: z22.string().min(1).max(500),
|
|
1384
|
+
en: z22.string().min(1).max(500)
|
|
1385
|
+
});
|
|
1386
|
+
var ChangelogChangeSchema = z22.object({
|
|
1387
|
+
kind: ChangelogChangeKindSchema,
|
|
1388
|
+
text: ChangelogTextSchema
|
|
1389
|
+
});
|
|
1390
|
+
var ChangelogDraftSchema = ChangelogChangeSchema.extend({
|
|
1391
|
+
date: z22.string().regex(/^\d{4}-\d{2}-\d{2}$/),
|
|
1392
|
+
title: ChangelogTextSchema.optional()
|
|
1393
|
+
});
|
|
1394
|
+
var ChangelogReleaseSchema = z22.object({
|
|
1395
|
+
surface: ChangelogSurfaceSchema,
|
|
1396
|
+
/** `1.4.2` pour l'app (version npm publiée), `2026-09-03` — ou `2026-09-03.2` — pour le cloud. */
|
|
1397
|
+
version: z22.string().min(1).max(32).regex(/^[0-9][0-9.-]*$/),
|
|
1398
|
+
/** Date de publication, `YYYY-MM-DD`. */
|
|
1399
|
+
date: z22.string().regex(/^\d{4}-\d{2}-\d{2}$/),
|
|
1400
|
+
/** Facultatif : une version peut s'annoncer par son seul numéro. */
|
|
1401
|
+
title: ChangelogTextSchema.optional(),
|
|
1402
|
+
/** Une version sans changement n'a rien à annoncer : elle n'a pas sa place ici. */
|
|
1403
|
+
changes: z22.array(ChangelogChangeSchema).min(1).max(50)
|
|
1404
|
+
});
|
|
1405
|
+
var ChangelogIndexItemSchema = ChangelogReleaseSchema.omit({ changes: true }).extend({
|
|
1406
|
+
changeCount: z22.number().int().nonnegative()
|
|
1407
|
+
});
|
|
1408
|
+
|
|
1409
|
+
// ../../packages/shared/src/utils/crypto.ts
|
|
1410
|
+
import { createCipheriv, createDecipheriv, randomBytes, pbkdf2Sync } from "crypto";
|
|
1411
|
+
|
|
1412
|
+
// ../../packages/shared/src/native-parsers.ts
|
|
1413
|
+
var epoch = /* @__PURE__ */ new Date("2025-01-01T00:00:00Z");
|
|
1414
|
+
var nativeParsers = [
|
|
1415
|
+
{
|
|
1416
|
+
id: "native:json",
|
|
1417
|
+
name: "JSON Log Parser",
|
|
1418
|
+
description: "Parses JSON log lines and extracts level, message, timestamp, metadata, and the full parsed object.",
|
|
1419
|
+
code: `(line) => {
|
|
1420
|
+
var trimmed = line.message.trim();
|
|
1421
|
+
if (!trimmed.startsWith('{')) return line;
|
|
1422
|
+
try {
|
|
1423
|
+
var obj = JSON.parse(trimmed);
|
|
1424
|
+
var level = (obj.level || obj.severity || obj.loglevel || '').toString().toLowerCase();
|
|
1425
|
+
var levelMap = { trace: 'debug', debug: 'debug', info: 'info', warn: 'warn', warning: 'warn', error: 'error', fatal: 'fatal', err: 'error' };
|
|
1426
|
+
var mappedLevel = levelMap[level] || line.level;
|
|
1427
|
+
var message = obj.message || obj.msg || obj.text || trimmed;
|
|
1428
|
+
var metadata = {};
|
|
1429
|
+
for (var k in obj) {
|
|
1430
|
+
if (['level','severity','loglevel','message','msg','text','timestamp','time','ts'].indexOf(k) !== -1) continue;
|
|
1431
|
+
metadata[k] = typeof obj[k] === 'string' ? obj[k] : JSON.stringify(obj[k]);
|
|
1432
|
+
}
|
|
1433
|
+
var merged = {};
|
|
1434
|
+
for (var mk in line.metadata) merged[mk] = line.metadata[mk];
|
|
1435
|
+
for (var nk in metadata) merged[nk] = metadata[nk];
|
|
1436
|
+
return { raw: line.raw, stream: line.stream, level: mappedLevel, message: String(message).slice(0, 16384), hidden: line.hidden, metadata: merged, json: obj, jsonHeader: line.jsonHeader };
|
|
1437
|
+
} catch (e) { return line; }
|
|
1438
|
+
}`,
|
|
1439
|
+
enabled: true,
|
|
1440
|
+
builtin: true,
|
|
1441
|
+
createdAt: epoch,
|
|
1442
|
+
updatedAt: epoch
|
|
1443
|
+
},
|
|
1444
|
+
{
|
|
1445
|
+
id: "native:debug",
|
|
1446
|
+
name: "Runeya Debug Parser",
|
|
1447
|
+
description: 'Detects Runeya internal debug logs emitted as JSON arrays: ["runeya", payload]. Marks them as debug level.',
|
|
1448
|
+
code: `(line) => {
|
|
1449
|
+
var trimmed = line.message.trim();
|
|
1450
|
+
if (!trimmed.startsWith('[')) return line;
|
|
1451
|
+
try {
|
|
1452
|
+
var parsed = JSON.parse(trimmed);
|
|
1453
|
+
if (!Array.isArray(parsed) || parsed[0] !== 'runeya') return line;
|
|
1454
|
+
var debug = parsed.length === 2 ? parsed[1] : parsed.slice(1);
|
|
1455
|
+
var message = typeof debug === 'string' ? debug : JSON.stringify(debug);
|
|
1456
|
+
var merged = {};
|
|
1457
|
+
for (var k in line.metadata) merged[k] = line.metadata[k];
|
|
1458
|
+
merged.runeya_debug = JSON.stringify(debug);
|
|
1459
|
+
return { raw: line.raw, stream: line.stream, level: 'debug', message: message, hidden: line.hidden, metadata: merged, jsonHeader: line.jsonHeader };
|
|
1460
|
+
} catch (e) { return line; }
|
|
1461
|
+
}`,
|
|
1462
|
+
enabled: true,
|
|
1463
|
+
builtin: true,
|
|
1464
|
+
createdAt: epoch,
|
|
1465
|
+
updatedAt: epoch
|
|
1466
|
+
},
|
|
1467
|
+
{
|
|
1468
|
+
id: "native:links",
|
|
1469
|
+
name: "Link Detector",
|
|
1470
|
+
description: "Detects URLs in plain-text log lines and exposes them in metadata.links for frontend rendering.",
|
|
1471
|
+
code: `(line) => {
|
|
1472
|
+
var urlRegex = /(https?|ftp):\\/\\/[\\w_-]+(?:\\.[\\w_-]+)+([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])?/gi;
|
|
1473
|
+
var urls = line.message.match(urlRegex);
|
|
1474
|
+
if (!urls || urls.length === 0) return line;
|
|
1475
|
+
var merged = {};
|
|
1476
|
+
for (var k in line.metadata) merged[k] = line.metadata[k];
|
|
1477
|
+
merged.links = urls.join(' ');
|
|
1478
|
+
return { raw: line.raw, stream: line.stream, level: line.level, message: line.message, hidden: line.hidden, metadata: merged, jsonHeader: line.jsonHeader };
|
|
1479
|
+
}`,
|
|
1480
|
+
enabled: true,
|
|
1481
|
+
builtin: true,
|
|
1482
|
+
createdAt: epoch,
|
|
1483
|
+
updatedAt: epoch
|
|
1484
|
+
}
|
|
1485
|
+
];
|
|
1486
|
+
|
|
1487
|
+
// ../../packages/shared/src/js-log-parser.ts
|
|
1488
|
+
import vm from "vm";
|
|
1489
|
+
var VALID_LEVELS = /* @__PURE__ */ new Set(["debug", "info", "warn", "error", "fatal"]);
|
|
1490
|
+
var PARSE_TIMEOUT_MS = 50;
|
|
1491
|
+
var MAX_CONSECUTIVE_TIMEOUTS = 10;
|
|
1492
|
+
var JSLogParser = class {
|
|
1493
|
+
parsers = [];
|
|
1494
|
+
constructor(definitions = []) {
|
|
1495
|
+
this.setParsers(definitions);
|
|
1496
|
+
}
|
|
1497
|
+
setParsers(definitions) {
|
|
1498
|
+
this.parsers = [];
|
|
1499
|
+
for (const def of definitions) {
|
|
1500
|
+
if (!def.enabled) continue;
|
|
1501
|
+
try {
|
|
1502
|
+
const compiled = this.compileParser(def);
|
|
1503
|
+
this.parsers.push({
|
|
1504
|
+
id: def.id,
|
|
1505
|
+
name: def.name,
|
|
1506
|
+
enabled: true,
|
|
1507
|
+
fn: compiled
|
|
1508
|
+
});
|
|
1509
|
+
} catch (err) {
|
|
1510
|
+
console.warn(
|
|
1511
|
+
`[js-log-parser] Failed to compile parser "${def.name}" (${def.id}): ${err instanceof Error ? err.message : String(err)}`
|
|
1512
|
+
);
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
parse(line) {
|
|
1517
|
+
let current = line;
|
|
1518
|
+
for (const parser of this.parsers) {
|
|
1519
|
+
try {
|
|
1520
|
+
current = parser.fn(current);
|
|
1521
|
+
} catch (err) {
|
|
1522
|
+
console.warn(
|
|
1523
|
+
`[js-log-parser] Parser "${parser.name}" threw error: ${err instanceof Error ? err.message : String(err)}`
|
|
1524
|
+
);
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
return this.sanitize(current);
|
|
1528
|
+
}
|
|
1529
|
+
/**
|
|
1530
|
+
* Compile le code utilisateur en une fonction bornée en temps.
|
|
1531
|
+
*
|
|
1532
|
+
* Le `timeout` de `runInNewContext` ne couvre que l'évaluation de la factory :
|
|
1533
|
+
* la closure retournée s'exécutait ensuite ligne par ligne directement sur
|
|
1534
|
+
* l'event loop, sans aucune borne. Une regex à backtracking exponentiel
|
|
1535
|
+
* fournie par l'utilisateur figeait donc l'agent entier — logs, statuts et
|
|
1536
|
+
* métriques de *tous* les services. Chaque invocation repasse maintenant par
|
|
1537
|
+
* la vm, avec son propre budget.
|
|
1538
|
+
*/
|
|
1539
|
+
compileParser(def) {
|
|
1540
|
+
const forbidden = ["require(", "import ", "eval("];
|
|
1541
|
+
for (const pat of forbidden) {
|
|
1542
|
+
if (def.code.includes(pat)) {
|
|
1543
|
+
throw new Error("Code contains forbidden patterns (require, import, eval)");
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
const sandbox = {
|
|
1547
|
+
RegExp,
|
|
1548
|
+
String,
|
|
1549
|
+
Object,
|
|
1550
|
+
Array,
|
|
1551
|
+
JSON,
|
|
1552
|
+
Math,
|
|
1553
|
+
Date,
|
|
1554
|
+
undefined: void 0,
|
|
1555
|
+
null: null
|
|
1556
|
+
};
|
|
1557
|
+
let script;
|
|
1558
|
+
try {
|
|
1559
|
+
script = new vm.Script(`(${def.code})`, { filename: `parser-${def.id}.js` });
|
|
1560
|
+
} catch (err) {
|
|
1561
|
+
throw new Error(`Compilation failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1562
|
+
}
|
|
1563
|
+
const context = vm.createContext({ ...sandbox, __line: null, __result: null });
|
|
1564
|
+
let parserFn;
|
|
1565
|
+
try {
|
|
1566
|
+
parserFn = script.runInContext(context, { timeout: 100 });
|
|
1567
|
+
} catch (err) {
|
|
1568
|
+
throw new Error(`Execution failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1569
|
+
}
|
|
1570
|
+
if (typeof parserFn !== "function") {
|
|
1571
|
+
throw new Error("Parser code must export a function");
|
|
1572
|
+
}
|
|
1573
|
+
context["__parserFn"] = parserFn;
|
|
1574
|
+
const callScript = new vm.Script("__result = __parserFn(__line);", {
|
|
1575
|
+
filename: `parser-${def.id}-call.js`
|
|
1576
|
+
});
|
|
1577
|
+
let consecutiveTimeouts = 0;
|
|
1578
|
+
let disabled = false;
|
|
1579
|
+
return (line) => {
|
|
1580
|
+
if (disabled) return line;
|
|
1581
|
+
const ctx = context;
|
|
1582
|
+
ctx["__line"] = line;
|
|
1583
|
+
ctx["__result"] = null;
|
|
1584
|
+
try {
|
|
1585
|
+
callScript.runInContext(context, { timeout: PARSE_TIMEOUT_MS });
|
|
1586
|
+
consecutiveTimeouts = 0;
|
|
1587
|
+
} catch (err) {
|
|
1588
|
+
const e = err;
|
|
1589
|
+
const timedOut = !!e && (e.code === "ERR_SCRIPT_EXECUTION_TIMEOUT" || typeof e.message === "string" && /execution timed out/i.test(e.message));
|
|
1590
|
+
if (!timedOut) throw err;
|
|
1591
|
+
consecutiveTimeouts += 1;
|
|
1592
|
+
if (consecutiveTimeouts >= MAX_CONSECUTIVE_TIMEOUTS) {
|
|
1593
|
+
disabled = true;
|
|
1594
|
+
console.warn(
|
|
1595
|
+
`[js-log-parser] Parser "${def.name}" (${def.id}) disabled after ${MAX_CONSECUTIVE_TIMEOUTS} consecutive timeouts`
|
|
1596
|
+
);
|
|
1597
|
+
}
|
|
1598
|
+
return line;
|
|
1599
|
+
}
|
|
1600
|
+
const result = ctx["__result"];
|
|
1601
|
+
if (result === null || result === void 0 || typeof result !== "object") {
|
|
1602
|
+
return line;
|
|
1603
|
+
}
|
|
1604
|
+
return result;
|
|
1605
|
+
};
|
|
1606
|
+
}
|
|
1607
|
+
/** Sanitize the final LogLine: truncate message, limit metadata, validate level */
|
|
1608
|
+
sanitize(line) {
|
|
1609
|
+
let { message, metadata, level } = line;
|
|
1610
|
+
if (message.length > 16384) {
|
|
1611
|
+
message = message.substring(0, 16384) + "...[truncated]";
|
|
1612
|
+
}
|
|
1613
|
+
metadata = metadata ?? {};
|
|
1614
|
+
const metaKeys = Object.keys(metadata);
|
|
1615
|
+
if (metaKeys.length > 100) {
|
|
1616
|
+
const limited = {};
|
|
1617
|
+
for (let i = 0; i < 100; i++) {
|
|
1618
|
+
limited[metaKeys[i]] = metadata[metaKeys[i]];
|
|
1619
|
+
}
|
|
1620
|
+
metadata = limited;
|
|
1621
|
+
}
|
|
1622
|
+
if (!VALID_LEVELS.has(level)) {
|
|
1623
|
+
level = "info";
|
|
1624
|
+
}
|
|
1625
|
+
if (message !== line.message || metadata !== line.metadata || level !== line.level) {
|
|
1626
|
+
return { ...line, message, metadata, level };
|
|
1627
|
+
}
|
|
1628
|
+
return line;
|
|
1629
|
+
}
|
|
1630
|
+
};
|
|
1631
|
+
|
|
1632
|
+
// ../../packages/shared/src/builtins.ts
|
|
1633
|
+
var BUILTIN_VARIABLES = [
|
|
1634
|
+
// ── Le service ───────────────────────────────────────────────────────────
|
|
1635
|
+
{ name: "service.NAME", scope: "server", descriptionKey: "serviceName" },
|
|
1636
|
+
{ name: "service.ID", scope: "server", descriptionKey: "serviceId" },
|
|
1637
|
+
{ name: "service.PORT", scope: "server", descriptionKey: "servicePort" },
|
|
1638
|
+
{ name: "service.URL", scope: "server", descriptionKey: "serviceUrl" },
|
|
1639
|
+
{ name: "service.BASE_URL", scope: "server", descriptionKey: "serviceBaseUrl" },
|
|
1640
|
+
{ name: "service.CWD", scope: "agent", descriptionKey: "serviceCwd" },
|
|
1641
|
+
// ── Le projet et l'environnement actif ───────────────────────────────────
|
|
1642
|
+
{ name: "project.NAME", scope: "server", descriptionKey: "projectName" },
|
|
1643
|
+
{ name: "runeya.ENV_NAME", scope: "server", descriptionKey: "envName" },
|
|
1644
|
+
// ── Le serveur Runeya ────────────────────────────────────────────────────
|
|
1645
|
+
// `service.HOST` a toujours désigné l'adresse d'écoute du SERVEUR, pas une
|
|
1646
|
+
// propriété du service : le nom trompait, il devient un alias.
|
|
1647
|
+
{ name: "runeya.HOST", scope: "server", descriptionKey: "runeyaHost", deprecatedAlias: "service.HOST" },
|
|
1648
|
+
// ── La machine qui exécute ───────────────────────────────────────────────
|
|
1649
|
+
{ name: "agent.HOST_LAN", scope: "agent", descriptionKey: "agentHostLan", deprecatedAlias: "service.HOST_LAN" },
|
|
1650
|
+
// Le NOM de l'agent est une étiquette de la configuration du serveur, pas
|
|
1651
|
+
// une propriété de la machine : c'est le serveur qui le connaît et le résout.
|
|
1652
|
+
{ name: "agent.NAME", scope: "server", descriptionKey: "agentName" },
|
|
1653
|
+
{ name: "agent.OS", scope: "agent", descriptionKey: "agentOs" },
|
|
1654
|
+
{ name: "agent.HOME", scope: "agent", descriptionKey: "agentHome" }
|
|
1655
|
+
];
|
|
1656
|
+
var BUILTIN_REFERENCE_RE = /\{\{([A-Za-z][A-Za-z0-9_.-]*)\}\}/g;
|
|
1657
|
+
var ENVIRONMENT_NAMESPACE = "environment.";
|
|
1658
|
+
function interpolateBuiltins(text, values) {
|
|
1659
|
+
return text.replace(BUILTIN_REFERENCE_RE, (match, name) => {
|
|
1660
|
+
if (name.startsWith(ENVIRONMENT_NAMESPACE)) return match;
|
|
1661
|
+
return values[name] ?? match;
|
|
1662
|
+
});
|
|
1663
|
+
}
|
|
1664
|
+
function interpolateBuiltinsInEnv(env2, values) {
|
|
1665
|
+
const out = {};
|
|
1666
|
+
for (const [key, value] of Object.entries(env2)) {
|
|
1667
|
+
out[key] = interpolateBuiltins(value, values);
|
|
1668
|
+
}
|
|
1669
|
+
return out;
|
|
1670
|
+
}
|
|
1671
|
+
function withDeprecatedAliases(values) {
|
|
1672
|
+
const out = { ...values };
|
|
1673
|
+
for (const builtin of BUILTIN_VARIABLES) {
|
|
1674
|
+
if (builtin.deprecatedAlias && out[builtin.name] !== void 0) {
|
|
1675
|
+
out[builtin.deprecatedAlias] = out[builtin.name];
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
return out;
|
|
1679
|
+
}
|
|
1680
|
+
function serviceSlug(name) {
|
|
1681
|
+
return name.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
1682
|
+
}
|
|
1683
|
+
function servicePortValues(ports, prefix = "service") {
|
|
1684
|
+
const values = {};
|
|
1685
|
+
(ports ?? []).forEach((port, i) => {
|
|
1686
|
+
values[i === 0 ? `${prefix}.PORT` : `${prefix}.PORT_${i + 1}`] = String(port);
|
|
1687
|
+
});
|
|
1688
|
+
return values;
|
|
1689
|
+
}
|
|
1690
|
+
function isWildcardHost(host) {
|
|
1691
|
+
const h = host.trim();
|
|
1692
|
+
return h === "" || h === "0.0.0.0" || h === "::" || h === "[::]";
|
|
1693
|
+
}
|
|
1694
|
+
function isLoopbackHost(host) {
|
|
1695
|
+
const h = host.trim();
|
|
1696
|
+
return h === "127.0.0.1" || h === "::1" || h === "[::1]";
|
|
1697
|
+
}
|
|
1698
|
+
function urlHostFor(host) {
|
|
1699
|
+
if (isWildcardHost(host)) return null;
|
|
1700
|
+
return isLoopbackHost(host) ? "localhost" : host.trim();
|
|
1701
|
+
}
|
|
1702
|
+
function serviceUrlValues(service, host, prefix = "service") {
|
|
1703
|
+
const domainByPort = new Map((service.localUrls ?? []).map((lu) => [lu.port, lu.url]));
|
|
1704
|
+
const ports = [...service.ports ?? []];
|
|
1705
|
+
for (const local of service.localUrls ?? []) {
|
|
1706
|
+
if (!ports.includes(local.port)) ports.push(local.port);
|
|
1707
|
+
}
|
|
1708
|
+
const values = {};
|
|
1709
|
+
ports.forEach((port, i) => {
|
|
1710
|
+
const domain = domainByPort.get(port);
|
|
1711
|
+
values[i === 0 ? `${prefix}.URL` : `${prefix}.URL_${i + 1}`] = domain ? `http://${domain}` : `http://${host}:${port}`;
|
|
1712
|
+
});
|
|
1713
|
+
return values;
|
|
1714
|
+
}
|
|
1715
|
+
function crossServiceValues(service, host) {
|
|
1716
|
+
const slug = serviceSlug(service.name);
|
|
1717
|
+
if (!slug) return {};
|
|
1718
|
+
return {
|
|
1719
|
+
[`services.${slug}.NAME`]: service.name,
|
|
1720
|
+
[`services.${slug}.ID`]: service.id,
|
|
1721
|
+
...servicePortValues(service.ports, `services.${slug}`),
|
|
1722
|
+
...serviceUrlValues(service, host, `services.${slug}`),
|
|
1723
|
+
...service.url ? { [`services.${slug}.BASE_URL`]: service.url } : {}
|
|
1724
|
+
};
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
// ../../packages/shared/src/constants/buffers.ts
|
|
1728
|
+
var LOG_BUFFER_SIZE = 5e3;
|
|
1729
|
+
|
|
1730
|
+
// ../../packages/shared/src/constants/editors.ts
|
|
1731
|
+
var SUPPORTED_EDITORS = [
|
|
1732
|
+
{ key: "vscode", name: "Visual Studio Code", command: "code" },
|
|
1733
|
+
{ key: "cursor", name: "Cursor", command: "cursor" },
|
|
1734
|
+
{ key: "windsurf", name: "Windsurf", command: "windsurf" },
|
|
1735
|
+
{ key: "sublime", name: "Sublime Text", command: "subl" },
|
|
1736
|
+
{ key: "atom", name: "Atom", command: "atom" },
|
|
1737
|
+
{ key: "antigravity", name: "Antigravity", command: "antigravity" },
|
|
1738
|
+
{ key: "intellij", name: "IntelliJ IDEA", command: "idea" },
|
|
1739
|
+
{ key: "android-studio", name: "Android Studio", command: "studio" },
|
|
1740
|
+
{ key: "webstorm", name: "WebStorm", command: "webstorm" },
|
|
1741
|
+
{ key: "zed", name: "Zed", command: "zed" },
|
|
1742
|
+
{ key: "neovim", name: "Neovim", command: "nvim" },
|
|
1743
|
+
{ key: "vim", name: "Vim", command: "vim" },
|
|
1744
|
+
{ key: "emacs", name: "Emacs", command: "emacs" },
|
|
1745
|
+
{ key: "fleet", name: "Fleet", command: "fleet" }
|
|
1746
|
+
];
|
|
1747
|
+
var EDITOR_BY_KEY = new Map(
|
|
1748
|
+
SUPPORTED_EDITORS.map((e) => [e.key, e])
|
|
1749
|
+
);
|
|
1750
|
+
|
|
1751
|
+
// ../../packages/shared/src/sync/json-crdt.ts
|
|
1752
|
+
import * as Y from "yjs";
|
|
1753
|
+
function normalize(value) {
|
|
1754
|
+
return JSON.parse(JSON.stringify(value ?? null));
|
|
1755
|
+
}
|
|
1756
|
+
function isPlainObject(v) {
|
|
1757
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
1758
|
+
}
|
|
1759
|
+
function toPlain(value) {
|
|
1760
|
+
if (value instanceof Y.Map) {
|
|
1761
|
+
const out = {};
|
|
1762
|
+
for (const [k, v] of value.entries()) out[k] = toPlain(v);
|
|
1763
|
+
return out;
|
|
1764
|
+
}
|
|
1765
|
+
if (value instanceof Y.Array) return value.toArray().map(toPlain);
|
|
1766
|
+
return value ?? null;
|
|
1767
|
+
}
|
|
1768
|
+
function identityOf(value) {
|
|
1769
|
+
if (isPlainObject(value) && typeof value["id"] === "string") return `id:${value["id"]}`;
|
|
1770
|
+
return `v:${JSON.stringify(value)}`;
|
|
1771
|
+
}
|
|
1772
|
+
function identityOfY(value) {
|
|
1773
|
+
if (value instanceof Y.Map) {
|
|
1774
|
+
const id = value.get("id");
|
|
1775
|
+
if (typeof id === "string") return `id:${id}`;
|
|
1776
|
+
}
|
|
1777
|
+
return `v:${JSON.stringify(toPlain(value))}`;
|
|
1778
|
+
}
|
|
1779
|
+
function toY(value) {
|
|
1780
|
+
if (Array.isArray(value)) {
|
|
1781
|
+
const arr = new Y.Array();
|
|
1782
|
+
if (value.length > 0) arr.insert(0, value.map(toY));
|
|
1783
|
+
return arr;
|
|
1784
|
+
}
|
|
1785
|
+
if (isPlainObject(value)) {
|
|
1786
|
+
const map = new Y.Map();
|
|
1787
|
+
for (const [k, v] of Object.entries(value)) map.set(k, toY(v));
|
|
1788
|
+
return map;
|
|
1789
|
+
}
|
|
1790
|
+
return value;
|
|
1791
|
+
}
|
|
1792
|
+
function applyToMap(map, next) {
|
|
1793
|
+
for (const key of Array.from(map.keys())) {
|
|
1794
|
+
if (!(key in next)) map.delete(key);
|
|
1795
|
+
}
|
|
1796
|
+
for (const [key, value] of Object.entries(next)) {
|
|
1797
|
+
const current = map.get(key);
|
|
1798
|
+
if (Array.isArray(value)) {
|
|
1799
|
+
if (!(current instanceof Y.Array)) map.set(key, toY(value));
|
|
1800
|
+
else applyToArray(current, value);
|
|
1801
|
+
} else if (isPlainObject(value)) {
|
|
1802
|
+
if (!(current instanceof Y.Map)) map.set(key, toY(value));
|
|
1803
|
+
else applyToMap(current, value);
|
|
1804
|
+
} else if (current instanceof Y.Map || current instanceof Y.Array || current !== value) {
|
|
1805
|
+
map.set(key, value);
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
function applyToArray(arr, next) {
|
|
1810
|
+
const wanted = next.map(identityOf);
|
|
1811
|
+
const wantedCount = /* @__PURE__ */ new Map();
|
|
1812
|
+
for (const k of wanted) wantedCount.set(k, (wantedCount.get(k) ?? 0) + 1);
|
|
1813
|
+
const seen = /* @__PURE__ */ new Map();
|
|
1814
|
+
for (let i = arr.length - 1; i >= 0; i--) {
|
|
1815
|
+
const key = identityOfY(arr.get(i));
|
|
1816
|
+
const used = seen.get(key) ?? 0;
|
|
1817
|
+
if (used >= (wantedCount.get(key) ?? 0)) arr.delete(i, 1);
|
|
1818
|
+
else seen.set(key, used + 1);
|
|
1819
|
+
}
|
|
1820
|
+
for (let j = 0; j < next.length; j++) {
|
|
1821
|
+
const key = wanted[j];
|
|
1822
|
+
if (j < arr.length && identityOfY(arr.get(j)) === key) {
|
|
1823
|
+
const current = arr.get(j);
|
|
1824
|
+
const value = next[j];
|
|
1825
|
+
if (current instanceof Y.Map && isPlainObject(value)) applyToMap(current, value);
|
|
1826
|
+
else if (current instanceof Y.Array && Array.isArray(value)) applyToArray(current, value);
|
|
1827
|
+
continue;
|
|
1828
|
+
}
|
|
1829
|
+
let found = -1;
|
|
1830
|
+
for (let k = j + 1; k < arr.length; k++) {
|
|
1831
|
+
if (identityOfY(arr.get(k)) === key) {
|
|
1832
|
+
found = k;
|
|
1833
|
+
break;
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
if (found !== -1) {
|
|
1837
|
+
const moved = toPlain(arr.get(found));
|
|
1838
|
+
arr.delete(found, 1);
|
|
1839
|
+
arr.insert(j, [toY(moved)]);
|
|
1840
|
+
} else {
|
|
1841
|
+
arr.insert(j, [toY(next[j])]);
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
function getCollection(doc, name) {
|
|
1846
|
+
return doc.getMap(name);
|
|
1847
|
+
}
|
|
1848
|
+
function readEntity(collection, id) {
|
|
1849
|
+
const entity = collection.get(id);
|
|
1850
|
+
if (!(entity instanceof Y.Map)) return null;
|
|
1851
|
+
const plain = toPlain(entity);
|
|
1852
|
+
return isPlainObject(plain) ? plain : null;
|
|
1853
|
+
}
|
|
1854
|
+
function writeEntity(collection, id, entity) {
|
|
1855
|
+
const next = normalize(entity);
|
|
1856
|
+
if (!isPlainObject(next)) return;
|
|
1857
|
+
const current = collection.get(id);
|
|
1858
|
+
if (!(current instanceof Y.Map)) {
|
|
1859
|
+
collection.set(id, toY(next));
|
|
1860
|
+
return;
|
|
1861
|
+
}
|
|
1862
|
+
applyToMap(current, next);
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
export {
|
|
1866
|
+
env,
|
|
1867
|
+
machineRoot,
|
|
1868
|
+
localVaultRoot,
|
|
1869
|
+
orgVaultRoot,
|
|
1870
|
+
projectVaultRoot,
|
|
1871
|
+
orgIdOfRoot,
|
|
1872
|
+
vaultIdOfRoot,
|
|
1873
|
+
vaultFor,
|
|
1874
|
+
stampOrgCloud,
|
|
1875
|
+
rememberOrgName,
|
|
1876
|
+
readOrgNames,
|
|
1877
|
+
rememberOrgLogo,
|
|
1878
|
+
forgetOrgLogo,
|
|
1879
|
+
readOrgLogos,
|
|
1880
|
+
readOrgClouds,
|
|
1881
|
+
listOrgVaults,
|
|
1882
|
+
listCloudVaults,
|
|
1883
|
+
allVaultRoots,
|
|
1884
|
+
machineFilePath,
|
|
1885
|
+
keyedFilePath,
|
|
1886
|
+
legacyMachineFilePath,
|
|
1887
|
+
ensureLocalVault,
|
|
1888
|
+
keyRoot,
|
|
1889
|
+
legacyVaultRoot,
|
|
1890
|
+
ProjectSchema,
|
|
1891
|
+
ScenarioGroupSchema,
|
|
1892
|
+
ScenarioNodeSchema,
|
|
1893
|
+
ScenarioSchema,
|
|
1894
|
+
AIProviderSchema,
|
|
1895
|
+
JSLogParserSchema,
|
|
1896
|
+
NotificationPreferencesSchema,
|
|
1897
|
+
SettingsSchema,
|
|
1898
|
+
TraefikConfigSchema,
|
|
1899
|
+
SettingsPrivateSchema,
|
|
1900
|
+
SchemaVersionSchema,
|
|
1901
|
+
LogSourceConfigSchema,
|
|
1902
|
+
HealthCheckSchema,
|
|
1903
|
+
DockerConfigSchema,
|
|
1904
|
+
RestartStrategySchema,
|
|
1905
|
+
ServiceShortcutSchema,
|
|
1906
|
+
ServiceCommandSchema,
|
|
1907
|
+
VariableSchema,
|
|
1908
|
+
ServiceConfigSchema,
|
|
1909
|
+
EnvironmentSchema,
|
|
1910
|
+
CreateEnvironmentSchema,
|
|
1911
|
+
UpdateEnvironmentSchema,
|
|
1912
|
+
VariableOverrideSchema,
|
|
1913
|
+
ApiKeyScopeSchema,
|
|
1914
|
+
ApiKeysFileSchema,
|
|
1915
|
+
ChangelogSurfaceSchema,
|
|
1916
|
+
ChangelogReleaseSchema,
|
|
1917
|
+
ChangelogIndexItemSchema,
|
|
1918
|
+
COMPANION_RELAY_OPEN,
|
|
1919
|
+
COMPANION_RELAY_CLOSE,
|
|
1920
|
+
extractCompanionRelay,
|
|
1921
|
+
nativeParsers,
|
|
1922
|
+
JSLogParser,
|
|
1923
|
+
interpolateBuiltinsInEnv,
|
|
1924
|
+
withDeprecatedAliases,
|
|
1925
|
+
serviceSlug,
|
|
1926
|
+
servicePortValues,
|
|
1927
|
+
urlHostFor,
|
|
1928
|
+
serviceUrlValues,
|
|
1929
|
+
crossServiceValues,
|
|
1930
|
+
AGENT_HEALTH_POLL_INTERVAL,
|
|
1931
|
+
LOG_BUFFER_SIZE,
|
|
1932
|
+
AGENT_FETCH_TIMEOUT,
|
|
1933
|
+
AGENT_LONG_FETCH_TIMEOUT,
|
|
1934
|
+
AGENT_STOP_FETCH_TIMEOUT,
|
|
1935
|
+
PASSPHRASE_TIMEOUT,
|
|
1936
|
+
WS_RECONNECT_MIN,
|
|
1937
|
+
WS_RECONNECT_MAX,
|
|
1938
|
+
SUPPORTED_EDITORS,
|
|
1939
|
+
EDITOR_BY_KEY,
|
|
1940
|
+
getCollection,
|
|
1941
|
+
readEntity,
|
|
1942
|
+
writeEntity
|
|
1943
|
+
};
|
|
1944
|
+
//# sourceMappingURL=chunk-3MJLS5UY.js.map
|