@runeya/runeya 2.0.124 → 2.0.126

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (276) hide show
  1. package/agent/index.js.map +1 -1
  2. package/{agent-manager-FZFFWISA.js → agent-manager-QLXVQ7OD.js} +3 -3
  3. package/{chat-JIJQ7IJS.js → chat-ODBVFMKX.js} +6 -6
  4. package/{chunk-GKK3ACWB.js → chunk-2EDVDRKV.js} +589 -258
  5. package/chunk-2EDVDRKV.js.map +1 -0
  6. package/{chunk-N3ZI35SC.js → chunk-K7A3Q62R.js} +2 -2
  7. package/{chunk-H22YLVQE.js → chunk-SG2ACPOE.js} +43 -19
  8. package/chunk-SG2ACPOE.js.map +1 -0
  9. package/{chunk-T2BV5WZE.js → chunk-TTPL2M74.js} +87 -1
  10. package/chunk-TTPL2M74.js.map +1 -0
  11. package/{chunk-4PN7QBNM.js → chunk-WLZQDWJT.js} +6 -2
  12. package/chunk-WLZQDWJT.js.map +1 -0
  13. package/{companion-OZODV5BR.js → companion-5DPH3HIO.js} +6 -4
  14. package/{desktop-launcher-EGGVXXKV.js → desktop-launcher-J2BCSSGZ.js} +2 -2
  15. package/index.js +4 -4
  16. package/mcp-server/index.js +1469 -20
  17. package/mcp-server/index.js.map +1 -1
  18. package/package.json +1 -1
  19. package/{settings-manager-MAVD4GAS.js → settings-manager-E3L56VAY.js} +3 -3
  20. package/{src-SGSG2RSF.js → src-XCI5NILM.js} +245 -54
  21. package/src-XCI5NILM.js.map +1 -0
  22. package/web/assets/AgentScalarChatInterface.vue-86061Tlh.js +13 -0
  23. package/web/assets/AgentTerminalPage-DxGLu5uT.js +1 -0
  24. package/web/assets/AiChatPage-DmQKv6pr.js +1 -0
  25. package/web/assets/{AppLayout-vWoE_P8T.css → AppLayout-Do2CLgOr.css} +1 -1
  26. package/web/assets/AppLayout-DtK_nr-e.js +1 -0
  27. package/web/assets/AuditPage-CX5VJGlF.js +1 -0
  28. package/web/assets/CloudAccountPage-B_sjXlfl.js +1 -0
  29. package/web/assets/CloudAccountPage-ocHdrVEm.js +1 -0
  30. package/web/assets/CloudMessagingPage-BTfGWio6.js +2 -0
  31. package/web/assets/DashboardPage-7sATlyhd.js +164 -0
  32. package/web/assets/DashboardPage-DWA-1xgl.css +1 -0
  33. package/web/assets/DirectoryPickerDialog-DAJGNiRV.js +1 -0
  34. package/web/assets/{EditorIcon-BZyy2C12.js → EditorIcon-lzF8hPtZ.js} +2 -2
  35. package/web/assets/EnvironmentForm-DVWdFsE1.js +108 -0
  36. package/web/assets/EnvironmentFormPage-DoKBTKCU.js +1 -0
  37. package/web/assets/EnvironmentListPage-C9wGFZWU.js +1 -0
  38. package/web/assets/KanbanBoardPage-CoiDga7h.js +4 -0
  39. package/web/assets/KanbanListPage-xWYUu1P0.js +1 -0
  40. package/web/assets/LaunchProjectPage-DVXgnUYk.js +1 -0
  41. package/web/assets/LaunchServicesPage-CPN3Z3m5.css +1 -0
  42. package/web/assets/LaunchServicesPage-DM6keva3.js +1 -0
  43. package/web/assets/LogViewer-CMtuP1rB.js +3 -0
  44. package/web/assets/OrgKeyPrompt-BqVugrV1.js +1 -0
  45. package/web/assets/{ProcessControls-neMxqIY_.js → ProcessControls-DkaiMo0H.js} +1 -1
  46. package/web/assets/ProcessDetailPage-DJacy1ZE.js +1 -0
  47. package/web/assets/{ProcessMetrics-Bb7yNIVd.js → ProcessMetrics-D2lP9cEF.js} +2 -2
  48. package/web/assets/RandomJobTestPage-BOsChnPH.js +2 -0
  49. package/web/assets/ScenarioEditorPage-8XSWtwA5.js +14 -0
  50. package/web/assets/SendToChatDialog-DqPVoUgN.js +1 -0
  51. package/web/assets/ServiceControlsBar-QwLQLGFP.js +1 -0
  52. package/web/assets/ServiceControlsBar-lhuSKZqO.css +1 -0
  53. package/web/assets/ServiceDetailPage-DUw-ZZyD.js +2 -0
  54. package/web/assets/{ServiceDetailPage-BcFOlsU9.css → ServiceDetailPage-cQNK1uWq.css} +1 -1
  55. package/web/assets/ServiceFormPage-OYBr0pY4.js +1 -0
  56. package/web/assets/SettingsPage-BFoWbWhq.js +2063 -0
  57. package/web/assets/UnlockPage-DgLCLMkg.js +1 -0
  58. package/web/assets/VaultMigrationPage-C93bZgWb.js +1 -0
  59. package/web/assets/VersionBadge-2JJyjyFh.js +1 -0
  60. package/web/assets/WikiPage-DBinkJlt.js +1 -0
  61. package/web/assets/WikiView-DMyRUz16.js +1 -0
  62. package/web/assets/add-scalar-classes-C1s53GSo.js +387 -0
  63. package/web/assets/{autocomplete-BTMTTAk9.js → autocomplete-qVwP27uM.js} +3 -3
  64. package/web/assets/{basic-shape-diamond.svg-CZQG7mdB.js → basic-shape-diamond.svg-BwZ1Enqo.js} +1 -1
  65. package/web/assets/{basic-shape-hexagon.svg-BnLoXUmj.js → basic-shape-hexagon.svg-Cyko19l-.js} +1 -1
  66. package/web/assets/{basic-shape-primary-circle-ellipse-round.svg-DDU6pRYe.js → basic-shape-primary-circle-ellipse-round.svg-CWaxr-XS.js} +1 -1
  67. package/web/assets/{basic-shape-primary-square-rectangle.svg-Dq_Zdck2.js → basic-shape-primary-square-rectangle.svg-BueTJIhO.js} +1 -1
  68. package/web/assets/{basic-shape-shield.svg-DbFCxPmO.js → basic-shape-shield.svg-DiYXMUMt.js} +1 -1
  69. package/web/assets/{browser-CTYk99RA.js → browser-72mztbYe.js} +1 -1
  70. package/web/assets/{browser-DowFjZcI.js → browser-B8wHMk1o.js} +1 -1
  71. package/web/assets/{card-R4Q2Qr9t.js → card-CRMlmWrt.js} +2 -2
  72. package/web/assets/{checkbox-CfoV-T17.js → checkbox-BiDvmfqK.js} +3 -3
  73. package/web/assets/{chip-V3vhLdcF.js → chip-Cb6eK00K.js} +2 -2
  74. package/web/assets/client-3Q_o9QCm.js +24 -0
  75. package/web/assets/cloud-chat.store-DIxQd2ew.js +1 -0
  76. package/web/assets/cloud-client-Idzdbhu6.js +1 -0
  77. package/web/assets/cloud-session-CIGp7324.js +2 -0
  78. package/web/assets/cloud-session-Cj_Q0hKS.js +1 -0
  79. package/web/assets/column-4DnT4nYp.js +763 -0
  80. package/web/assets/{computer-device-desktop-monitor.svg-CRLfD7-U.js → computer-device-desktop-monitor.svg-DkL4R6oe.js} +1 -1
  81. package/web/assets/{computer-device-desktop.svg-CGKq4iih.js → computer-device-desktop.svg-DXRQ2Wl4.js} +1 -1
  82. package/web/assets/{computer-device-laptop.svg-bmeM_RDO.js → computer-device-laptop.svg-BwdMHvul.js} +1 -1
  83. package/web/assets/{computer-device-mobile-phone-android-samsung-back.svg-CFwMSjoP.js → computer-device-mobile-phone-android-samsung-back.svg-CzfVICvS.js} +1 -1
  84. package/web/assets/{computer-device-mobile-phone-android-samsung.svg-iIOhGZVY.js → computer-device-mobile-phone-android-samsung.svg-5mcZzPvQ.js} +1 -1
  85. package/web/assets/{computer-device-mobile-phone-iphone-x-back.svg-CLqnsMnT.js → computer-device-mobile-phone-iphone-x-back.svg-CovJE-GH.js} +1 -1
  86. package/web/assets/{computer-device-mobile-phone-iphone-x.svg-XECS9ZDX.js → computer-device-mobile-phone-iphone-x.svg-PgDuCiQq.js} +1 -1
  87. package/web/assets/{computer-device-mobile-tablet-touch.svg-CUR9IhGB.js → computer-device-mobile-tablet-touch.svg-1xFu6tBt.js} +1 -1
  88. package/web/assets/{computer-device-mobile-tablet.svg-BJGisjBt.js → computer-device-mobile-tablet.svg-lvKpoZnh.js} +1 -1
  89. package/web/assets/{computer-device-network-ethernet-cat6.svg-DzgiswAZ.js → computer-device-network-ethernet-cat6.svg-BJ6jNe-4.js} +1 -1
  90. package/web/assets/{computer-device-network-lan-www.svg-Dr1frFpv.js → computer-device-network-lan-www.svg-D2V9EO5w.js} +1 -1
  91. package/web/assets/{computer-device-network-wifi-connection.svg-DSj6qxT1.js → computer-device-network-wifi-connection.svg-DhFLYNK0.js} +1 -1
  92. package/web/assets/{computer-device-network-wifi-router.svg-8lGzw_-s.js → computer-device-network-wifi-router.svg-BGWV2N2B.js} +1 -1
  93. package/web/assets/{cssMode-sBjZEJAf.js → cssMode-Q_UQl6r1.js} +1 -1
  94. package/web/assets/{divider-p4BForJk.js → divider-D2zmU0b9.js} +2 -2
  95. package/web/assets/{docx-preview-D-bfEEBT.js → docx-preview-CAEo0pZg.js} +1 -1
  96. package/web/assets/{ecology-science-erlenmeyer-flask.svg-DhxVJRJ1.js → ecology-science-erlenmeyer-flask.svg-D4Cb7DOj.js} +1 -1
  97. package/web/assets/{fieldset-CCZ1tJUm.js → fieldset-CvPPXvgb.js} +2 -2
  98. package/web/assets/{freemarker2-C8iPD1fo.js → freemarker2-CCRi9jHA.js} +1 -1
  99. package/web/assets/{handlebars-BbBZAhwL.js → handlebars-4FU6Ze_N.js} +1 -1
  100. package/web/assets/{html-BQ_SV3Jd.js → html-1I40tTPC.js} +1 -1
  101. package/web/assets/{htmlMode-DReHoZFB.js → htmlMode-DQrNrxvx.js} +1 -1
  102. package/web/assets/{image-flash-lightning.svg-DbKHX2c2.js → image-flash-lightning.svg-Bh48o-tL.js} +1 -1
  103. package/web/assets/{image-picture-flower.svg-CEpqP8le.js → image-picture-flower.svg-CE0C3oid.js} +1 -1
  104. package/web/assets/{index-PMr5ScNs.js → index-SrQFBx_K.js} +36 -36
  105. package/web/assets/{interface-alert-exclamation-diamond.svg-CoNNtahD.js → interface-alert-exclamation-diamond.svg-Dzt9JrNZ.js} +1 -1
  106. package/web/assets/{interface-alert-exclamation-triangle-warning.svg-BHa7AW0u.js → interface-alert-exclamation-triangle-warning.svg-CET5JCIK.js} +1 -1
  107. package/web/assets/{interface-alert-information-circle.svg-CpRzO-l8.js → interface-alert-information-circle.svg-GX_R0hCS.js} +1 -1
  108. package/web/assets/{interface-award-crown.svg-BFOXAZFu.js → interface-award-crown.svg-BUS_3snr.js} +1 -1
  109. package/web/assets/{interface-bookmark.svg-DulnuoPg.js → interface-bookmark-tag.svg-GOtO3ous.js} +1 -1
  110. package/web/assets/{interface-bookmark-tag.svg-DpZGlSV4.js → interface-bookmark.svg-B1HfpZ9v.js} +1 -1
  111. package/web/assets/{interface-calendar-date-one.svg-CWQHbXWQ.js → interface-calendar-date-one.svg-W8G2NQFL.js} +1 -1
  112. package/web/assets/{interface-content-book-open-pages.svg-BH97UDUJ.js → interface-content-book-open-pages.svg-0dUMuEJV.js} +1 -1
  113. package/web/assets/{interface-content-book-page.svg-DmnJkpeN.js → interface-content-book-page.svg-BZ9dLtQQ.js} +1 -1
  114. package/web/assets/{interface-content-file.svg-DkouOQzj.js → interface-content-file.svg-C5JU1QaC.js} +1 -1
  115. package/web/assets/interface-content-folder.svg-BZAP22kT.js +1 -0
  116. package/web/assets/{interface-content-folder.svg-DK2esxIw.js → interface-content-folder.svg-DeWnODx9.js} +1 -1
  117. package/web/assets/{interface-copy-clipboard.svg-DuwyZprv.js → interface-copy-clipboard.svg-DneOONZN.js} +1 -1
  118. package/web/assets/{interface-edit-attachment.svg-C4lXPh7a.js → interface-edit-attachment.svg-BUDutqFa.js} +1 -1
  119. package/web/assets/{interface-edit-binocular.svg-CuA4f4ED.js → interface-edit-binocular.svg-DQ_sVWUa.js} +1 -1
  120. package/web/assets/{interface-edit-magic-wand.svg-D-Cc4zpI.js → interface-edit-magic-wand.svg-BqDEUbja.js} +1 -1
  121. package/web/assets/{interface-edit-tool-paint-roller.svg-MtAeMQ6k.js → interface-edit-tool-paint-roller.svg-CcbJr-sE.js} +1 -1
  122. package/web/assets/{interface-edit-tool-pencil.svg-ZAP8C3Sw.js → interface-edit-tool-pencil.svg-Dlmq9sMb.js} +1 -1
  123. package/web/assets/{interface-favorite-award.svg-DRZh5var.js → interface-favorite-award.svg-CfRf16yB.js} +1 -1
  124. package/web/assets/{interface-favorite-flag.svg-Dy0qBZak.js → interface-favorite-flag.svg-BeXa9l_o.js} +1 -1
  125. package/web/assets/{interface-favorite-heart.svg-Cjxi5AEp.js → interface-favorite-heart.svg-DWDXtfc-.js} +1 -1
  126. package/web/assets/{interface-favorite-star.svg-B1OPbNTd.js → interface-favorite-star.svg-D0my2O2z.js} +1 -1
  127. package/web/assets/{interface-favorite-stars-sparkles.svg-CvnZTUkf.js → interface-favorite-stars-sparkles.svg-DwnkpORM.js} +1 -1
  128. package/web/assets/{interface-hierarchy-flowchart.svg-GGCH0pvQ.js → interface-hierarchy-flowchart.svg-BS1qAEvQ.js} +1 -1
  129. package/web/assets/{interface-home-house.svg-DB_dC7eo.js → interface-home-house.svg-ByCGOgtp.js} +1 -1
  130. package/web/assets/{interface-hyperlink.svg-LlMqAHmb.js → interface-hyperlink.svg-D0RP2diO.js} +1 -1
  131. package/web/assets/{interface-lighting-brightness.svg-DutEgNfQ.js → interface-lighting-brightness.svg-B7Wir9fI.js} +1 -1
  132. package/web/assets/{interface-lock-closed.svg-DteyBWrL.js → interface-lock-closed.svg-D93wzWGY.js} +1 -1
  133. package/web/assets/{interface-lock-open-unlock.svg-D2g-W1Mn.js → interface-lock-open-unlock.svg-CEbreK15.js} +1 -1
  134. package/web/assets/{interface-login-key.svg-Dk1JjhYH.js → interface-login-key.svg-a_CUiiRx.js} +1 -1
  135. package/web/assets/{interface-search.svg-CDHAdhLc.js → interface-search.svg-CP6bN80a.js} +1 -1
  136. package/web/assets/{interface-setting-cog.svg-BXKxgm-B.js → interface-setting-cog.svg-C1yqB1H3.js} +1 -1
  137. package/web/assets/{interface-share-megaphone-bullhorn.svg-Fq3c3_sE.js → interface-share-megaphone-bullhorn.svg-BpEzN7dc.js} +1 -1
  138. package/web/assets/{interface-share-rocket.svg-BBIuiQ8_.js → interface-share-rocket.svg-CZTpH2do.js} +1 -1
  139. package/web/assets/{interface-share-satellite.svg-LZRzoY-Y.js → interface-share-satellite.svg-CDpvXyTq.js} +1 -1
  140. package/web/assets/{interface-share-space-ship.svg-C6EewxDh.js → interface-share-space-ship.svg-QXv4WQWa.js} +1 -1
  141. package/web/assets/{interface-share.svg-Bj60UW_t.js → interface-share.svg-DO9f8_w3.js} +1 -1
  142. package/web/assets/{interface-signal-square.svg-wJGg3ZJ7.js → interface-signal-square.svg-Dpbb94dT.js} +1 -1
  143. package/web/assets/{interface-time-clock-circle.svg-C2Ki_bgh.js → interface-time-clock-circle.svg-BOM8J4p-.js} +1 -1
  144. package/web/assets/{interface-time-hour-glass.svg-BeaTe2YW.js → interface-time-hour-glass.svg-B4wmuGrS.js} +1 -1
  145. package/web/assets/{interface-users-multiple.svg-ZNPhOLEJ.js → interface-users-multiple.svg-CX6Z1IAw.js} +1 -1
  146. package/web/assets/{interface-weather-moon.svg-CzOxK1E2.js → interface-weather-moon.svg-VjaROepI.js} +1 -1
  147. package/web/assets/{javascript-CV2jmATe.js → javascript-dnJjMqJl.js} +1 -1
  148. package/web/assets/{jsonMode-BpNATOZn.js → jsonMode-DIklAZzl.js} +2 -2
  149. package/web/assets/{liquid-Bkbhlfu6.js → liquid-DM3-T0fg.js} +1 -1
  150. package/web/assets/{lspLanguageFeatures-BIiCr6WR.js → lspLanguageFeatures-DtduOI48.js} +3 -3
  151. package/web/assets/{mail-chat-bubble-square.svg-B-R9ItyG.js → mail-chat-bubble-square.svg-BtQmLgyl.js} +1 -1
  152. package/web/assets/{mail-send-email-paper-airplane.svg-F4sC3JuQ.js → mail-send-email-paper-airplane.svg-DBzfHbzK.js} +1 -1
  153. package/web/assets/{mail-send-envelope.svg-BaE9bGol.js → mail-send-envelope.svg-ByoaJJai.js} +1 -1
  154. package/web/assets/{mdx-CsTzsRLc.js → mdx-COmjqkAf.js} +1 -1
  155. package/web/assets/{minus-CsIPqtIl.js → minus-CLTSMcUf.js} +2 -2
  156. package/web/assets/modal-BaVGcm8s.js +1 -0
  157. package/web/assets/modal-Cl434j6P.js +5 -0
  158. package/web/assets/{money-cashier-receipt.svg-C8rqn3qa.js → money-cashier-receipt.svg-D3I5UkrO.js} +1 -1
  159. package/web/assets/{money-currency-dollar-pay.svg-BW5dnMxx.js → money-currency-dollar-pay.svg-BEt_zoFT.js} +1 -1
  160. package/web/assets/{money-graph-arrow-increase.svg-fHNc8kor.js → money-graph-arrow-increase.svg-BFgo8Syp.js} +1 -1
  161. package/web/assets/{money-graph-bar-chart-increase.svg-65H_xZ15.js → money-graph-bar-chart-increase.svg-BPBRyqtM.js} +1 -1
  162. package/web/assets/{multiselect-Z0owdrkn.js → multiselect-Bd1n3-4t.js} +3 -3
  163. package/web/assets/{nature-ecology-leaf.svg-BIZVZEYz.js → nature-ecology-leaf.svg-DCIaflet.js} +1 -1
  164. package/web/assets/{password-Be5EVCzq.js → password-kxqyN9bC.js} +4 -4
  165. package/web/assets/{phone-telephone.svg-B1dHjXge.js → phone-telephone.svg-_P3X_Fym.js} +1 -1
  166. package/web/assets/{plus-BY4yX4ZS.js → plus-Cs39ICwL.js} +6 -6
  167. package/web/assets/process.store-m5afcW9w.js +1 -0
  168. package/web/assets/{programming-bug.svg-DJHBIgCF.js → programming-bug.svg-BGbIcZnS.js} +1 -1
  169. package/web/assets/{programming-cloud.svg-26MWe8cC.js → programming-cloud.svg-8TyU38aV.js} +1 -1
  170. package/web/assets/{programming-computer-database-server.svg-Dy7gdMab.js → programming-computer-database-server.svg-DBxTrFCn.js} +1 -1
  171. package/web/assets/{programming-computer-database.svg-3HsFit56.js → programming-computer-database.svg-Bi3RBUmB.js} +1 -1
  172. package/web/assets/{programming-module-four-layout.svg-CLumiwsC.js → programming-module-four-layout.svg-BicMHalL.js} +1 -1
  173. package/web/assets/{programming-module-three.svg-3DvVSvY_.js → programming-module-three.svg-D13tfKhT.js} +1 -1
  174. package/web/assets/{programming-module.svg-CgtgW8TW.js → programming-module.svg-HJDv8jeZ.js} +1 -1
  175. package/web/assets/{programming-script-code.svg-DdeXzy2-.js → programming-script-code.svg-oXFzvCKr.js} +1 -1
  176. package/web/assets/project-launch.store-Cgu622KX.js +1 -0
  177. package/web/assets/project.store-CM-kT9-z.js +1 -0
  178. package/web/assets/{python-YqWM3LFr.js → python-ejRXAr81.js} +1 -1
  179. package/web/assets/{radiobutton-Pm1c37Fw.js → radiobutton-BWBirQno.js} +2 -2
  180. package/web/assets/{razor-BtNiyC__.js → razor-CbzUoARP.js} +1 -1
  181. package/web/assets/router-o5ycRaEE.js +1 -0
  182. package/web/assets/settings-scope-CSLK3J2k.js +1 -0
  183. package/web/assets/settings.store-DDQmm1ig.js +1 -0
  184. package/web/assets/{shopping-cart.svg-ejbEU5yG.js → shopping-cart.svg-DL2Mf0BX.js} +1 -1
  185. package/web/assets/{shopping-gift-present.svg-RLuyvmga.js → shopping-gift-present.svg-keqzudV3.js} +1 -1
  186. package/web/assets/{shopping-shipping-box-parcel-package.svg-0GduEUbl.js → shopping-shipping-box-parcel-package.svg-BZ0Ri9AV.js} +1 -1
  187. package/web/assets/src-C1fYy9Ht.js +572 -0
  188. package/web/assets/src-DnhPQBBB.js +1 -0
  189. package/web/assets/{tabpanel-CssLXh-h.js → tabpanel-Bdw_XASI.js} +3 -3
  190. package/web/assets/{tag-new-circle.svg-CEdgH15R.js → tag-new-circle.svg-7tUBDDe7.js} +1 -1
  191. package/web/assets/theme-COzp71lh.js +1 -0
  192. package/web/assets/{toggleswitch-CEiGEBl3.js → toggleswitch-BhJmSx1t.js} +2 -2
  193. package/web/assets/{travel-map-earth-globe.svg-Dmwx1Lus.js → travel-map-earth-globe.svg-CfJb5_3k.js} +1 -1
  194. package/web/assets/trpc-Bn_6G8HK.js +1 -0
  195. package/web/assets/{tsMode-DpPT4F6s.js → tsMode-D5Gulgwd.js} +5 -5
  196. package/web/assets/{typescript-DoO0syM1.js → typescript-B73-3GtI.js} +1 -1
  197. package/web/assets/useAiChatDrawer-QOflawaX.js +1 -0
  198. package/web/assets/useCloudOrg-BZNmQ2Ek.js +1 -0
  199. package/web/assets/useEnvVarAutocomplete-DAxcV0jl.js +1 -0
  200. package/web/assets/useProjectCatalog-8u5wFtf-.js +1 -0
  201. package/web/assets/{useProjectCloudOrg-CG7seJKu.js → useProjectCloudOrg-Bkja4sed.js} +1 -1
  202. package/web/assets/useServiceUrlHost-biHEzQVv.js +1 -0
  203. package/web/assets/{xml-FoCdWVvH.js → xml-Mkua9fdo.js} +1 -1
  204. package/web/assets/{yaml-CgRsanOy.js → yaml-BP9pkdmT.js} +1 -1
  205. package/web/index.html +1 -1
  206. package/chunk-4PN7QBNM.js.map +0 -1
  207. package/chunk-GKK3ACWB.js.map +0 -1
  208. package/chunk-H22YLVQE.js.map +0 -1
  209. package/chunk-T2BV5WZE.js.map +0 -1
  210. package/src-SGSG2RSF.js.map +0 -1
  211. package/web/assets/AgentScalarChatInterface.vue-Bv7WQetq.js +0 -13
  212. package/web/assets/AgentTerminalPage-CMA5oI2T.js +0 -1
  213. package/web/assets/AiChatPage-C0Ho1rG3.js +0 -1
  214. package/web/assets/AppLayout-DBKRAp0R.js +0 -1
  215. package/web/assets/AuditPage-fZVhSJlE.js +0 -1
  216. package/web/assets/CloudAccountPage-2LiTQCKr.js +0 -1
  217. package/web/assets/CloudAccountPage-CunPTy1b.js +0 -1
  218. package/web/assets/CloudMessagingPage-DWciFn32.js +0 -2
  219. package/web/assets/DashboardPage-3psdQljM.js +0 -164
  220. package/web/assets/DashboardPage-DFaiJ4c-.css +0 -1
  221. package/web/assets/DirectoryPickerDialog-DiiAUQKg.js +0 -1
  222. package/web/assets/EnvironmentForm-MRC8U5op.js +0 -108
  223. package/web/assets/EnvironmentFormPage-gd8fGS8P.js +0 -1
  224. package/web/assets/EnvironmentListPage-DgbclvZs.js +0 -1
  225. package/web/assets/KanbanBoardPage-BBT0gqjT.js +0 -4
  226. package/web/assets/KanbanListPage-CidIQgAq.js +0 -1
  227. package/web/assets/LaunchProjectPage-DBtkrI-A.js +0 -1
  228. package/web/assets/LaunchServicesPage-DdmfVxYL.js +0 -1
  229. package/web/assets/LaunchServicesPage-zR9FoF4q.css +0 -1
  230. package/web/assets/LogViewer-CvDPgFjq.js +0 -3
  231. package/web/assets/OrgKeyPrompt-D3RmJEtb.js +0 -1
  232. package/web/assets/ProcessDetailPage-Dj0L8Jz0.js +0 -1
  233. package/web/assets/RandomJobTestPage-ohHAOaio.js +0 -2
  234. package/web/assets/ScenarioEditorPage-BIcmG3wo.js +0 -14
  235. package/web/assets/SendToChatDialog-oi4KFAVq.js +0 -1
  236. package/web/assets/ServiceControlsBar-BtnWYJmp.css +0 -1
  237. package/web/assets/ServiceControlsBar-GgoPszoH.js +0 -1
  238. package/web/assets/ServiceDetailPage-CIDlO0iu.js +0 -2
  239. package/web/assets/ServiceFormPage-p3AUhHLN.js +0 -1
  240. package/web/assets/SettingsPage-B_heumvd.js +0 -2063
  241. package/web/assets/UnlockPage-nz_1VQWy.js +0 -1
  242. package/web/assets/VaultMigrationPage-B_nZC8Cc.js +0 -1
  243. package/web/assets/VersionBadge-DJJK7bgD.js +0 -1
  244. package/web/assets/WikiPage-DiCUjWEu.js +0 -1
  245. package/web/assets/WikiView-vYMnLt41.js +0 -1
  246. package/web/assets/add-scalar-classes-_7NDhIUO.js +0 -387
  247. package/web/assets/client-DHQNUKOx.js +0 -24
  248. package/web/assets/cloud-chat.store-CaSRn8Mg.js +0 -1
  249. package/web/assets/cloud-client-CzGojtBl.js +0 -1
  250. package/web/assets/cloud-session-D71P4F3g.js +0 -2
  251. package/web/assets/cloud-session-DlLnrwVQ.js +0 -1
  252. package/web/assets/column-CjJa3tsz.js +0 -763
  253. package/web/assets/interface-content-folder.svg-BLBb2W1v.js +0 -1
  254. package/web/assets/modal-B_0-h4nC.js +0 -1
  255. package/web/assets/modal-KwmdNF_4.js +0 -5
  256. package/web/assets/process.store-B-PvNJQb.js +0 -1
  257. package/web/assets/project-launch.store-DtFeb4vv.js +0 -1
  258. package/web/assets/project.store-DcaBpnnB.js +0 -1
  259. package/web/assets/router-DnVYXVMw.js +0 -1
  260. package/web/assets/settings-scope-DR8NUZr5.js +0 -1
  261. package/web/assets/settings.store-CniuNQ3t.js +0 -1
  262. package/web/assets/src-BS3JGGS_.js +0 -1
  263. package/web/assets/src-BzZzroPd.js +0 -572
  264. package/web/assets/theme-C7HVmgEO.js +0 -1
  265. package/web/assets/trpc-C6zILEMh.js +0 -1
  266. package/web/assets/useAiChatDrawer-CnrYG1GW.js +0 -1
  267. package/web/assets/useCloudOrg-DWmP9gqs.js +0 -1
  268. package/web/assets/useEnvVarAutocomplete-Dkx7Cn9l.js +0 -1
  269. package/web/assets/useProjectCatalog-Cu3VZu2F.js +0 -1
  270. package/web/assets/useServiceUrlHost-ADKWqhx0.js +0 -1
  271. /package/{settings-manager-MAVD4GAS.js.map → agent-manager-QLXVQ7OD.js.map} +0 -0
  272. /package/{companion-OZODV5BR.js.map → chat-ODBVFMKX.js.map} +0 -0
  273. /package/{chunk-N3ZI35SC.js.map → chunk-K7A3Q62R.js.map} +0 -0
  274. /package/{chat-JIJQ7IJS.js.map → companion-5DPH3HIO.js.map} +0 -0
  275. /package/{desktop-launcher-EGGVXXKV.js.map → desktop-launcher-J2BCSSGZ.js.map} +0 -0
  276. /package/{agent-manager-FZFFWISA.js.map → settings-manager-E3L56VAY.js.map} +0 -0
@@ -3,9 +3,1214 @@
3
3
  // src/index.ts
4
4
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
5
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import { z as z24 } from "zod";
7
+
8
+ // ../ai-capabilities/dist/index.js
9
+ import { z as z22 } from "zod";
10
+
11
+ // ../shared/dist/index.js
6
12
  import { z } from "zod";
13
+ import { z as z2 } from "zod";
14
+ import { z as z3 } from "zod";
15
+ import { z as z7 } from "zod";
16
+ import { z as z5 } from "zod";
17
+ import { z as z4 } from "zod";
18
+ import { z as z6 } from "zod";
19
+ import { z as z8 } from "zod";
20
+ import { z as z9 } from "zod";
21
+ import { z as z10 } from "zod";
22
+ import { z as z11 } from "zod";
23
+ import { z as z12 } from "zod";
24
+ import { z as z13 } from "zod";
25
+ import { z as z14 } from "zod";
26
+ import { z as z15 } from "zod";
27
+ import { z as z16 } from "zod";
28
+ import { z as z17 } from "zod";
29
+ import { z as z18 } from "zod";
30
+ import { z as z19 } from "zod";
31
+ import { z as z20 } from "zod";
32
+ import { z as z21 } from "zod";
33
+ import { createCipheriv, createDecipheriv, randomBytes, pbkdf2Sync } from "crypto";
34
+ import vm from "vm";
35
+ import * as Y from "yjs";
36
+ var UserSchema = z.object({
37
+ id: z.string().max(128),
38
+ email: z.string().email().max(320),
39
+ name: z.string().min(1).max(500),
40
+ avatar: z.string().url().max(2048).nullable().optional()
41
+ });
42
+ var OrgSchema = z2.object({
43
+ id: z2.string().max(128),
44
+ name: z2.string().min(1).max(100),
45
+ slug: z2.string().min(1).max(100).regex(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/),
46
+ ownerId: z2.string().max(128)
47
+ });
48
+ var OrgMemberSchema = z2.object({
49
+ id: z2.string().max(128),
50
+ orgId: z2.string().max(128),
51
+ userId: z2.string().max(128),
52
+ globalRole: z2.enum(["owner", "admin", "member"]),
53
+ invitedAt: z2.coerce.date(),
54
+ joinedAt: z2.coerce.date().nullable().optional()
55
+ });
56
+ var ProjectSchema = z3.object({
57
+ id: z3.string().max(128),
58
+ orgId: z3.string().max(128).nullable().optional(),
59
+ name: z3.string().min(1).max(200),
60
+ description: z3.string().max(1e4).optional().default(""),
61
+ serviceIds: z3.array(z3.string().max(128)).max(1e4).default([]),
62
+ // Environment support
63
+ // NOTE: activeEnvironmentId is runtime-only (not persisted to JSON)
64
+ // It's initialized to 'local' by default at load time
65
+ activeEnvironmentId: z3.string().max(128).optional(),
66
+ environmentIds: z3.array(z3.string().max(128)).max(100).default([]),
67
+ // Ordre d'affichage des groupes de services dans la sidebar (noms de groupes).
68
+ // Les groupes absents de cette liste sont affichés après, par ordre alphabétique.
69
+ groupOrder: z3.array(z3.string().max(200)).max(100).default([])
70
+ });
71
+ var CreateProjectSchema = ProjectSchema.omit({ id: true }).partial().required({ name: true });
72
+ var UpdateProjectSchema = ProjectSchema.partial().required({ id: true });
73
+ var PositionSchema = z4.object({
74
+ x: z4.number(),
75
+ y: z4.number()
76
+ });
77
+ var ScenarioGroupSchema = z4.object({
78
+ id: z4.string().min(1).max(128),
79
+ name: z4.string().min(1).max(200),
80
+ description: z4.string().max(1e3).optional(),
81
+ color: z4.string().max(32).optional(),
82
+ position: PositionSchema.default({ x: 0, y: 0 }),
83
+ width: z4.number().default(300),
84
+ height: z4.number().default(200)
85
+ });
86
+ var ScenarioPresetRoleSchema = z4.object({
87
+ id: z4.string().min(1).max(64),
88
+ name: z4.string().min(1).max(200),
89
+ systemPrompt: z4.string().max(1e4).default(""),
90
+ prompt: z4.string().max(1e4).default("")
91
+ });
92
+ var ScenarioPresetInitialDataSchema = z4.object({
93
+ leaderId: z4.string().min(1).max(128),
94
+ groups: z4.array(z4.object({
95
+ id: z4.string().min(1).max(128),
96
+ name: z4.string().min(1).max(200),
97
+ description: z4.string().max(1e3).optional(),
98
+ color: z4.string().max(32).optional(),
99
+ position: z4.object({ x: z4.number(), y: z4.number() }).default({ x: 0, y: 0 }),
100
+ width: z4.number().default(300),
101
+ height: z4.number().default(200)
102
+ })).max(100).default([]),
103
+ nodes: z4.array(z4.object({
104
+ id: z4.string().min(1).max(128),
105
+ type: z4.enum(["ai", "ask"]).default("ai"),
106
+ parentIds: z4.array(z4.string().max(128)).default([]),
107
+ groupId: z4.string().max(128).nullable().default(null),
108
+ label: z4.string().max(240).default(""),
109
+ role: z4.string().max(64).default("other"),
110
+ prompt: z4.string().max(5e4).default(""),
111
+ question: z4.string().max(2e3).default(""),
112
+ autoGenerated: z4.boolean().default(true),
113
+ canAddNode: z4.boolean().default(false),
114
+ aiCli: z4.enum(["claude-code", "codex"]).default("claude-code"),
115
+ model: z4.string().max(128).default("sonnet"),
116
+ position: z4.object({ x: z4.number(), y: z4.number() }).default({ x: 0, y: 0 })
117
+ })).min(1).max(500)
118
+ });
119
+ var LocalizedStringSchema = z4.record(z4.string(), z4.string().max(100));
120
+ var ScenarioPresetLabelsSchema = z4.object({
121
+ group: LocalizedStringSchema.optional(),
122
+ node: LocalizedStringSchema.optional(),
123
+ role: LocalizedStringSchema.optional(),
124
+ leader: LocalizedStringSchema.optional()
125
+ });
126
+ var ScenarioPresetSchema = z4.object({
127
+ id: z4.string().min(1).max(128),
128
+ name: z4.string().min(1).max(200),
129
+ icon: z4.string().max(64).optional(),
130
+ defaultTraversalMode: z4.enum(["hierarchical", "topological"]).optional(),
131
+ canChangeTraversalMode: z4.boolean().default(true),
132
+ roles: z4.array(ScenarioPresetRoleSchema).min(1).max(100),
133
+ initialData: ScenarioPresetInitialDataSchema.optional(),
134
+ labels: ScenarioPresetLabelsSchema.optional()
135
+ });
136
+ var ScenarioNodeSchema = z4.object({
137
+ id: z4.string().min(1).max(128),
138
+ type: z4.enum(["ai", "ask"]).default("ai"),
139
+ parentIds: z4.array(z4.string().max(128)).default([]),
140
+ groupId: z4.string().max(128).nullable().default(null),
141
+ label: z4.string().max(240).default(""),
142
+ role: z4.string().max(64).default("other"),
143
+ prompt: z4.string().max(5e4).default(""),
144
+ question: z4.string().max(2e3).default(""),
145
+ autoGenerated: z4.boolean().default(true),
146
+ canAddNode: z4.boolean().default(false),
147
+ aiCli: z4.enum(["claude-code", "codex"]).default("claude-code"),
148
+ model: z4.string().max(128).default("sonnet"),
149
+ position: PositionSchema.default({ x: 0, y: 0 }),
150
+ injectParentOutputs: z4.boolean().default(false),
151
+ injectedAncestorIds: z4.array(z4.string().max(128)).default([])
152
+ });
153
+ var ScenarioSchema = z4.object({
154
+ id: z4.string().min(1).max(128),
155
+ name: z4.string().min(1).max(200),
156
+ icon: z4.string().max(64).optional(),
157
+ description: z4.string().max(2e3).optional(),
158
+ leaderId: z4.string().min(1).max(128),
159
+ groups: z4.array(ScenarioGroupSchema).max(100).default([]),
160
+ nodes: z4.array(ScenarioNodeSchema).min(1).max(500),
161
+ traversalMode: z4.enum(["hierarchical", "topological"]).default("hierarchical"),
162
+ presetId: z4.string().max(128).optional(),
163
+ isPublished: z4.boolean().default(false),
164
+ createdAt: z4.number(),
165
+ updatedAt: z4.number()
166
+ });
167
+ var AI_PROVIDERS = ["anthropic", "openai", "mistral", "groq", "ollama"];
168
+ var AIProviderSchema = z5.object({
169
+ id: z5.string().min(1).max(128),
170
+ name: z5.string().min(1).max(200),
171
+ provider: z5.enum(AI_PROVIDERS),
172
+ encryptedApiKey: z5.string().max(2e3).default(""),
173
+ model: z5.string().max(200).optional(),
174
+ active: z5.boolean().default(false),
175
+ createdAt: z5.coerce.date(),
176
+ updatedAt: z5.coerce.date()
177
+ });
178
+ var JSLogParserSchema = z5.object({
179
+ id: z5.string().min(1).max(128),
180
+ name: z5.string().min(1).max(200),
181
+ description: z5.string().max(2e3).optional(),
182
+ code: z5.string().min(1).max(5e4).refine(
183
+ (s) => !s.includes("require(") && !s.includes("import ") && !s.includes("eval("),
184
+ { message: "Code must not contain require, import, or eval patterns" }
185
+ ),
186
+ enabled: z5.boolean().default(true),
187
+ builtin: z5.boolean().optional(),
188
+ createdAt: z5.coerce.date(),
189
+ updatedAt: z5.coerce.date()
190
+ });
191
+ var NotificationPreferencesSchema = z5.object({
192
+ scenario_waiting_input: z5.boolean().default(true),
193
+ ai_conversation_complete: z5.boolean().default(true),
194
+ ai_conversation_error: z5.boolean().default(true),
195
+ service_error_log: z5.boolean().default(true),
196
+ service_status_changed: z5.boolean().default(true),
197
+ service_health_changed: z5.boolean().default(true),
198
+ /** Service IDs excluded from error-log notifications */
199
+ service_error_log_excluded: z5.array(z5.string().max(100)).max(500).default([]),
200
+ /** Service IDs excluded from status-change notifications */
201
+ service_status_changed_excluded: z5.array(z5.string().max(100)).max(500).default([]),
202
+ /** Service IDs excluded from health-change notifications */
203
+ service_health_changed_excluded: z5.array(z5.string().max(100)).max(500).default([])
204
+ });
205
+ var CompanionSettingsSchema = z5.object({
206
+ /** Activer le compagnon d'office sur les conversations créées ensuite. */
207
+ enabledByDefault: z5.boolean().default(false),
208
+ /**
209
+ * Spécificités ajoutées aux consignes Runeya.
210
+ *
211
+ * Vide — l'absence — signifie « aucune spécificité ». On ne recopie pas le
212
+ * texte par défaut dans le réglage : les consignes Runeya restent dans le
213
+ * code, pour profiter de leurs corrections.
214
+ *
215
+ * Rejeté au-delà de la borne plutôt que tronqué (§1) : un prompt coupé en
216
+ * plein milieu produirait des relectures incohérentes sans rien signaler.
217
+ */
218
+ prompt: z5.string().max(2e4).optional()
219
+ });
220
+ var SettingsSchema = z5.object({
221
+ mode: z5.enum(["local-simple", "cloud"]),
222
+ cloudUrl: z5.string().url().max(2048).nullable().optional(),
223
+ logParsers: z5.array(JSLogParserSchema).max(100).default([]),
224
+ scenarios: z5.array(ScenarioSchema).max(100).default([]),
225
+ /** Absolute path to the folder where the global wiki/docs markdown files live. Optional. */
226
+ globalDocsPath: z5.string().max(4096).optional(),
227
+ /**
228
+ * Optionnel plutôt que défauté : un réglage absent est un réglage jamais
229
+ * touché, et le rendre obligatoire dans le type forcerait chaque appelant qui
230
+ * construit un objet de réglages à inventer une valeur.
231
+ */
232
+ companion: CompanionSettingsSchema.optional()
233
+ });
234
+ var TraefikConfigSchema = z5.object({
235
+ enabled: z5.boolean().default(false),
236
+ acmeEmail: z5.string().email().max(256).optional(),
237
+ wildcardDomain: z5.string().max(253).optional(),
238
+ httpPort: z5.number().int().min(1).max(65535).default(80),
239
+ httpsPort: z5.number().int().min(1).max(65535).default(443),
240
+ dnsProvider: z5.string().max(64).optional(),
241
+ dnsCredentials: z5.record(z5.string().max(64), z5.string().max(2048)).default({}),
242
+ acmeStaging: z5.boolean().default(false),
243
+ encryptedCert: z5.string().max(65536).optional(),
244
+ encryptedCertKey: z5.string().max(65536).optional()
245
+ });
246
+ var SettingsPrivateSchema = z5.object({
247
+ aiProviders: z5.array(AIProviderSchema).max(50).default([]),
248
+ scenarios: z5.array(ScenarioSchema).max(100).default([]),
249
+ notifications: NotificationPreferencesSchema.default(() => ({
250
+ scenario_waiting_input: true,
251
+ ai_conversation_complete: true,
252
+ ai_conversation_error: true,
253
+ service_error_log: true,
254
+ service_status_changed: true,
255
+ service_health_changed: true,
256
+ service_error_log_excluded: [],
257
+ service_status_changed_excluded: [],
258
+ service_health_changed_excluded: []
259
+ })),
260
+ traefikConfig: TraefikConfigSchema.optional()
261
+ });
262
+ var SchemaVersionSchema = z5.object({
263
+ version: z5.number().int().positive(),
264
+ migratedAt: z5.coerce.date()
265
+ });
266
+ var safePath = z6.string().min(1).max(4096).refine(
267
+ (p) => !p.includes("\0"),
268
+ { message: "path must not contain null bytes" }
269
+ ).refine(
270
+ (p) => !/(^|[/\\])\.\.([/\\]|$)/.test(p),
271
+ { message: "path must not contain path-traversal sequences (..)" }
272
+ );
273
+ var ConsoleLogSourceSchema = z6.object({
274
+ type: z6.literal("console")
275
+ });
276
+ var FileLogSourceSchema = z6.object({
277
+ type: z6.literal("file"),
278
+ path: safePath,
279
+ encoding: z6.string().max(32).default("utf-8"),
280
+ startFromEnd: z6.boolean().default(true),
281
+ createIfNotExists: z6.boolean().default(false)
282
+ });
283
+ var MongoLogSourceSchema = z6.object({
284
+ type: z6.literal("mongo"),
285
+ /** @sensitive — stored encrypted (AES-256-GCM) on disk */
286
+ connectionString: z6.string().min(1).max(2048),
287
+ database: z6.string().min(1).max(256),
288
+ collection: z6.string().min(1).max(256),
289
+ filter: z6.record(z6.string(), z6.unknown()).optional(),
290
+ timestampField: z6.string().max(128).default("timestamp"),
291
+ messageField: z6.string().max(128).default("message"),
292
+ levelField: z6.string().max(128).optional()
293
+ });
294
+ var MySQLLogSourceSchema = z6.object({
295
+ type: z6.literal("mysql"),
296
+ host: z6.string().min(1).max(253),
297
+ port: z6.number().int().min(1).max(65535).default(3306),
298
+ user: z6.string().min(1).max(256),
299
+ /** @sensitive — stored encrypted (AES-256-GCM) on disk */
300
+ password: z6.string().max(2048),
301
+ database: z6.string().min(1).max(256),
302
+ table: z6.string().min(1).max(256),
303
+ query: z6.string().max(8192).optional(),
304
+ timestampColumn: z6.string().max(128).default("created_at"),
305
+ messageColumn: z6.string().max(128).default("message"),
306
+ levelColumn: z6.string().max(128).optional(),
307
+ pollIntervalMs: z6.number().int().min(500).max(6e4).default(2e3)
308
+ });
309
+ var LogSourceConfigSchema = z6.discriminatedUnion("type", [
310
+ ConsoleLogSourceSchema,
311
+ FileLogSourceSchema,
312
+ MongoLogSourceSchema,
313
+ MySQLLogSourceSchema
314
+ ]);
315
+ var HealthCheckSchema = z7.object({
316
+ type: z7.enum(["http", "command"]).default("http"),
317
+ // HTTP-specific (required when type=http)
318
+ path: z7.string().min(1).max(500).startsWith("/").optional(),
319
+ method: z7.enum(["GET", "HEAD", "POST", "PUT"]).optional().default("GET"),
320
+ expectedStatus: z7.number().int().min(100).max(599).optional().default(200),
321
+ // Command-specific (required when type=command)
322
+ command: z7.string().min(1).max(4096).optional(),
323
+ // Shared
324
+ interval: z7.number().int().positive().default(1e3),
325
+ timeout: z7.number().int().positive().default(1e3),
326
+ retries: z7.number().int().nonnegative().default(3),
327
+ initialDelay: z7.number().int().nonnegative().optional().default(0)
328
+ }).refine(
329
+ (data) => data.type === "http" ? !!data.path : !!data.command,
330
+ { message: "HTTP type requires path; command type requires command" }
331
+ );
332
+ var BootstrapCommandSchema = z7.object({
333
+ id: z7.string().min(1).max(64),
334
+ label: z7.string().max(200).default(""),
335
+ entrypoint: z7.string().max(4096).optional(),
336
+ command: z7.string().max(4096).default(""),
337
+ user: z7.string().max(256).optional()
338
+ });
339
+ var DockerConfigSchema = z7.object({
340
+ // Image mode (pull from registry) — mutually exclusive with build mode in UI
341
+ image: z7.string().min(1).max(1024).optional(),
342
+ // Build mode — Dockerfile stored inline in services.json
343
+ dockerfile: z7.string().max(65536).optional(),
344
+ buildContext: z7.string().max(4096).optional(),
345
+ buildArgs: z7.record(z7.string().max(256), z7.string().max(4096)).default({}).refine(
346
+ (obj) => Object.keys(obj).length <= 50,
347
+ { message: "Max 50 build args" }
348
+ ),
349
+ targetStage: z7.string().max(256).optional(),
350
+ // Runtime config
351
+ networkMode: z7.enum(["host", "bridge"]).default("host"),
352
+ ports: z7.array(z7.string().max(64)).max(100).default([]),
353
+ volumes: z7.array(z7.string().max(1024)).max(100).default([]),
354
+ mountRootpath: z7.boolean().default(false),
355
+ entrypoint: z7.string().max(4096).optional(),
356
+ command: z7.string().max(4096).optional(),
357
+ user: z7.string().max(256).optional(),
358
+ useNativeCommand: z7.boolean().default(false),
359
+ nativeCommandMode: z7.enum(["shared", "isolated"]).default("isolated"),
360
+ nativeShell: z7.string().max(256).default("sh"),
361
+ bootstrapCommands: z7.array(BootstrapCommandSchema).max(20).default([])
362
+ });
363
+ var RestartStrategySchema = z7.enum(["none", "on-failure", "always", "unless-stopped"]).default("none");
364
+ var ServiceShortcutSchema = z7.object({
365
+ id: z7.string().min(1).max(64),
366
+ label: z7.string().max(200).default(""),
367
+ command: z7.string().max(4096).default(""),
368
+ cwd: z7.string().max(4096).optional()
369
+ });
370
+ var ServiceCommandSchema = z7.object({
371
+ id: z7.string().min(1).max(64),
372
+ label: z7.string().max(200).default(""),
373
+ command: z7.string().max(4096).default(""),
374
+ cwd: z7.string().max(4096).optional(),
375
+ shell: z7.boolean().optional().default(true)
376
+ });
377
+ var VariableSlotSchema = z7.object({
378
+ value: z7.string().max(8192).default(""),
379
+ pre: z7.string().max(8192).default(""),
380
+ post: z7.string().max(8192).default(""),
381
+ isSecret: z7.boolean().default(false),
382
+ // Deux décisions distinctes, et il ne faut pas les confondre :
383
+ //
384
+ // - `shareWithAi` est une permission de **lecture** : une IA (le chat de
385
+ // Runeya, un agent par le serveur MCP) peut voir la valeur de ce secret.
386
+ // Une variable publique est lisible de toute façon, le drapeau ne la
387
+ // concerne pas.
388
+ // - `injectIntoAi` est une **exécution** : la variable est posée dans
389
+ // l'environnement du process des agents (Claude Code, Codex, …) lancés
390
+ // depuis Runeya pendant que cet environnement est actif.
391
+ //
392
+ // Les deux sont opt-in : sans rien cocher, aucun secret ne part vers une IA.
393
+ // Injecter implique lire (ce que le process reçoit, l'agent le voit), donc
394
+ // la lecture accepte l'un OU l'autre : voir `isSharedWithAi`, qui est le seul
395
+ // endroit où cette règle s'écrit.
396
+ shareWithAi: z7.boolean().default(false),
397
+ injectIntoAi: z7.boolean().default(false),
398
+ // Une variable obligatoire doit avoir une valeur finale non vide avant qu'un
399
+ // service de cet environnement puisse démarrer. Le démarrage est refusé
400
+ // sinon, avec la liste des manquantes — l'assistant est le moyen de remplir.
401
+ required: z7.boolean().default(false),
402
+ // Une variable « seulement surchargeable » n'a jamais de valeur partagée :
403
+ // `value` reste vide dans le document synchronisé, et chaque poste DOIT
404
+ // fournir sa propre surcharge machine-locale (chemin local, jeton personnel).
405
+ // `pre` et `post` restent partagés — ils décrivent la forme, pas le secret.
406
+ overrideOnly: z7.boolean().default(false),
407
+ // À quoi sert cette variable, pour quelqu'un qui doit la remplir. Affichée
408
+ // par l'assistant de complétion et dans l'éditeur.
409
+ //
410
+ // Du **markdown**, pas du texte brut : une description gagne à pouvoir
411
+ // pointer vers la console qui délivre le jeton. Écrite et relue par le même
412
+ // éditeur Tiptap (`packages/editor-ui`), jamais injectée en HTML — Tiptap
413
+ // analyse le markdown dans son propre schéma, si bien qu'une description
414
+ // arrivée d'un autre poste par la synchronisation ne peut rien exécuter.
415
+ description: z7.string().max(2e3).default("")
416
+ }).refine(
417
+ (slot) => !slot.overrideOnly || slot.value === "",
418
+ { message: "An override-only variable cannot carry a shared value", path: ["value"] }
419
+ );
420
+ var MissingVariableReasonSchema = z7.enum(["required", "overrideOnly"]);
421
+ var MissingVariableSchema = z7.object({
422
+ variableId: z7.string().max(128),
423
+ key: z7.string().max(256),
424
+ description: z7.string().max(2e3),
425
+ reason: MissingVariableReasonSchema,
426
+ isSecret: z7.boolean(),
427
+ environmentId: z7.string().max(128),
428
+ environmentName: z7.string().max(200)
429
+ });
430
+ var VariableSchema = z7.object({
431
+ key: z7.string().min(1).max(256),
432
+ value: VariableSlotSchema
433
+ });
434
+ var VariablesRecordSchema = z7.record(
435
+ z7.string().max(128),
436
+ VariableSchema
437
+ ).refine(
438
+ (obj) => Object.keys(obj).length <= 200,
439
+ { message: "Max 200 variables" }
440
+ );
441
+ var VariableSlotsRecordSchema = z7.record(
442
+ z7.string().max(256),
443
+ VariableSlotSchema
444
+ ).refine(
445
+ (obj) => Object.keys(obj).length <= 200,
446
+ { message: "Max 200 variable slots" }
447
+ );
448
+ var ServiceConfigSchema = z7.object({
449
+ id: z7.string().max(128),
450
+ orgId: z7.string().max(128).nullable().optional(),
451
+ agentId: z7.string().max(128).optional(),
452
+ // Optional: if absent, inherited from active environment's agentId
453
+ name: z7.string().min(1).max(200),
454
+ commands: z7.array(ServiceCommandSchema).max(50).optional().default([]),
455
+ cwd: z7.string().max(4096).optional(),
456
+ ports: z7.array(z7.number().int().positive().max(65535)).max(20).optional().default([]),
457
+ // Metadata fields (migration from old Runeya)
458
+ groups: z7.array(z7.string().max(200)).max(20).optional().default([]),
459
+ description: z7.string().max(2e3).optional(),
460
+ /** Path (relative to service.cwd or absolute) where the service's docs/wiki markdown files live. Optional — defaults to service.cwd. */
461
+ docsPath: z7.string().max(4096).optional(),
462
+ url: z7.string().max(2048).optional(),
463
+ localUrls: z7.array(z7.object({
464
+ url: z7.string().max(253).regex(/^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$/),
465
+ port: z7.number().int().min(1).max(65535)
466
+ })).max(20).optional().default([]),
467
+ openapiUrl: z7.string().max(2048).optional(),
468
+ git: z7.object({
469
+ remote: z7.string().max(2048).optional(),
470
+ home: z7.string().max(2048).optional()
471
+ }).optional(),
472
+ meta: z7.record(z7.string().max(256), z7.string().max(2e3)).optional().refine((obj) => !obj || Object.keys(obj).length <= 100, { message: "Too many meta keys (max 100)" }),
473
+ // Transient env dict (resolved by server before deployment, used directly by agent runner — NOT persisted)
474
+ env: z7.record(z7.string().max(256), z7.string().max(8192)).default({}).refine(
475
+ (obj) => Object.keys(obj).length <= 200,
476
+ { message: "Too many env vars (max 200)" }
477
+ ),
478
+ envSecrets: z7.array(z7.string().max(256)).max(200).default([]),
479
+ // Transient: resolved JS log parsers (from parserIds, resolved by server before deployment — NOT persisted)
480
+ resolvedLogParsers: z7.array(JSLogParserSchema).default([]).optional(),
481
+ // Transient: resolved working directory (cwd with env vars expanded — NOT persisted)
482
+ resolvedCwd: z7.string().optional(),
483
+ runner: z7.enum(["native", "docker"]).optional().default("native"),
484
+ dockerConfig: DockerConfigSchema.optional(),
485
+ healthCheck: HealthCheckSchema.optional(),
486
+ parserIds: z7.array(z7.string().max(128)).max(50).default([]),
487
+ shortcuts: z7.array(ServiceShortcutSchema).max(50).optional().default([]),
488
+ autoRestart: z7.boolean().optional().default(false),
489
+ clearLogsOnStart: z7.boolean().optional().default(false),
490
+ restartStrategy: RestartStrategySchema.optional(),
491
+ maxRestarts: z7.number().int().nonnegative().optional(),
492
+ restartBackoffMs: z7.number().int().positive().optional().default(1e3),
493
+ // Log sources additionnelles (au-delà du stdout/stderr console par défaut)
494
+ logSources: z7.array(LogSourceConfigSchema).max(20).optional().default([])
495
+ });
496
+ var CreateServiceSchema = ServiceConfigSchema.omit({ id: true }).partial().required({ name: true });
497
+ var UpdateServiceSchema = ServiceConfigSchema.partial().required({ id: true }).extend({
498
+ agentId: z7.string().max(128).nullable().optional(),
499
+ // null = clear (inherit from env), undefined = no change
500
+ cwd: z7.string().max(4096).nullable().optional(),
501
+ git: z7.object({ remote: z7.string().max(2048).optional(), home: z7.string().max(2048).optional() }).nullable().optional(),
502
+ meta: z7.record(z7.string().max(256), z7.string().max(2e3)).nullable().optional().refine((obj) => !obj || Object.keys(obj).length <= 100, { message: "Too many meta keys (max 100)" }),
503
+ healthCheck: HealthCheckSchema.nullable().optional()
504
+ });
505
+ var ProcessStateSchema = z8.enum(["starting", "running", "stopped", "errored"]);
506
+ var HealthStatusSchema = z8.enum(["healthy", "unhealthy", "unknown"]);
507
+ var ProcessStatusSchema = z8.object({
508
+ id: z8.string().max(128),
509
+ serviceId: z8.string().max(128),
510
+ agentId: z8.string().max(128),
511
+ state: ProcessStateSchema,
512
+ pid: z8.number().int().nullable().optional(),
513
+ pids: z8.array(z8.number().int()).optional().default([]),
514
+ exitCode: z8.number().int().nullable().optional(),
515
+ startedAt: z8.coerce.date().nullable().optional(),
516
+ restartCount: z8.number().int().nonnegative().default(0),
517
+ uptime: z8.number().nonnegative().default(0),
518
+ healthStatus: HealthStatusSchema.default("unknown"),
519
+ /**
520
+ * Le répertoire où le processus s'exécute VRAIMENT, absolutisé par l'agent.
521
+ *
522
+ * Rapporté par l'agent plutôt que déduit de la config : entre le `cwd` de la
523
+ * commande, celui du service, l'ancrage sur le projet et les variables que
524
+ * l'agent étend lui-même, la valeur affichée n'aurait rien prouvé. Ce qui
525
+ * intéresse quand un service tourne contre le mauvais dépôt, c'est le chemin
526
+ * final — y compris quand il retombe sur le répertoire de l'agent.
527
+ */
528
+ cwd: z8.string().max(4096).nullable().optional()
529
+ });
530
+ var LogLevelSchema = z9.enum(["debug", "info", "warn", "error", "fatal"]);
531
+ var LogLineSchema = z9.object({
532
+ /** Raw log line as received from the process (immutable context) */
533
+ raw: z9.string(),
534
+ /** Source stream (immutable context) */
535
+ stream: z9.enum(["stdout", "stderr"]),
536
+ /** Severity level */
537
+ level: LogLevelSchema,
538
+ /** Parsed/enriched message to display */
539
+ message: z9.string(),
540
+ /** When true, the line is hidden from the log view */
541
+ hidden: z9.boolean(),
542
+ /** Arbitrary key/value pairs shown in the detail panel */
543
+ metadata: z9.record(z9.string().max(256), z9.unknown()).refine(
544
+ (obj) => Object.keys(obj).length <= 100,
545
+ { message: "Too many metadata keys (max 100)" }
546
+ ),
547
+ /** Full parsed JSON object when the line is JSON */
548
+ json: z9.record(z9.string(), z9.unknown()).optional(),
549
+ /** Custom header for the JSON log card (supports HTML, sanitized before display) */
550
+ jsonHeader: z9.string().max(256).optional()
551
+ });
552
+ var LogCardDirectiveSchema = z9.object({
553
+ id: z9.string().max(128),
554
+ type: z9.string().max(64),
555
+ header: z9.string().max(256),
556
+ collapsable: z9.boolean().optional(),
557
+ collapsed: z9.boolean().optional(),
558
+ state: z9.enum(["open", "append", "close", "self"])
559
+ });
560
+ var ParsedLogSchema = z9.object({
561
+ id: z9.string().max(128),
562
+ processId: z9.string().max(128),
563
+ pid: z9.number().int().nullable().optional(),
564
+ timestamp: z9.coerce.date(),
565
+ level: LogLevelSchema.default("info"),
566
+ message: z9.string().max(16384),
567
+ raw: z9.string().max(16384),
568
+ stream: z9.enum(["stdout", "stderr"]).default("stdout"),
569
+ hidden: z9.boolean().optional().default(false),
570
+ metadata: z9.record(z9.string().max(256), z9.unknown()).optional().refine(
571
+ (obj) => !obj || Object.keys(obj).length <= 100,
572
+ { message: "Too many metadata keys (max 100)" }
573
+ ),
574
+ json: z9.record(z9.string(), z9.unknown()).optional(),
575
+ logCard: LogCardDirectiveSchema.optional(),
576
+ sourceType: z9.enum(["console", "file", "mongo", "mysql"]).optional(),
577
+ sourcePath: z9.string().max(4096).optional()
578
+ });
579
+ var ENV_VAR_NAME_REGEX = /^[A-Za-z_][A-Za-z0-9_]*$/;
580
+ var AgentConfigSchema = z10.object({
581
+ id: z10.string().max(128),
582
+ name: z10.string().min(1).max(100),
583
+ url: z10.string().url().max(2048),
584
+ passphrase: z10.string().min(1).max(1024),
585
+ passthroughEnv: z10.array(
586
+ z10.string().regex(ENV_VAR_NAME_REGEX).max(256)
587
+ ).max(100).default([])
588
+ });
589
+ var AgentStatusSchema = z10.object({
590
+ connected: z10.boolean(),
591
+ lastSeen: z10.string().nullable().optional(),
592
+ uptime: z10.number().nonnegative().default(0),
593
+ runnersAvailable: z10.array(z10.enum(["native", "docker"])).default(["native"]),
594
+ lanIp: z10.string().optional(),
595
+ /**
596
+ * Ce que la machine de l'agent vaut pour les builtins de portée `agent`.
597
+ * Sert à PRÉVISUALISER — la valeur injectée reste calculée au lancement, par
598
+ * l'agent lui-même : une IP change, un agent se déconnecte, et un statut
599
+ * n'est qu'un cliché.
600
+ */
601
+ os: z10.string().max(64).optional(),
602
+ home: z10.string().max(4096).optional(),
603
+ cwd: z10.string().max(4096).optional()
604
+ });
605
+ var GlobalRoleSchema = z11.enum(["owner", "admin", "member"]);
606
+ var ProjectRoleSchema = z11.enum(["admin", "editor", "viewer"]);
607
+ var ProjectMemberRoleSchema = z11.object({
608
+ id: z11.string().max(128),
609
+ projectId: z11.string().max(128),
610
+ userId: z11.string().max(128),
611
+ role: ProjectRoleSchema
612
+ });
613
+ var ConfigVersionSchema = z12.object({
614
+ id: z12.string().max(128),
615
+ entityType: z12.enum(["project", "service"]),
616
+ entityId: z12.string().max(128),
617
+ version: z12.string().max(128),
618
+ parentVersion: z12.string().max(128),
619
+ data: z12.record(z12.string(), z12.unknown()).refine(
620
+ (obj) => Object.keys(obj).length <= 1e3,
621
+ "Too many data keys (max 1000)"
622
+ ),
623
+ patch: z12.array(z12.record(z12.string(), z12.unknown())).max(1e3),
624
+ userId: z12.string().max(128),
625
+ timestamp: z12.coerce.date(),
626
+ resolved: z12.boolean().default(false)
627
+ });
628
+ var ConfigChangeSchema = z12.object({
629
+ entityType: z12.enum(["project", "service"]),
630
+ entityId: z12.string().max(128),
631
+ version: z12.string().max(128),
632
+ parentVersion: z12.string().max(128),
633
+ data: z12.record(z12.string(), z12.unknown()).refine(
634
+ (obj) => Object.keys(obj).length <= 1e3,
635
+ "Too many data keys (max 1000)"
636
+ ),
637
+ patch: z12.array(z12.record(z12.string(), z12.unknown())).max(1e3)
638
+ });
639
+ var SyncStatusSchema = z12.object({
640
+ connected: z12.boolean(),
641
+ lastSync: z12.coerce.date().nullable().optional(),
642
+ pendingChanges: z12.number().int().nonnegative().default(0),
643
+ conflicts: z12.number().int().nonnegative().default(0)
644
+ });
645
+ var AuditActionSchema = z13.enum([
646
+ "create",
647
+ "update",
648
+ "delete",
649
+ "invite",
650
+ "remove",
651
+ "deploy",
652
+ "start",
653
+ "stop",
654
+ "roleChange"
655
+ ]);
656
+ var AuditEntityTypeSchema = z13.enum([
657
+ "org",
658
+ "project",
659
+ "service",
660
+ "member",
661
+ "permission"
662
+ ]);
663
+ var AuditLogSchema = z13.object({
664
+ id: z13.string().max(128),
665
+ orgId: z13.string().max(128),
666
+ userId: z13.string().max(128),
667
+ action: AuditActionSchema,
668
+ entityType: AuditEntityTypeSchema,
669
+ entityId: z13.string().max(128),
670
+ metadata: z13.record(z13.string().max(256), z13.unknown()).default({}).refine(
671
+ (obj) => Object.keys(obj).length <= 100,
672
+ { message: "Too many metadata keys (max 100)" }
673
+ ),
674
+ timestamp: z13.coerce.date()
675
+ });
676
+ var ProcessMetricsSchema = z14.object({
677
+ processId: z14.string().max(128),
678
+ cpu: z14.number().nonnegative(),
679
+ memory: z14.number().int().nonnegative(),
680
+ timestamp: z14.string()
681
+ });
682
+ var EnvironmentVariablesSchema = z15.record(
683
+ z15.string().max(256),
684
+ VariableSchema
685
+ ).refine(
686
+ (obj) => Object.keys(obj).length <= 200,
687
+ { message: "Max 200 variables" }
688
+ );
689
+ var EnvironmentSchema = z15.object({
690
+ id: z15.string().max(128),
691
+ projectId: z15.string().max(128),
692
+ name: z15.string().min(1).max(200),
693
+ description: z15.string().max(2e3).optional().default(""),
694
+ parentIds: z15.array(z15.string().max(128)).max(10).default([]),
695
+ variables: EnvironmentVariablesSchema.default({}),
696
+ // Scope: 'global' = project-level env, 'service' = per-service env
697
+ scope: z15.enum(["global", "service"]).default("global"),
698
+ // When scope='service': the serviceId this env belongs to
699
+ reference: z15.string().max(128).optional(),
700
+ // When scope='service': the globalEnvId this env activates on
701
+ activateOn: z15.string().max(128).optional(),
702
+ immutable: z15.boolean().default(false),
703
+ default: z15.boolean().optional().default(false),
704
+ color: z15.string().max(20).optional(),
705
+ bgColor: z15.string().max(20).optional(),
706
+ // When scope='global': the default agent used by services that don't have an explicit agentId
707
+ agentId: z15.string().max(128).optional()
708
+ });
709
+ var ResolvedEnvironmentSchema = z15.object({
710
+ variables: z15.record(z15.string().max(256), VariableSchema).refine((obj) => Object.keys(obj).length <= 500, { message: "Max 500 resolved variables" }),
711
+ env: z15.record(z15.string().max(256), z15.string().max(8192)).refine((obj) => Object.keys(obj).length <= 500, { message: "Max 500 resolved env vars" }),
712
+ envSecrets: z15.array(z15.string().max(256)).max(500),
713
+ sources: z15.record(z15.string().max(256), z15.object({
714
+ environmentId: z15.string().max(128),
715
+ environmentName: z15.string().max(200),
716
+ overridden: z15.boolean(),
717
+ resolvedFrom: z15.object({
718
+ environmentId: z15.string().max(128),
719
+ environmentName: z15.string().max(200)
720
+ }).optional(),
721
+ // Set when a machine-local override was applied to this variable, pointing
722
+ // at the environment that carries the winning override. Distinct from
723
+ // `overridden`, which also covers "shadows an inherited variable".
724
+ overriddenBy: z15.object({
725
+ environmentId: z15.string().max(128),
726
+ environmentName: z15.string().max(200)
727
+ }).optional()
728
+ })).refine((obj) => Object.keys(obj).length <= 500, { message: "Max 500 source entries" })
729
+ });
730
+ var CreateEnvironmentSchema = EnvironmentSchema.omit({ id: true }).extend({
731
+ description: z15.string().max(2e3).optional().default(""),
732
+ parentIds: z15.array(z15.string().max(128)).max(10).optional().default([]),
733
+ variables: EnvironmentVariablesSchema.optional().default({}),
734
+ scope: z15.enum(["global", "service"]).optional().default("global"),
735
+ reference: z15.string().max(128).optional(),
736
+ activateOn: z15.string().max(128).optional(),
737
+ immutable: z15.boolean().optional().default(false)
738
+ });
739
+ var UpdateEnvironmentSchema = EnvironmentSchema.partial().required({ id: true }).extend({
740
+ description: z15.string().max(2e3).optional(),
741
+ parentIds: z15.array(z15.string().max(128)).max(10).optional(),
742
+ variables: EnvironmentVariablesSchema.optional(),
743
+ scope: z15.enum(["global", "service"]).optional(),
744
+ immutable: z15.boolean().optional(),
745
+ default: z15.boolean().optional(),
746
+ agentId: z15.string().max(128).nullable().optional()
747
+ // null = clear (no default agent)
748
+ });
749
+ var VariableOverrideSchema = z16.object({
750
+ value: VariableSlotSchema
751
+ });
752
+ var EnvironmentOverridesSchema = z16.record(
753
+ z16.string().max(128),
754
+ VariableOverrideSchema
755
+ ).refine(
756
+ (obj) => Object.keys(obj).length <= 5e3,
757
+ { message: "Max 5000 overrides" }
758
+ );
759
+ var ApiServiceActionSchema = z17.enum([
760
+ "service:read",
761
+ "service:start",
762
+ "service:stop",
763
+ "service:restart",
764
+ "service:healthcheck",
765
+ "service:status",
766
+ "logs:read"
767
+ ]);
768
+ var ApiEnvActionSchema = z17.enum(["env:read", "env:write"]);
769
+ var ApiEnvPermSchema = z17.object({
770
+ environmentId: z17.string().max(128),
771
+ actions: z17.array(ApiEnvActionSchema).max(10).default(["env:read"]),
772
+ includeSecrets: z17.boolean().default(false)
773
+ });
774
+ var ApiServicePermSchema = z17.object({
775
+ serviceId: z17.string().max(128),
776
+ actions: z17.array(ApiServiceActionSchema).max(10).default(["service:read"]),
777
+ environments: z17.array(ApiEnvPermSchema).max(100).default([])
778
+ });
779
+ var ApiKeyScopeSchema = z17.object({
780
+ services: z17.array(ApiServicePermSchema).max(500).default([])
781
+ });
782
+ var ApiKeySchema = z17.object({
783
+ id: z17.string().max(128),
784
+ name: z17.string().min(1).max(200),
785
+ key: z17.string().regex(/^[0-9a-f]{64}$/i),
786
+ scopes: ApiKeyScopeSchema,
787
+ createdAt: z17.string().max(64),
788
+ isPublic: z17.boolean().default(false)
789
+ });
790
+ var PersistedApiKeySchema = ApiKeySchema.extend({
791
+ key: z17.string().min(1).max(4096)
792
+ });
793
+ var ApiKeysFileSchema = z17.object({
794
+ keys: z17.array(PersistedApiKeySchema).max(100)
795
+ });
796
+ var MaskedApiKeySchema = ApiKeySchema.omit({ key: true }).extend({
797
+ /** Last 4 characters of the secret, for recognising a key in a list. */
798
+ keyPreview: z17.string().max(8)
799
+ });
800
+ var ALLOWED_IMAGE_MIME_TYPES = ["image/png", "image/jpeg", "image/webp", "image/gif"];
801
+ var ImagePartSchema = z18.object({
802
+ type: z18.literal("image"),
803
+ imageId: z18.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"),
804
+ url: z18.string().min(1),
805
+ mimeType: z18.enum(ALLOWED_IMAGE_MIME_TYPES),
806
+ altText: z18.string().max(500).optional()
807
+ });
808
+ var ImageUploadResponseSchema = z18.object({
809
+ imageId: z18.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"),
810
+ url: z18.string().min(1),
811
+ mimeType: z18.enum(ALLOWED_IMAGE_MIME_TYPES),
812
+ originalName: z18.string()
813
+ });
814
+ var ImageMetaSchema = z18.object({
815
+ imageId: z18.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"),
816
+ filePath: z18.string().min(1),
817
+ mimeType: z18.enum(ALLOWED_IMAGE_MIME_TYPES),
818
+ originalName: z18.string().min(1),
819
+ createdAt: z18.number().positive(),
820
+ size: z18.number().positive().optional()
821
+ });
822
+ var KanbanAttachmentSchema = z19.object({
823
+ /** Server-issued id, also the storage key. */
824
+ id: z19.string().max(128),
825
+ name: z19.string().max(255),
826
+ size: z19.number().int().nonnegative(),
827
+ contentType: z19.string().max(128)
828
+ });
829
+ var KanbanCardEventSchema = z19.object({
830
+ type: z19.enum(["created", "edited", "moved", "image_added", "image_removed", "title_changed", "conversation_started", "scenario_started", "comment", "archived", "unarchived"]),
831
+ timestamp: z19.string(),
832
+ /** Extra context: old/new column name, old/new title, comment text, etc. */
833
+ /**
834
+ * Le texte de l'entrée : le corps d'un commentaire, ou le contexte du geste.
835
+ *
836
+ * Borné comme le corps d'une carte (100 000), et non plus à 5 000 : un
837
+ * commentaire est de la prose comme une description, et rien de technique ne
838
+ * justifiait un écart de vingt fois. La borne étroite s'est vue à l'import
839
+ * d'un Kanbanize, où des commentaires de 12 000 caractères passaient par
840
+ * l'API publique — bornée, elle, à 20 000 — pour écrire en base une donnée que
841
+ * ce schéma déclarait invalide, et qu'aucune reprise depuis l'interface
842
+ * n'aurait ensuite pu enregistrer.
843
+ */
844
+ detail: z19.string().max(1e5).optional(),
845
+ /**
846
+ * Stable identity of the event, used to tell an edit from an insertion when a
847
+ * whole history is written back. Absent on events recorded before the field
848
+ * existed; those fall back to (type, timestamp).
849
+ */
850
+ id: z19.string().max(128).optional(),
851
+ /** Who authored this event — 'ai' or 'user'. Only set for comment events. */
852
+ author: z19.enum(["ai", "user"]).optional(),
853
+ /**
854
+ * Qui est derrière l'événement, estampillé par le serveur — jamais pris du
855
+ * client, sans quoi n'importe qui pourrait signer au nom d'un autre.
856
+ *
857
+ * Posé sur les commentaires (c'est ce qui rend « mon propre commentaire »
858
+ * répondable ; `author` ne sépare que l'IA de l'humain) et sur les
859
+ * déplacements. Absent des événements écrits avant qu'on l'estampille : un
860
+ * lecteur doit donc afficher « on ne sait pas », pas un nom vide.
861
+ *
862
+ * Pour une clé d'API, c'est le nom de la clé et non son porteur : la clé
863
+ * emprunte les droits de son créateur, pas son identité — personne ne doit
864
+ * croire qu'un humain a déplacé ce qu'un robot de CI a déplacé.
865
+ */
866
+ authorUser: z19.object({ id: z19.string().max(128), name: z19.string().max(200) }).optional(),
867
+ /** Set when the author amended their comment, so the UI can say so. */
868
+ editedAt: z19.string().optional(),
869
+ /** Files attached to a comment — same storage as a card's own attachments. */
870
+ attachments: z19.array(KanbanAttachmentSchema).max(20).optional(),
871
+ /** Conversation that produced this event (comments only). Used to navigate back to the conversation. */
872
+ conversationId: z19.string().optional()
873
+ });
874
+ var KanbanCardSchema = z19.object({
875
+ id: z19.string(),
876
+ title: z19.string().min(1).max(500),
877
+ markdown: z19.string().max(1e5).default(""),
878
+ /**
879
+ * Legacy inline images, kept so boards written before object storage still
880
+ * render. New uploads go to `attachments` instead.
881
+ */
882
+ images: z19.array(z19.string()).default([]),
883
+ /** Files attached to the card — stored out of band, referenced here. */
884
+ attachments: z19.array(KanbanAttachmentSchema).max(50).default([]),
885
+ order: z19.number().int(),
886
+ /**
887
+ * La priorité de la carte, de 1 à 10 — 10 étant le plus urgent.
888
+ *
889
+ * Facultative, et absente veut dire « pas de priorité », pas « la plus
890
+ * basse » : une carte qu'on n'a pas encore arbitrée ne doit pas se ranger
891
+ * d'office au fond de la pile.
892
+ */
893
+ priority: z19.number().int().min(1).max(10).optional(),
894
+ /**
895
+ * Les groupes de la carte — des étiquettes libres, posées par l'équipe.
896
+ *
897
+ * Rien ne les déclare ailleurs : un groupe existe parce qu'une carte le
898
+ * porte, et disparaît avec la dernière qui le portait. C'est ce qui permet
899
+ * d'en créer un en le tapant, sans passer par un écran d'administration.
900
+ */
901
+ groups: z19.array(z19.string().min(1).max(60)).max(30).optional(),
902
+ /**
903
+ * L'échéance de la carte : le jour où elle est attendue, `AAAA-MM-JJ`.
904
+ *
905
+ * Un jour, pas un instant, et c'est une décision : une équipe se dit « pour
906
+ * vendredi », jamais « pour vendredi 23:59:59 UTC ». Stocker un instant
907
+ * ferait afficher une échéance au 4 mars comme le 3 mars à qui travaille à
908
+ * l'ouest de Greenwich — la carte serait en retard d'un jour pour la moitié
909
+ * de l'équipe, et personne ne saurait pourquoi.
910
+ *
911
+ * Facultative, et absente veut dire « pas d'échéance », pas « en retard » :
912
+ * une carte qu'on n'a pas datée ne doit pas s'annoncer comme urgente.
913
+ */
914
+ deadline: z19.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
915
+ /**
916
+ * La couleur de la carte, en hexadécimal (`#RRGGBB`) — un liseré en haut de
917
+ * la carte, et rien d'autre : ce qu'elle veut dire appartient à l'équipe.
918
+ *
919
+ * Bornée à une notation stricte plutôt qu'à une chaîne libre : cette valeur
920
+ * finit dans un attribut `style`, et une couleur ne doit pouvoir contenir
921
+ * qu'une couleur. Absente sur les cartes sans couleur.
922
+ */
923
+ color: z19.string().regex(/^#[0-9a-fA-F]{6}$/).optional(),
924
+ /**
925
+ * Le journal de la carte — commentaires compris.
926
+ *
927
+ * Optionnel, et c'est tout l'intérêt : c'est la partie qui grossit sans fin
928
+ * (une IA bavarde y écrit des pages), alors les lectures de tableau ne le
929
+ * transportent plus. `undefined` veut dire « pas chargé », et une écriture
930
+ * qui l'omet laisse au serveur celui qu'il a en base — à ne pas confondre
931
+ * avec `[]`, qui demanderait bel et bien de le vider.
932
+ */
933
+ history: z19.array(KanbanCardEventSchema).optional(),
934
+ /**
935
+ * Ce que le journal absent laisse quand même dire : combien de commentaires,
936
+ * et quand fut le dernier. Posés par le serveur en lecture, ignorés en
937
+ * écriture — la carte ne les stocke pas, ils se déduisent de `history`.
938
+ */
939
+ commentCount: z19.number().int().nonnegative().optional(),
940
+ lastCommentAt: z19.string().optional(),
941
+ /**
942
+ * Les entrées de journal qui ouvrent une conversation IA. Elles restent dans
943
+ * la lecture allégée — il y en a une poignée par carte, et l'hôte s'en sert
944
+ * pour dire, sans ouvrir la carte, qu'une IA y travaille.
945
+ */
946
+ conversationEvents: z19.array(KanbanCardEventSchema).optional(),
947
+ createdAt: z19.string(),
948
+ updatedAt: z19.string(),
949
+ /**
950
+ * Quand la carte a été archivée — absente tant qu'elle est au tableau.
951
+ *
952
+ * Une carte archivée reste dans sa colonne en base : c'est la lecture qui la
953
+ * retire du tableau, jamais une écriture qui la déplace. Rien à recoller donc
954
+ * au désarchivage, et aucun cimetière où une carte pourrait se perdre.
955
+ */
956
+ archivedAt: z19.string().optional(),
957
+ /**
958
+ * La colonne d'où la carte a été archivée, telle qu'elle s'appelait alors.
959
+ *
960
+ * L'identifiant sert à l'y remettre, le titre à le dire dans l'archive même
961
+ * quand la colonne a disparu depuis — auquel cas le désarchivage repose la
962
+ * carte dans la première colonne, sans se taire sur son origine.
963
+ */
964
+ archivedFrom: z19.object({ columnId: z19.string().max(128), columnTitle: z19.string().max(200) }).optional(),
965
+ /**
966
+ * Quand la carte a été supprimée. Rien n'est effacé : la carte reste en base,
967
+ * et toutes les lectures l'écartent.
968
+ *
969
+ * Une suppression est le seul geste que rien ne rattrape — sauf à ne pas
970
+ * l'exécuter vraiment. La colonne et le tableau portent le même champ, pour
971
+ * que supprimer l'un n'emporte jamais les cartes de l'autre.
972
+ */
973
+ deletedAt: z19.string().optional(),
974
+ /**
975
+ * People assigned to the card. Names are denormalized for display; the server
976
+ * keeps only members of the owning organization, and notifies newcomers.
977
+ */
978
+ assignees: z19.array(z19.object({ id: z19.string().max(128), name: z19.string().max(200) })).max(20).default([]),
979
+ /**
980
+ * Who first created the card. Stamped by the server the first time a card id
981
+ * appears in a board write, never taken from the client — a member could
982
+ * otherwise claim any authorship. Absent on cards created before this field
983
+ * existed, so readers must treat it as unknown rather than assume.
984
+ */
985
+ createdBy: z19.object({ id: z19.string().max(128), name: z19.string().max(200) }).optional()
986
+ });
987
+ var KanbanColumnSchema = z19.object({
988
+ id: z19.string(),
989
+ title: z19.string().min(1).max(200),
990
+ order: z19.number().int(),
991
+ cards: z19.array(KanbanCardSchema).default([]),
992
+ /**
993
+ * Le regroupement auquel la colonne appartient, s'il y en a un.
994
+ *
995
+ * Un pointeur vers le parent, et rien dans l'autre sens : le groupe ne tient
996
+ * pas la liste de ses membres. Deux listes qui prétendent dire qui contient
997
+ * quoi finissent par se contredire, et un déplacement devient alors deux
998
+ * écritures au lieu d'une.
999
+ */
1000
+ groupId: z19.string().optional(),
1001
+ /** Supprimée, mais conservée — voir `deletedAt` sur la carte. */
1002
+ deletedAt: z19.string().optional()
1003
+ });
1004
+ var KanbanColumnGroupSchema = z19.object({
1005
+ id: z19.string(),
1006
+ title: z19.string().min(1).max(200),
1007
+ /** La couleur du bandeau, en hexadécimal — l'interface décide du défaut. */
1008
+ color: z19.string().regex(/^#[0-9a-fA-F]{6}$/).optional(),
1009
+ /** Le groupe parent, pour les regroupements imbriqués. */
1010
+ parentId: z19.string().optional(),
1011
+ /** Supprimé, mais conservé — comme une colonne. */
1012
+ deletedAt: z19.string().optional()
1013
+ });
1014
+ var KanbanBoardSchema = z19.object({
1015
+ id: z19.string(),
1016
+ name: z19.string().min(1).max(200),
1017
+ description: z19.string().max(1e4).default(""),
1018
+ /**
1019
+ * Le mode d'emploi du tableau, en texte libre : ce que veulent dire ses
1020
+ * colonnes, quand une carte a le droit d'avancer, les conventions de
1021
+ * l'équipe. Écrit par les humains, lu surtout par l'IA — il est injecté dans
1022
+ * le prompt des agents pour qu'ils travaillent selon les règles du tableau
1023
+ * plutôt que selon les leurs.
1024
+ */
1025
+ instructions: z19.string().max(2e4).default(""),
1026
+ columns: z19.array(KanbanColumnSchema).default([]),
1027
+ /** Les regroupements de colonnes — vide sur un tableau qui n'en a jamais eu. */
1028
+ columnGroups: z19.array(KanbanColumnGroupSchema).default([]),
1029
+ /**
1030
+ * Les projets auxquels le tableau est rattaché, par leur identifiant.
1031
+ *
1032
+ * Un rattachement, pas une possession : il ne sert qu'à filtrer la liste des
1033
+ * tableaux, et un tableau sans projet (`[]`, le cas par défaut) reste visible
1034
+ * partout. Plusieurs projets sont permis parce qu'une équipe partage souvent
1035
+ * un même tableau entre deux projets — obliger à choisir l'un des deux
1036
+ * ferait disparaître le tableau de la liste de l'autre.
1037
+ *
1038
+ * Les identifiants sont ceux des projets de l'organisation ; le serveur
1039
+ * refuse ceux qu'il ne connaît pas plutôt que de garder un lien mort.
1040
+ */
1041
+ projectIds: z19.array(z19.string().min(1).max(128)).max(20).default([]),
1042
+ archived: z19.boolean().default(false),
1043
+ /** Supprimé, mais conservé avec ses cartes — voir `deletedAt` sur la carte. */
1044
+ deletedAt: z19.string().optional(),
1045
+ createdAt: z19.string(),
1046
+ updatedAt: z19.string()
1047
+ });
1048
+ var CreateKanbanBoardInput = z19.object({
1049
+ name: z19.string().min(1).max(200),
1050
+ description: z19.string().max(1e4).optional(),
1051
+ instructions: z19.string().max(2e4).optional(),
1052
+ projectIds: z19.array(z19.string().min(1).max(128)).max(20).optional()
1053
+ });
1054
+ var UpdateKanbanBoardInput = z19.object({
1055
+ id: z19.string(),
1056
+ name: z19.string().min(1).max(200).optional(),
1057
+ description: z19.string().max(1e4).optional(),
1058
+ instructions: z19.string().max(2e4).optional(),
1059
+ columns: z19.array(KanbanColumnSchema).optional(),
1060
+ archived: z19.boolean().optional(),
1061
+ projectIds: z19.array(z19.string().min(1).max(128)).max(20).optional()
1062
+ });
1063
+ var KanbanCardLinkSchema = z19.object({
1064
+ id: z19.string().max(128),
1065
+ /** Le tableau et la carte qui *dépendent* de l'autre. */
1066
+ childBoardId: z19.string().max(64),
1067
+ childCardId: z19.string().max(128),
1068
+ /** Le tableau et la carte *dont* on dépend. */
1069
+ parentBoardId: z19.string().max(64),
1070
+ parentCardId: z19.string().max(128),
1071
+ createdAt: z19.string(),
1072
+ createdBy: z19.object({ id: z19.string().max(128), name: z19.string().max(200) }).optional()
1073
+ });
1074
+ var KanbanCardRefSchema = z19.object({
1075
+ cardId: z19.string().max(128),
1076
+ boardId: z19.string().max(64),
1077
+ boardName: z19.string().max(200),
1078
+ columnId: z19.string().max(128),
1079
+ columnTitle: z19.string().max(200),
1080
+ title: z19.string().max(500),
1081
+ /** Les mêmes informations qu'une ligne de tableau montre d'une carte d'ici. */
1082
+ assignees: z19.array(z19.object({ id: z19.string().max(128), name: z19.string().max(200) })).default([]),
1083
+ commentCount: z19.number().int().nonnegative().default(0)
1084
+ });
1085
+ var CloudApiScopeSchema = z20.enum([
1086
+ "kanban:read",
1087
+ "kanban:write",
1088
+ "kanban:comment",
1089
+ "kanban:delete"
1090
+ ]);
1091
+ var CloudApiKeySecretSchema = z20.string().regex(/^rk_[0-9a-f]{64}$/);
1092
+ var CloudApiKeySchema = z20.object({
1093
+ id: z20.string().max(128),
1094
+ organizationId: z20.string().max(128),
1095
+ name: z20.string().min(1).max(200),
1096
+ scopes: z20.array(CloudApiScopeSchema).min(1).max(10),
1097
+ /**
1098
+ * Les tableaux que la clé peut atteindre, ou `null` pour « tous ceux de
1099
+ * l'organisation ».
1100
+ *
1101
+ * `null` et `[]` ne sont pas la même chose : la liste vide n'ouvre rien, et
1102
+ * c'est délibéré — un tableau supprimé ne doit pas élargir une clé qui ne le
1103
+ * nommait plus que lui.
1104
+ */
1105
+ boards: z20.array(z20.string().max(64)).max(200).nullable(),
1106
+ createdAt: z20.string().max(64),
1107
+ /** Dernier usage constaté, pour reconnaître une clé oubliée. */
1108
+ lastUsedAt: z20.string().max(64).nullable(),
1109
+ /** Qui l'a émise — une clé sans visage ne se révoque jamais sereinement. */
1110
+ createdBy: z20.object({ id: z20.string().max(128), name: z20.string().max(200) }),
1111
+ /** Les 4 derniers caractères du secret, pour reconnaître une clé dans une liste. */
1112
+ keyPreview: z20.string().max(8)
1113
+ });
1114
+ var CreatedCloudApiKeySchema = z20.object({
1115
+ key: CloudApiKeySchema,
1116
+ secret: CloudApiKeySecretSchema
1117
+ });
1118
+ var CreateCloudApiKeyInput = z20.object({
1119
+ organizationId: z20.string().min(1).max(128),
1120
+ name: z20.string().min(1).max(200),
1121
+ scopes: z20.array(CloudApiScopeSchema).min(1).max(10),
1122
+ boards: z20.array(z20.string().max(64)).max(200).nullable().default(null)
1123
+ });
1124
+ var UpdateCloudApiKeyInput = z20.object({
1125
+ id: z20.string().min(1).max(128),
1126
+ name: z20.string().min(1).max(200).optional(),
1127
+ scopes: z20.array(CloudApiScopeSchema).min(1).max(10).optional(),
1128
+ boards: z20.array(z20.string().max(64)).max(200).nullable().optional()
1129
+ });
1130
+ var ChangelogSurfaceSchema = z21.enum(["app", "cloud"]);
1131
+ var ChangelogChangeKindSchema = z21.enum(["feature", "improvement", "fix", "breaking"]);
1132
+ var ChangelogTextSchema = z21.object({
1133
+ fr: z21.string().min(1).max(500),
1134
+ en: z21.string().min(1).max(500)
1135
+ });
1136
+ var ChangelogChangeSchema = z21.object({
1137
+ kind: ChangelogChangeKindSchema,
1138
+ text: ChangelogTextSchema
1139
+ });
1140
+ var ChangelogDraftSchema = ChangelogChangeSchema.extend({
1141
+ date: z21.string().regex(/^\d{4}-\d{2}-\d{2}$/),
1142
+ title: ChangelogTextSchema.optional()
1143
+ });
1144
+ var ChangelogReleaseSchema = z21.object({
1145
+ surface: ChangelogSurfaceSchema,
1146
+ /** `1.4.2` pour l'app (version npm publiée), `2026-09-03` — ou `2026-09-03.2` — pour le cloud. */
1147
+ version: z21.string().min(1).max(32).regex(/^[0-9][0-9.-]*$/),
1148
+ /** Date de publication, `YYYY-MM-DD`. */
1149
+ date: z21.string().regex(/^\d{4}-\d{2}-\d{2}$/),
1150
+ /** Facultatif : une version peut s'annoncer par son seul numéro. */
1151
+ title: ChangelogTextSchema.optional(),
1152
+ /** Une version sans changement n'a rien à annoncer : elle n'a pas sa place ici. */
1153
+ changes: z21.array(ChangelogChangeSchema).min(1).max(50)
1154
+ });
1155
+ var ChangelogIndexItemSchema = ChangelogReleaseSchema.omit({ changes: true }).extend({
1156
+ changeCount: z21.number().int().nonnegative()
1157
+ });
1158
+ var MASKED_VALUE = "***";
1159
+ function maskLogSourceSecrets(sources) {
1160
+ return sources.map((src) => {
1161
+ if (src.type === "mongo") return { ...src, connectionString: MASKED_VALUE };
1162
+ if (src.type === "mysql" && src.password) return { ...src, password: MASKED_VALUE };
1163
+ return src;
1164
+ });
1165
+ }
1166
+ var BUILTIN_VARIABLES = [
1167
+ // ── Le service ───────────────────────────────────────────────────────────
1168
+ { name: "service.NAME", scope: "server", descriptionKey: "serviceName" },
1169
+ { name: "service.ID", scope: "server", descriptionKey: "serviceId" },
1170
+ { name: "service.PORT", scope: "server", descriptionKey: "servicePort" },
1171
+ { name: "service.URL", scope: "server", descriptionKey: "serviceUrl" },
1172
+ { name: "service.BASE_URL", scope: "server", descriptionKey: "serviceBaseUrl" },
1173
+ { name: "service.CWD", scope: "agent", descriptionKey: "serviceCwd" },
1174
+ // ── Le projet et l'environnement actif ───────────────────────────────────
1175
+ { name: "project.NAME", scope: "server", descriptionKey: "projectName" },
1176
+ { name: "runeya.ENV_NAME", scope: "server", descriptionKey: "envName" },
1177
+ // ── Le serveur Runeya ────────────────────────────────────────────────────
1178
+ // `service.HOST` a toujours désigné l'adresse d'écoute du SERVEUR, pas une
1179
+ // propriété du service : le nom trompait, il devient un alias.
1180
+ { name: "runeya.HOST", scope: "server", descriptionKey: "runeyaHost", deprecatedAlias: "service.HOST" },
1181
+ // ── La machine qui exécute ───────────────────────────────────────────────
1182
+ { name: "agent.HOST_LAN", scope: "agent", descriptionKey: "agentHostLan", deprecatedAlias: "service.HOST_LAN" },
1183
+ // Le NOM de l'agent est une étiquette de la configuration du serveur, pas
1184
+ // une propriété de la machine : c'est le serveur qui le connaît et le résout.
1185
+ { name: "agent.NAME", scope: "server", descriptionKey: "agentName" },
1186
+ { name: "agent.OS", scope: "agent", descriptionKey: "agentOs" },
1187
+ { name: "agent.HOME", scope: "agent", descriptionKey: "agentHome" }
1188
+ ];
1189
+ var GRACE_PERIOD = 1e4;
1190
+ var AGENT_STOP_FETCH_TIMEOUT = GRACE_PERIOD + 15e3;
1191
+ var SUPPORTED_EDITORS = [
1192
+ { key: "vscode", name: "Visual Studio Code", command: "code" },
1193
+ { key: "cursor", name: "Cursor", command: "cursor" },
1194
+ { key: "windsurf", name: "Windsurf", command: "windsurf" },
1195
+ { key: "sublime", name: "Sublime Text", command: "subl" },
1196
+ { key: "atom", name: "Atom", command: "atom" },
1197
+ { key: "antigravity", name: "Antigravity", command: "antigravity" },
1198
+ { key: "intellij", name: "IntelliJ IDEA", command: "idea" },
1199
+ { key: "android-studio", name: "Android Studio", command: "studio" },
1200
+ { key: "webstorm", name: "WebStorm", command: "webstorm" },
1201
+ { key: "zed", name: "Zed", command: "zed" },
1202
+ { key: "neovim", name: "Neovim", command: "nvim" },
1203
+ { key: "vim", name: "Vim", command: "vim" },
1204
+ { key: "emacs", name: "Emacs", command: "emacs" },
1205
+ { key: "fleet", name: "Fleet", command: "fleet" }
1206
+ ];
1207
+ var EDITOR_BY_KEY = new Map(
1208
+ SUPPORTED_EDITORS.map((e) => [e.key, e])
1209
+ );
7
1210
 
8
1211
  // ../ai-capabilities/dist/index.js
1212
+ import { z as z23 } from "zod";
1213
+ import { z as z32 } from "zod";
9
1214
  function toList(raw) {
10
1215
  if (!raw) return [];
11
1216
  const text = raw.trim();
@@ -32,9 +1237,107 @@ function gitTarget(p) {
32
1237
  ...p.orgId ? { orgId: p.orgId } : {}
33
1238
  };
34
1239
  }
1240
+ var toBool = (raw) => raw.trim().toLowerCase() === "true";
1241
+ var newId = () => globalThis.crypto.randomUUID();
1242
+ function listItem(raw) {
1243
+ try {
1244
+ return JSON.parse(raw);
1245
+ } catch {
1246
+ return raw;
1247
+ }
1248
+ }
1249
+ function parseTyped(name, schema, raw) {
1250
+ if (raw === void 0) return void 0;
1251
+ let result = raw.trim() === "null" ? schema.safeParse(null) : schema.safeParse(raw);
1252
+ if (!result.success && raw.trim() === "null") result = schema.safeParse(raw);
1253
+ if (!result.success) {
1254
+ const text = raw.trim();
1255
+ const json = listItem(text);
1256
+ if (json !== text) result = schema.safeParse(json);
1257
+ if (!result.success && !/^[[{]/.test(text)) {
1258
+ const list = schema.safeParse(toList(text).map(listItem));
1259
+ if (list.success) result = list;
1260
+ }
1261
+ }
1262
+ if (!result.success) throw new Error(`${name}: ${z22.prettifyError(result.error)}`);
1263
+ return result.data;
1264
+ }
1265
+ function withIds(items) {
1266
+ return items.map((item) => ({ ...item, id: item.id || newId() }));
1267
+ }
1268
+ var optionalId = (schema) => schema.extend({ id: z22.string().min(1).max(64).optional() });
1269
+ var DockerConfigInput = DockerConfigSchema.extend({
1270
+ bootstrapCommands: z22.array(optionalId(BootstrapCommandSchema)).max(20).default([])
1271
+ }).refine((c) => !!c.image !== !!c.dockerfile, {
1272
+ message: 'dockerConfig needs exactly one of "image" (an image to pull) or "dockerfile" (a Dockerfile to build)'
1273
+ });
1274
+ var SERVICE_FIELDS = [
1275
+ { name: "description", description: "What the service is, in a sentence" },
1276
+ { name: "agentId", description: "The agent that runs it, from list_agents. Omit to inherit from the environment.", clearable: true },
1277
+ { name: "cwd", description: `Working directory, RELATIVE to the project root (e.g. "apps/web", or omit for the root). The project is synced between machines and lives in a different folder on each: Runeya resolves a relative cwd against each machine's own project folder, while an absolute path (/home/you/\u2026) breaks on every other machine. Use an absolute path only for something outside the project, written with ~ or an environment variable ($NAME) rather than a literal home directory.`, clearable: true },
1278
+ { name: "command", description: 'Shortcut for a single command line (e.g. "npm run dev"). Replaces every existing command. Use commands for several.' },
1279
+ { name: "commands", description: 'The processes of the service. They all start AT THE SAME TIME, in parallel, and the service runs while they run \u2014 not one after another. Use several for processes that live side by side (a web server and a worker). Steps that must follow each other (build, then install, then launch) go in ONE command chained with &&. A one-off action the user triggers by hand (build, deploy, read logs) is a shortcut, not a command. Each command runs in the service cwd, or its own "cwd", relative to the project root. No absolute paths of this machine: the service is synced to other machines. Replaces every existing command. "id" is generated when omitted; "shell" runs the line through a shell (default true).', schema: z22.array(optionalId(ServiceCommandSchema)).max(50) },
1280
+ { name: "ports", description: "Ports the service listens on. Declare them: they become {{service.PORT}}, {{service.URL}} and {{services.<slug>.URL}} for the other services, which environment variables should reference instead of repeating the numbers.", schema: ServiceConfigSchema.shape.ports.unwrap().unwrap() },
1281
+ { name: "groups", description: "Groups the service belongs to. Replaces the current ones.", schema: ServiceConfigSchema.shape.groups.unwrap().unwrap() },
1282
+ { name: "url", description: "URL where the service is reached" },
1283
+ { name: "localUrls", description: 'Local domain names routed to a port of the service (e.g. {"url":"api.localhost.dev","port":3000})', schema: ServiceConfigSchema.shape.localUrls.unwrap().unwrap() },
1284
+ { name: "openapiUrl", description: "URL of its OpenAPI document" },
1285
+ { name: "docsPath", description: "Where its markdown docs live, relative to cwd or absolute. Defaults to cwd." },
1286
+ { name: "git", description: 'Its git repository: "remote" URL and "home" page', schema: ServiceConfigSchema.shape.git.unwrap(), clearable: true },
1287
+ { name: "meta", description: "Free key/value metadata (strings)", schema: ServiceConfigSchema.shape.meta.unwrap(), clearable: true },
1288
+ { name: "runner", description: '"native" runs the commands on the machine; "docker" runs the service in a container and then needs dockerConfig', schema: ServiceConfigSchema.shape.runner.unwrap().unwrap() },
1289
+ { name: "dockerConfig", description: 'With runner "docker": the container. Exactly one of "image" (pull) or "dockerfile" (inline Dockerfile, built with "buildContext", "buildArgs", "targetStage"). Ports and volumes use Docker syntax ("8080:80", "./data:/data"); host paths in volumes relative to the service directory, never an absolute path of this machine. "useNativeCommand" runs the service commands inside the container instead of its CMD ("nativeCommandMode": one shared container or one per command). "bootstrapCommands" run once when the container starts. Replaces the whole Docker configuration: read it first with get_service to keep what you do not change.', schema: DockerConfigInput },
1290
+ { name: "healthCheck", description: 'How to tell the service is ready: an HTTP "path" to call, or a "command" that must succeed', schema: HealthCheckSchema, clearable: true },
1291
+ { name: "autoRestart", description: "Restart the service when it crashes", schema: z22.boolean() },
1292
+ { name: "restartStrategy", description: "When to restart it", schema: RestartStrategySchema.unwrap() },
1293
+ { name: "maxRestarts", description: "Give up after this many restarts", schema: ServiceConfigSchema.shape.maxRestarts.unwrap() },
1294
+ { name: "restartBackoffMs", description: "Delay before a restart, in milliseconds", schema: ServiceConfigSchema.shape.restartBackoffMs.unwrap().unwrap() },
1295
+ { name: "clearLogsOnStart", description: "Clear the logs each time the service starts", schema: z22.boolean() },
1296
+ { name: "shortcuts", description: 'One-click actions shown on the service, run on demand and independently of the running commands (build, deploy, migrate, read logs). Same path rules as commands: relative to the project root, never an absolute path of this machine. Replaces the current ones. "id" is generated when omitted.', schema: z22.array(optionalId(ServiceShortcutSchema)).max(50) },
1297
+ { name: "parserIds", description: "Log parsers applied to its output, by id", schema: ServiceConfigSchema.shape.parserIds.unwrap() },
1298
+ { name: "logSources", description: 'Extra log sources beyond the console output (files, databases\u2026). Replaces the current ones. Credentials (mongo connectionString, mysql password) read as "***": send "***" back to keep the stored value, or the real value to change it.', schema: ServiceConfigSchema.shape.logSources.unwrap().unwrap() }
1299
+ ];
1300
+ function serviceParams(clearable2) {
1301
+ return SERVICE_FIELDS.map((f) => {
1302
+ const nullable = clearable2 && f.clearable;
1303
+ const base = f.schema ?? (nullable ? z22.string() : void 0);
1304
+ return {
1305
+ name: f.name,
1306
+ description: nullable ? `${f.description} null clears it.` : f.description,
1307
+ required: false,
1308
+ ...base ? { schema: nullable ? base.nullable() : base } : {}
1309
+ };
1310
+ });
1311
+ }
1312
+ function serviceFields(p, params) {
1313
+ const out = {};
1314
+ for (const param of params) {
1315
+ if (p[param.name] === void 0 || param.name === "command") continue;
1316
+ out[param.name] = param.schema ? parseTyped(param.name, param.schema, p[param.name]) : p[param.name];
1317
+ }
1318
+ if (p.command !== void 0 && p.commands === void 0) out["commands"] = [{ label: "", command: p.command, shell: true }];
1319
+ if (Array.isArray(out["commands"])) out["commands"] = withIds(out["commands"]);
1320
+ if (Array.isArray(out["shortcuts"])) out["shortcuts"] = withIds(out["shortcuts"]);
1321
+ const docker = out["dockerConfig"];
1322
+ if (docker?.bootstrapCommands) out["dockerConfig"] = { ...docker, bootstrapCommands: withIds(docker.bootstrapCommands) };
1323
+ return out;
1324
+ }
1325
+ function maskServices(result) {
1326
+ if (Array.isArray(result)) return result.map(maskServices);
1327
+ if (result && typeof result === "object" && Array.isArray(result.logSources)) {
1328
+ const service = result;
1329
+ return { ...service, logSources: maskLogSourceSecrets(service.logSources) };
1330
+ }
1331
+ return result;
1332
+ }
1333
+ var refs = (scope) => BUILTIN_VARIABLES.filter((b) => b.scope === scope).map((b) => `{{${b.name}}}`).join(", ");
1334
+ var BUILTINS_HELP = `Built-in references Runeya fills itself \u2014 filled when the service is deployed, from the service that receives the variable: ${refs("server")}, the numbered {{service.PORT_2}} / {{service.URL_2}}\u2026 for its other ports, and {{services.<slug>.PORT}}, .URL, .BASE_URL, .NAME, .ID for a sibling service of the project (slug = its name in lowercase-dashes). Filled on the machine when the service starts: ${refs("agent")}.`;
1335
+ var CREATE_SERVICE_PARAMS = serviceParams(false);
1336
+ var UPDATE_SERVICE_PARAMS = serviceParams(true);
35
1337
  var RUNEYA_CAPABILITIES = [
36
1338
  {
37
1339
  name: "list_services",
1340
+ transformOutput: maskServices,
38
1341
  description: "List services, with the serviceId and agentId to use in other calls. Pass the projectId your context names to stay on the project the user is looking at, or another one from list_projects to look elsewhere. Called with no project, this can answer for every project of every organization on the machine \u2014 far more than the interface shows.",
39
1342
  route: "service.list",
40
1343
  method: "GET",
@@ -320,8 +1623,8 @@ var RUNEYA_CAPABILITIES = [
320
1623
  },
321
1624
  // ─── Lecture seule ───────────────────────────────────────────────────────
322
1625
  //
323
- // Tout ce qui se consulte sans rien changer. La création, la mise à jour et
324
- // la suppression restent hors MCP : elles s'ajouteront au cas par cas.
1626
+ // Tout ce qui se consulte sans rien changer. Les écritures s'ajoutent au cas
1627
+ // par cas : aujourd'hui les services et leurs variables, plus bas.
325
1628
  //
326
1629
  // Volontairement absentes, et à ne pas ajouter sans y regarder à deux fois,
327
1630
  // parce qu'elles rendent un secret : `environment.list` / `get` / `resolve` /
@@ -348,6 +1651,7 @@ var RUNEYA_CAPABILITIES = [
348
1651
  },
349
1652
  {
350
1653
  name: "get_service",
1654
+ transformOutput: maskServices,
351
1655
  description: "Read the full configuration of one service: its commands, ports, groups, runner, log sources and restart policy. list_services gives the ids.",
352
1656
  route: "service.get",
353
1657
  method: "GET",
@@ -358,13 +1662,145 @@ var RUNEYA_CAPABILITIES = [
358
1662
  },
359
1663
  {
360
1664
  name: "get_service_env",
361
- description: 'Read the environment variables a service runs with, and the project\'s variable inventory. `env` lists every key the service receives; a value reads "***" when it is a secret whose author did not share it with AI (sharing = ticking "AI read", or injecting it into the agents\' environment, which grants reading too). `envSecrets` says which keys are secret, `hiddenKeys` which ones are masked. A masked key is set on the service: never treat it as missing, never suggest adding it, and never pass "***" as a value \u2014 ask the user for it. `variables` describes every variable of the project \u2014 which environment defines it and its scope, its description, its flags, whether this machine overrides it, and `inService: false` for the ones this service does not receive. Use it to say where a variable must be changed instead of guessing. On an overridden variable, `sharedValue` is what the machine-local override replaces (the team\'s value, masked as "***" when unreadable); no other value appears there.',
1665
+ description: 'Read the environment variables a service runs with, and the project\'s variable inventory. `env` lists every key the service receives; a value reads "***" when it is a secret whose author did not share it with AI (sharing = ticking "AI read", or injecting it into the agents\' environment, which grants reading too). `envSecrets` says which keys are secret, `hiddenKeys` which ones are masked. A masked key is set on the service: never treat it as missing, never suggest adding it, and never pass "***" as a value \u2014 ask the user for it. `variables` describes every variable of the project \u2014 which environment defines it and its scope, its description, its flags, whether this machine overrides it, and `inService: false` for the ones this service does not receive. Use it to say where a variable must be changed instead of guessing. On an overridden variable, `sharedValue` is what the machine-local override replaces (the team\'s value, masked as "***" when unreadable); no other value appears there. This is the resolver: the values are what the service would receive \u2014 inheritance, {{environment.KEY}} references, this machine\'s overrides and server built-ins applied; agent built-ins stay as written until the service starts. Use it to check a variable you just composed. `unresolvedReferences` lists references nothing will fill (a typo, a variable that does not exist): fix them.',
362
1666
  route: "service.getEnv",
363
1667
  method: "GET",
364
1668
  params: [
365
- { name: "serviceId", description: "The service ID", required: true }
1669
+ { name: "serviceId", description: "The service ID", required: true },
1670
+ { name: "environmentId", description: "A global environment of the project to resolve in instead of the active one, without activating it (from list_environments). Omit for the active one.", required: false }
366
1671
  ],
367
- buildInput: (p) => ({ id: p.serviceId })
1672
+ buildInput: (p) => ({ id: p.serviceId, ...p.environmentId ? { environmentId: p.environmentId } : {} })
1673
+ },
1674
+ // ─── Écrire un service et ses variables ────────────────────────────────────
1675
+ //
1676
+ // Les variables s'écrivent à l'aveugle (`environment.setVariableBlind`) : une
1677
+ // IA remplace la valeur d'un secret sans la lire, et ne peut ni le rendre
1678
+ // public, ni le partager avec les IA. La règle tient côté serveur, dans la
1679
+ // route ; ces outils ne passent jamais par une route qui renvoie des valeurs
1680
+ // (`upsertVariable`, `removeVariable`, `update` rendent l'environnement entier).
1681
+ {
1682
+ name: "create_service",
1683
+ transformOutput: maskServices,
1684
+ description: "Create a service, native or Docker, in a project: it joins the project and gets its environments in the same call. Pass the projectId your context names. Projects are synced between machines, so write paths relative to the project root and put machine-specific values (a device serial, a local token) in environment variables, referenced as $NAME in commands \u2014 see the cwd, commands and shortcuts parameters. Then set its variables with set_environment_variable.",
1685
+ route: "service.create",
1686
+ method: "POST",
1687
+ params: [
1688
+ { name: "name", description: "The service name", required: true },
1689
+ { name: "projectId", description: "The project it joins: the one your context names, or another from list_projects. Without it, the service belongs to no project.", required: false },
1690
+ { name: "orgId", description: "Its organization. Needed only when the same project id exists in several.", required: false },
1691
+ ...CREATE_SERVICE_PARAMS
1692
+ ],
1693
+ buildInput: (p) => {
1694
+ const fields = serviceFields(p, CREATE_SERVICE_PARAMS);
1695
+ if (fields["runner"] === "docker" && !fields["dockerConfig"]) {
1696
+ throw new Error('dockerConfig: required with runner "docker" \u2014 give an "image" or a "dockerfile"');
1697
+ }
1698
+ return {
1699
+ name: p.name,
1700
+ ...fields,
1701
+ ...p.projectId ? { projectId: p.projectId } : {},
1702
+ ...p.orgId ? { orgId: p.orgId } : {}
1703
+ };
1704
+ }
1705
+ },
1706
+ {
1707
+ name: "add_service_to_project",
1708
+ description: "Add an existing service to a project, and create its environments \u2014 one for each of the project's environments, where its own variables go. Not needed after create_service, which already does it; calling it again changes nothing.",
1709
+ route: "project.addService",
1710
+ method: "POST",
1711
+ params: [
1712
+ { name: "projectId", description: "The project ID, from list_projects", required: true },
1713
+ { name: "serviceId", description: "The service ID", required: true },
1714
+ { name: "orgId", description: "Its organization. Needed only when the same project id exists in several.", required: false }
1715
+ ],
1716
+ buildInput: (p) => ({ projectId: p.projectId, serviceId: p.serviceId, ...p.orgId ? { orgId: p.orgId } : {} })
1717
+ },
1718
+ {
1719
+ name: "update_service",
1720
+ transformOutput: maskServices,
1721
+ description: "Change any part of a service configuration \u2014 commands, ports, health check, restart policy, shortcuts, log sources, whether it runs natively or in Docker (runner, dockerConfig)\u2026 Only the fields you pass change; a list or an object you pass replaces the current one whole. Read the service first with get_service.",
1722
+ route: "service.update",
1723
+ method: "POST",
1724
+ params: [
1725
+ { name: "serviceId", description: "The service ID", required: true },
1726
+ { name: "name", description: "New name", required: false },
1727
+ { name: "orgId", description: "Move the service to this organization vault. Leave unset unless asked.", required: false, schema: z22.string().max(128).nullable() },
1728
+ ...UPDATE_SERVICE_PARAMS
1729
+ ],
1730
+ buildInput: (p) => ({
1731
+ id: p.serviceId,
1732
+ ...p.name ? { name: p.name } : {},
1733
+ ...p.orgId !== void 0 ? { orgId: parseTyped("orgId", z22.string().max(128).nullable(), p.orgId) } : {},
1734
+ ...serviceFields(p, UPDATE_SERVICE_PARAMS)
1735
+ })
1736
+ },
1737
+ {
1738
+ name: "list_environments",
1739
+ description: "List the environments of a project, with no value: each one's id, name and scope (global = shared by the whole project, service = one service's own variables), which global environment is active, which service a service environment belongs to and which global environment activates it, its parents (it inherits their variables), `isolated` when a service environment does not inherit from its global one, and the variables it defines with their flags. Empty environments are listed too \u2014 a service you just created has one per global environment, where its own variables go. Use it to find the environmentId before set_environment_variable.",
1740
+ route: "environment.listForAi",
1741
+ method: "GET",
1742
+ params: [
1743
+ { name: "projectId", description: "The project ID: the one your context names, or another from list_projects", required: true },
1744
+ { name: "orgId", description: "Its organization. Needed only when the same project id exists in several.", required: false }
1745
+ ],
1746
+ buildInput: (p) => ({ projectId: p.projectId, ...p.orgId ? { orgId: p.orgId } : {} })
1747
+ },
1748
+ {
1749
+ name: "resolve_environment",
1750
+ description: "Resolve one environment alone \u2014 its variables with those inherited from its parents and this machine's overrides \u2014 as an AI may read it: secrets not shared with AI read \"***\". Built-in references ({{service.*}}, {{services.*}}, {{agent.*}}\u2026) are NOT filled, since they depend on the service that receives the variable; use get_service_env for a service's final values. `unresolvedReferences` lists references nothing will fill: a misspelled {{environment.KEY}}, or a name that is no built-in.",
1751
+ route: "environment.resolveForAi",
1752
+ method: "GET",
1753
+ params: [
1754
+ { name: "environmentId", description: "The environment, from list_environments", required: true }
1755
+ ],
1756
+ buildInput: (p) => ({ environmentId: p.environmentId })
1757
+ },
1758
+ {
1759
+ name: "set_environment_variable",
1760
+ description: `Create or change an environment variable, by name, in one environment \u2014 global or service, same rules for both. Find the environmentId with list_environments. Where it belongs: a value shared by several services (a database host, an API base URL) goes ONCE in the active global environment; services inherit it. A value only one service needs goes in that service's environment (scope service, activated by the active global one), where it also overrides a global variable of the same name. Never hardcode what Runeya already knows: a service's own port is {{service.PORT}}, its own URL {{service.URL}}, another service's address {{services.<slug>.URL}} \u2014 a copied "3210" or "http://localhost:3211" breaks as soon as a port changes or the project runs on another machine. If the port a variable needs is not declared on its service, declare it there (update_service, ports) instead of writing the number. When a written value contains a port or URL of a project service, the response lists \`suggestions\`: rewrite the value with those references. Compose instead of copying: a value can reference another variable of the resolved environment as {{environment.KEY}} (e.g. "postgres://{{environment.DB_USER}}@{{environment.DB_HOST}}:5432"). ${BUILTINS_HELP} After writing, check the result with get_service_env (a service, optionally in another global environment) or resolve_environment (an environment alone). References are substituted in one pass: a reference to a variable whose own value is only a reference may stay unexpanded, so point at the variable that holds the actual value. $NAME is not a reference here: it only expands inside a shell command. pre and post are concatenated around the value, each resolved separately. You can replace a secret's value without reading it, and create a variable as secret. You cannot make a secret public nor make it readable by AI: that stays the user's decision. Never pass "***" as a value. The response never contains the value.`,
1761
+ route: "environment.setVariableBlind",
1762
+ method: "POST",
1763
+ params: [
1764
+ { name: "environmentId", description: "The environment that holds the variable, from list_environments", required: true },
1765
+ { name: "key", description: "The variable name, e.g. DATABASE_URL", required: true },
1766
+ { name: "value", description: "The new value, possibly with {{environment.KEY}} references. Omit to leave it unchanged.", required: false },
1767
+ { name: "pre", description: 'Text put before the value (e.g. "https://"). Omit to leave it unchanged.', required: false },
1768
+ { name: "post", description: 'Text put after the value (e.g. "/api"). Omit to leave it unchanged.', required: false },
1769
+ { name: "isSecret", description: '"true" to store it as a secret. On an existing public variable, makes it secret.', required: false },
1770
+ { name: "description", description: "What the variable is for, in markdown", required: false }
1771
+ ],
1772
+ buildInput: (p) => ({
1773
+ environmentId: p.environmentId,
1774
+ key: p.key,
1775
+ ...p.value !== void 0 ? { value: p.value } : {},
1776
+ ...p.pre !== void 0 ? { pre: p.pre } : {},
1777
+ ...p.post !== void 0 ? { post: p.post } : {},
1778
+ ...p.isSecret !== void 0 ? { isSecret: toBool(p.isSecret) } : {},
1779
+ ...p.description !== void 0 ? { description: p.description } : {}
1780
+ })
1781
+ },
1782
+ {
1783
+ name: "set_environment_inheritance",
1784
+ description: "Switch whether a service environment inherits the variables of the global environment that activates it (the default), or is isolated from it and receives only its own variables. list_environments shows this as `isolated`. Isolating a service is unusual: it loses every shared variable of the project. Do it only when the user asks, and never to work around a variable \u2014 override it in the service environment instead.",
1785
+ route: "environment.setInheritanceBlind",
1786
+ method: "POST",
1787
+ params: [
1788
+ { name: "environmentId", description: "A service environment (scope service), from list_environments", required: true },
1789
+ { name: "inherit", description: '"true" to inherit from the global environment, "false" to isolate', required: true, schema: z22.boolean() }
1790
+ ],
1791
+ buildInput: (p) => ({ environmentId: p.environmentId, inherit: toBool(p.inherit ?? "true") })
1792
+ },
1793
+ {
1794
+ name: "remove_environment_variable",
1795
+ description: "Delete an environment variable, by name, from one environment. Its value is lost.",
1796
+ route: "environment.removeVariableBlind",
1797
+ method: "POST",
1798
+ params: [
1799
+ { name: "environmentId", description: "The environment that holds the variable", required: true },
1800
+ { name: "key", description: "The variable name", required: true }
1801
+ ],
1802
+ buildInput: (p) => ({ environmentId: p.environmentId, key: p.key }),
1803
+ destructive: true
368
1804
  },
369
1805
  {
370
1806
  name: "get_service_metrics",
@@ -590,13 +2026,29 @@ var RUNEYA_CAPABILITIES = [
590
2026
  buildInput: () => void 0
591
2027
  }
592
2028
  ];
593
- async function callTrpc(baseUrl, route, method, input, authToken) {
2029
+ function buildMcpShape(cap) {
2030
+ const shape = {};
2031
+ for (const param of cap.params) {
2032
+ const base = (param.schema ?? z32.string()).describe(param.description);
2033
+ shape[param.name] = param.required ? base : base.optional();
2034
+ }
2035
+ shape["authToken"] = z32.string().describe("Bearer token for authentication").optional();
2036
+ return shape;
2037
+ }
2038
+ function toRawParams(input, cap) {
2039
+ const typed = new Set(cap?.params.filter((p) => p.schema).map((p) => p.name));
2040
+ return Object.fromEntries(Object.entries(input).map(([k, v]) => [
2041
+ k,
2042
+ v === null && typed.has(k) ? "null" : v == null ? void 0 : typeof v === "object" ? JSON.stringify(v) : String(v)
2043
+ ]));
2044
+ }
2045
+ async function callTrpc(baseUrl, route, method, input, authToken, fetchImpl = fetch) {
594
2046
  const headers = {
595
2047
  "Content-Type": "application/json",
596
2048
  "Authorization": `Bearer ${authToken}`
597
2049
  };
598
2050
  const url = method === "GET" && input ? `${baseUrl}/api/trpc/${route}?input=${encodeURIComponent(JSON.stringify(input))}` : `${baseUrl}/api/trpc/${route}`;
599
- const res = await fetch(url, {
2051
+ const res = await fetchImpl(url, {
600
2052
  method,
601
2053
  headers,
602
2054
  ...method === "POST" ? { body: JSON.stringify(input ?? {}) } : {},
@@ -607,8 +2059,10 @@ async function callTrpc(baseUrl, route, method, input, authToken) {
607
2059
  const result = json["result"];
608
2060
  return result?.["data"] ?? result ?? json;
609
2061
  }
610
-
611
- // src/project-default.ts
2062
+ async function runCapability(cap, baseUrl, params, authToken, fetchImpl = fetch) {
2063
+ const result = await callTrpc(baseUrl, cap.route, cap.method, cap.buildInput(params), authToken, fetchImpl);
2064
+ return cap.transformOutput ? cap.transformOutput(result) : result;
2065
+ }
612
2066
  function applyProjectAnchor(cap, params, anchor) {
613
2067
  if (!anchor.projectId) return params;
614
2068
  const accepts = (name) => cap.params.some((p) => p.name === name);
@@ -633,19 +2087,14 @@ var PROJECT_ANCHOR = {
633
2087
  };
634
2088
  var server = new McpServer({ name: "runeya", version: "1.0.0" });
635
2089
  for (const cap of RUNEYA_CAPABILITIES) {
636
- const zodShape = {};
637
- for (const param of cap.params) {
638
- const base = z.string().describe(param.description);
639
- zodShape[param.name] = param.required ? base : base.optional();
640
- }
641
- zodShape["authToken"] = z.string().describe("Bearer token for authentication").optional();
642
- server.tool(cap.name, cap.description, zodShape, async (input) => {
2090
+ server.tool(cap.name, cap.description, buildMcpShape(cap), async (input) => {
643
2091
  try {
644
- const raw = input.authToken;
2092
+ const rawParams = toRawParams(input, cap);
2093
+ const raw = rawParams["authToken"];
645
2094
  const authToken = raw && !raw.startsWith("$") ? raw : ENV_TOKEN || INTERNAL_TOKEN || void 0;
646
2095
  if (!authToken) throw new Error("No auth token available");
647
- const params = applyProjectAnchor(cap, input, PROJECT_ANCHOR);
648
- const result = await callTrpc(BASE_URL, cap.route, cap.method, cap.buildInput(params), authToken);
2096
+ const params = applyProjectAnchor(cap, rawParams, PROJECT_ANCHOR);
2097
+ const result = await runCapability(cap, BASE_URL, params, authToken);
649
2098
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
650
2099
  } catch (err) {
651
2100
  return {
@@ -659,7 +2108,7 @@ if (CONVERSATION_ID && INTERNAL_TOKEN) {
659
2108
  server.tool(
660
2109
  "ask_user",
661
2110
  "Ask the user a question and wait for their reply. Use this when you need clarification or input from the user to proceed.",
662
- { question: z.string().describe("The question to ask the user") },
2111
+ { question: z24.string().describe("The question to ask the user") },
663
2112
  async ({ question }) => {
664
2113
  try {
665
2114
  const res = await fetch(`${BASE_URL}/api/trpc/scenario.requestInput`, {