@runeya/runeya 2.0.53 → 2.0.55

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 (248) hide show
  1. package/agent/index.js +31 -0
  2. package/agent/index.js.map +1 -1
  3. package/agent-manager-LSAJSO3X.js +7 -0
  4. package/{chunk-EL75GG7O.js → chunk-Q2WY6PYX.js} +32 -1
  5. package/{chunk-EL75GG7O.js.map → chunk-Q2WY6PYX.js.map} +1 -1
  6. package/index.js +1 -1
  7. package/mcp-server/index.js +28 -0
  8. package/mcp-server/index.js.map +1 -1
  9. package/package.json +1 -1
  10. package/{src-4GK5OK3K.js → src-WCSXKTXA.js} +148 -35
  11. package/src-WCSXKTXA.js.map +1 -0
  12. package/web/assets/AgentScalarChatInterface.vue-BMqFzngo.js +13 -0
  13. package/web/assets/AgentTerminalPage-BaeZYHEz.js +1 -0
  14. package/web/assets/AiChatPage-cppSydlY.js +1 -0
  15. package/web/assets/AppLayout-DKaFXFNm.js +1 -0
  16. package/web/assets/AuditPage-BoqD2rTL.js +1 -0
  17. package/web/assets/CloudAccountPage-BhXNhby1.js +1 -0
  18. package/web/assets/CloudAccountPage-BvlALaKX.js +1 -0
  19. package/web/assets/CloudMessagingPage-DJGOTMJG.css +1 -0
  20. package/web/assets/CloudMessagingPage-DU_Y4dCb.js +2 -0
  21. package/web/assets/DashboardPage-UpH-RReH.js +1 -0
  22. package/web/assets/{EditorIcon-BYTcFJnr.js → EditorIcon-C69miffT.js} +2 -2
  23. package/web/assets/EnvironmentForm-DMG36ruj.js +108 -0
  24. package/web/assets/EnvironmentFormPage-DZQ1aCFu.js +1 -0
  25. package/web/assets/EnvironmentListPage-BxHOrX38.js +1 -0
  26. package/web/assets/EnvironmentSelector-DzSlMAQT.js +1 -0
  27. package/web/assets/KanbanBoardPage-A-JNWTlH.css +1 -0
  28. package/web/assets/KanbanBoardPage-DmguTXbS.js +4 -0
  29. package/web/assets/KanbanListPage-BSWy3lH-.css +1 -0
  30. package/web/assets/KanbanListPage-EwWSNHFg.js +1 -0
  31. package/web/assets/LaunchProjectPage-uL_AUfYG.js +1 -0
  32. package/web/assets/LaunchServicesPage-BCoT8uka.js +1 -0
  33. package/web/assets/LogViewer-CP5tPjpN.js +3 -0
  34. package/web/assets/{ProcessControls-Dkf-zJF8.js → ProcessControls-BT8Hq3fS.js} +1 -1
  35. package/web/assets/ProcessDetailPage-Dl5eVR0B.js +1 -0
  36. package/web/assets/{ProcessMetrics-BxwLdytO.js → ProcessMetrics-DCPeQlXs.js} +2 -2
  37. package/web/assets/ProjectDetailPage-I4it0Fch.js +1 -0
  38. package/web/assets/ProjectListPage-BpdbODZn.js +1 -0
  39. package/web/assets/RandomJobTestPage-B54p6EdF.js +2 -0
  40. package/web/assets/ScenarioEditorPage-C0NIE3t8.js +14 -0
  41. package/web/assets/SendToChatDialog-Dy_x4DDI.js +1 -0
  42. package/web/assets/ServiceControlsBar-DPDmBLOQ.js +1 -0
  43. package/web/assets/ServiceDetailPage-D_hndxqK.js +2 -0
  44. package/web/assets/ServiceFormPage-DAyFlHvA.js +1 -0
  45. package/web/assets/SettingsPage-CcuC2wFK.js +2062 -0
  46. package/web/assets/UnlockPage-B58VPSfR.js +1 -0
  47. package/web/assets/VariablesTable-Mj9gxe8i.js +1 -0
  48. package/web/assets/VaultMigrationPage-Dlo4g-x3.js +1 -0
  49. package/web/assets/VersionBadge-BAI4Ayxx.js +1 -0
  50. package/web/assets/WikiPage-C0PzmD-1.js +1 -0
  51. package/web/assets/WikiView-1GXLAPfT.js +1 -0
  52. package/web/assets/add-scalar-classes-BkwoBpWy.js +387 -0
  53. package/web/assets/auth-errors-B7MynIJ7.js +1 -0
  54. package/web/assets/{autocomplete-DLtfuYAg.js → autocomplete--65VKbBs.js} +4 -4
  55. package/web/assets/{basic-shape-diamond.svg-Dwn3EJf7.js → basic-shape-diamond.svg-CAMv78H-.js} +1 -1
  56. package/web/assets/{basic-shape-hexagon.svg-kpOvfzAi.js → basic-shape-hexagon.svg-XSrcZLW0.js} +1 -1
  57. package/web/assets/{basic-shape-primary-circle-ellipse-round.svg-CZpeeE8h.js → basic-shape-primary-circle-ellipse-round.svg-BgVH88jK.js} +1 -1
  58. package/web/assets/{basic-shape-primary-square-rectangle.svg-lIzT-3bQ.js → basic-shape-primary-square-rectangle.svg-xTzxoq2Y.js} +1 -1
  59. package/web/assets/{basic-shape-shield.svg-DB-n6Wmn.js → basic-shape-shield.svg-BTgpH2yJ.js} +1 -1
  60. package/web/assets/{browser-wjfUiObI.js → browser-3-eXKCbo.js} +1 -1
  61. package/web/assets/{browser-Dm_lNzZ-.js → browser-CUmhJaQx.js} +1 -1
  62. package/web/assets/card-C002Ads9.js +32 -0
  63. package/web/assets/{checkbox-lVXx5U1s.js → checkbox-oRGfXjHa.js} +3 -3
  64. package/web/assets/{chip-Cc40pDDT.js → chip-C16evUWL.js} +2 -2
  65. package/web/assets/client-DQ7l0X0R.js +24 -0
  66. package/web/assets/cloud-chat.store-6rrle1LS.js +1 -0
  67. package/web/assets/cloud-session-C1j_MV8O.js +1 -0
  68. package/web/assets/column-_TAitU2u.js +907 -0
  69. package/web/assets/{computer-device-desktop-monitor.svg-B8fVLOqV.js → computer-device-desktop-monitor.svg-Dc6aGusC.js} +1 -1
  70. package/web/assets/{computer-device-desktop.svg-CKeybOQk.js → computer-device-desktop.svg-CM2cPc30.js} +1 -1
  71. package/web/assets/{computer-device-laptop.svg-C5xV7_Nt.js → computer-device-laptop.svg-Cgkag9qJ.js} +1 -1
  72. package/web/assets/{computer-device-mobile-phone-android-samsung-back.svg-5CRKvrQx.js → computer-device-mobile-phone-android-samsung-back.svg-zn5env47.js} +1 -1
  73. package/web/assets/{computer-device-mobile-phone-android-samsung.svg-Da4aZrXd.js → computer-device-mobile-phone-android-samsung.svg-oS1pUYbb.js} +1 -1
  74. package/web/assets/{computer-device-mobile-phone-iphone-x-back.svg-D9phyiQZ.js → computer-device-mobile-phone-iphone-x-back.svg-Cn7NWYpM.js} +1 -1
  75. package/web/assets/{computer-device-mobile-phone-iphone-x.svg-V7yMTZCu.js → computer-device-mobile-phone-iphone-x.svg-B5OAArcG.js} +1 -1
  76. package/web/assets/{computer-device-mobile-tablet-touch.svg-CGMdXdex.js → computer-device-mobile-tablet-touch.svg-DUz5IocO.js} +1 -1
  77. package/web/assets/{computer-device-mobile-tablet.svg-66hlusLK.js → computer-device-mobile-tablet.svg--VeqZdb9.js} +1 -1
  78. package/web/assets/{computer-device-network-ethernet-cat6.svg-BhuzmqfI.js → computer-device-network-ethernet-cat6.svg-DXH_pdMh.js} +1 -1
  79. package/web/assets/{computer-device-network-lan-www.svg-BXLNIvQ6.js → computer-device-network-lan-www.svg-uqOsigHB.js} +1 -1
  80. package/web/assets/{computer-device-network-wifi-connection.svg-CaVzq_6z.js → computer-device-network-wifi-connection.svg-BP5vkv9N.js} +1 -1
  81. package/web/assets/{computer-device-network-wifi-router.svg-DasSXsmT.js → computer-device-network-wifi-router.svg-CjK4RVQx.js} +1 -1
  82. package/web/assets/{cssMode-CokQPPhF.js → cssMode-CN46e-Az.js} +1 -1
  83. package/web/assets/{divider-3st3S0cz.js → divider-LLul0-iW.js} +2 -2
  84. package/web/assets/{ecology-science-erlenmeyer-flask.svg-0xfq6Yyi.js → ecology-science-erlenmeyer-flask.svg-cnbAOGwK.js} +1 -1
  85. package/web/assets/{fieldset-CvZZBOcz.js → fieldset-ZxYA8U84.js} +2 -2
  86. package/web/assets/{freemarker2-1YMoAedE.js → freemarker2-Qlh6aPDo.js} +1 -1
  87. package/web/assets/{handlebars-wAW8puhT.js → handlebars-CpN0Qvyd.js} +1 -1
  88. package/web/assets/{html-DdFlw76f.js → html-DnKAO9rJ.js} +1 -1
  89. package/web/assets/{htmlMode-Cy1vm8Ag.js → htmlMode-Bj-LpSqo.js} +1 -1
  90. package/web/assets/{image-flash-lightning.svg-COFAE0wR.js → image-flash-lightning.svg-2F6xtNBK.js} +1 -1
  91. package/web/assets/{image-picture-flower.svg-ezqcE4KS.js → image-picture-flower.svg-BW6lv8j7.js} +1 -1
  92. package/web/assets/{index-Ccntdgfe.js → index-Bdr5knDo.js} +299 -299
  93. package/web/assets/{interface-alert-exclamation-diamond.svg-CHGW-cLp.js → interface-alert-exclamation-diamond.svg-CEYeQFhC.js} +1 -1
  94. package/web/assets/{interface-alert-exclamation-triangle-warning.svg-DvPTCqs0.js → interface-alert-exclamation-triangle-warning.svg-CJfmEMRl.js} +1 -1
  95. package/web/assets/{interface-alert-information-circle.svg-jX4BkfAJ.js → interface-alert-information-circle.svg-Dmru-S4E.js} +1 -1
  96. package/web/assets/{interface-award-crown.svg-DtuQ-cID.js → interface-award-crown.svg-UJmfoU0o.js} +1 -1
  97. package/web/assets/{interface-bookmark.svg-BneowIGx.js → interface-bookmark-tag.svg-DYlOV-H_.js} +1 -1
  98. package/web/assets/{interface-bookmark-tag.svg-CAFVyAoV.js → interface-bookmark.svg-BtCSsE7I.js} +1 -1
  99. package/web/assets/{interface-calendar-date-one.svg-CfpOGCx4.js → interface-calendar-date-one.svg-BG8zrSlq.js} +1 -1
  100. package/web/assets/{interface-content-book-open-pages.svg-Cl1dxQ4s.js → interface-content-book-open-pages.svg-CK8vOvUS.js} +1 -1
  101. package/web/assets/{interface-content-book-page.svg-CEhybPQh.js → interface-content-book-page.svg-txhkDQQp.js} +1 -1
  102. package/web/assets/{interface-content-file.svg-HK08zzYO.js → interface-content-file.svg-UZc-jRFQ.js} +1 -1
  103. package/web/assets/interface-content-folder.svg-B10e_dq6.js +1 -0
  104. package/web/assets/{interface-content-folder.svg-DuncK7Kw.js → interface-content-folder.svg-oD2MMIrG.js} +1 -1
  105. package/web/assets/{interface-copy-clipboard.svg-CHxj1VUB.js → interface-copy-clipboard.svg-VhpbGb8y.js} +1 -1
  106. package/web/assets/{interface-edit-attachment.svg-DQ-TGp2N.js → interface-edit-attachment.svg-CuGtstos.js} +1 -1
  107. package/web/assets/{interface-edit-binocular.svg-CIUJcI__.js → interface-edit-binocular.svg-Naq_0QWK.js} +1 -1
  108. package/web/assets/{interface-edit-magic-wand.svg-Bn7wsTVd.js → interface-edit-magic-wand.svg-DrbefRb0.js} +1 -1
  109. package/web/assets/{interface-edit-tool-paint-roller.svg-BLR1HoWs.js → interface-edit-tool-paint-roller.svg-NzqkhEEN.js} +1 -1
  110. package/web/assets/{interface-edit-tool-pencil.svg-DM3xZUtj.js → interface-edit-tool-pencil.svg-CHQRBxu1.js} +1 -1
  111. package/web/assets/{interface-favorite-award.svg-Bc8_APGD.js → interface-favorite-award.svg-CtNtg14Q.js} +1 -1
  112. package/web/assets/{interface-favorite-flag.svg-BBV01eyw.js → interface-favorite-flag.svg-80koie1H.js} +1 -1
  113. package/web/assets/{interface-favorite-heart.svg-DpFl3KSk.js → interface-favorite-heart.svg-DA5IHByK.js} +1 -1
  114. package/web/assets/{interface-favorite-star.svg-CaFUQ9jK.js → interface-favorite-star.svg-JGlI0-Gv.js} +1 -1
  115. package/web/assets/{interface-favorite-stars-sparkles.svg-19cy1b4g.js → interface-favorite-stars-sparkles.svg-DVC5nlik.js} +1 -1
  116. package/web/assets/{interface-hierarchy-flowchart.svg-Btiu5TuK.js → interface-hierarchy-flowchart.svg-z_RqQP1A.js} +1 -1
  117. package/web/assets/{interface-home-house.svg-Bp4aVUgs.js → interface-home-house.svg-DSwCUQvt.js} +1 -1
  118. package/web/assets/{interface-hyperlink.svg-Df34T3Eu.js → interface-hyperlink.svg-voKgjrwo.js} +1 -1
  119. package/web/assets/{interface-lighting-brightness.svg-CBJnLIw7.js → interface-lighting-brightness.svg-qz6LzfZ_.js} +1 -1
  120. package/web/assets/{interface-lock-closed.svg-C082mEtr.js → interface-lock-closed.svg-BCXfx-uz.js} +1 -1
  121. package/web/assets/{interface-lock-open-unlock.svg-ktQ_lN_X.js → interface-lock-open-unlock.svg-CLnjXmO8.js} +1 -1
  122. package/web/assets/{interface-login-key.svg-1JZV_q3n.js → interface-login-key.svg-Rb6Hb0dk.js} +1 -1
  123. package/web/assets/{interface-search.svg-BWOepCe2.js → interface-search.svg-DisX65jX.js} +1 -1
  124. package/web/assets/{interface-setting-cog.svg-Ck7-QPf8.js → interface-setting-cog.svg-VBsFZ4k1.js} +1 -1
  125. package/web/assets/{interface-share-megaphone-bullhorn.svg-B4XWLcvf.js → interface-share-megaphone-bullhorn.svg-zBjfLFB-.js} +1 -1
  126. package/web/assets/{interface-share-rocket.svg-jsXjbfvo.js → interface-share-rocket.svg-84fU9l-d.js} +1 -1
  127. package/web/assets/{interface-share-satellite.svg-DYc-pAdI.js → interface-share-satellite.svg-BX00A6-3.js} +1 -1
  128. package/web/assets/{interface-share-space-ship.svg-azKKMF8L.js → interface-share-space-ship.svg-Bd4tm7i6.js} +1 -1
  129. package/web/assets/{interface-share.svg-k0lPxn1t.js → interface-share.svg-CKrFOUGn.js} +1 -1
  130. package/web/assets/{interface-signal-square.svg-eCO4ev15.js → interface-signal-square.svg-ChP-Ag0w.js} +1 -1
  131. package/web/assets/{interface-time-clock-circle.svg-C0Sm0_j9.js → interface-time-clock-circle.svg-BK02YgSw.js} +1 -1
  132. package/web/assets/{interface-time-hour-glass.svg-hfRVIC1r.js → interface-time-hour-glass.svg-0NvuFWjn.js} +1 -1
  133. package/web/assets/{interface-users-multiple.svg-Dm9UimfL.js → interface-users-multiple.svg-Ba9lXpUM.js} +1 -1
  134. package/web/assets/{interface-weather-moon.svg-BhxFHPbN.js → interface-weather-moon.svg-CwqP_Nej.js} +1 -1
  135. package/web/assets/{javascript-_AR6wrF0.js → javascript-CFWxThAh.js} +1 -1
  136. package/web/assets/{jsonMode-CYWBTJpV.js → jsonMode-Cdw2w5W7.js} +2 -2
  137. package/web/assets/{liquid-Doe_Qoxn.js → liquid-cH8Ar8JC.js} +1 -1
  138. package/web/assets/{lspLanguageFeatures-TK5k9ahW.js → lspLanguageFeatures-CSQgHrR9.js} +3 -3
  139. package/web/assets/{mail-chat-bubble-square.svg-CitsmxJ_.js → mail-chat-bubble-square.svg-C-ovjGCd.js} +1 -1
  140. package/web/assets/{mail-send-email-paper-airplane.svg-CYDMogt4.js → mail-send-email-paper-airplane.svg-BZayiABF.js} +1 -1
  141. package/web/assets/{mail-send-envelope.svg-s-A4ytfv.js → mail-send-envelope.svg-C_cz8SOf.js} +1 -1
  142. package/web/assets/{mdx-CSf3fjQb.js → mdx-QDarK7vD.js} +1 -1
  143. package/web/assets/{message-5nViABpL.js → message-QiLCZQ6U.js} +2 -2
  144. package/web/assets/{minus-mDLJQeXY.js → minus-CjIL1IQ0.js} +2 -2
  145. package/web/assets/modal--_j6f_13.js +1 -0
  146. package/web/assets/modal-C6AVHTdY.js +5 -0
  147. package/web/assets/{money-cashier-receipt.svg-B3w4dcvy.js → money-cashier-receipt.svg-CGCVucBa.js} +1 -1
  148. package/web/assets/{money-currency-dollar-pay.svg-By5pgatC.js → money-currency-dollar-pay.svg-BLMxlzG8.js} +1 -1
  149. package/web/assets/{money-graph-arrow-increase.svg-JJK_oYl6.js → money-graph-arrow-increase.svg-n46081bf.js} +1 -1
  150. package/web/assets/{money-graph-bar-chart-increase.svg-BMvEIVpy.js → money-graph-bar-chart-increase.svg-Dyf3rVrr.js} +1 -1
  151. package/web/assets/{multiselect-CqGmdE3J.js → multiselect-CeWstZUW.js} +3 -3
  152. package/web/assets/{nature-ecology-leaf.svg-CGCHa8bD.js → nature-ecology-leaf.svg-BSyMcKpo.js} +1 -1
  153. package/web/assets/{password-CSX8oB5M.js → password-CWjT4bmn.js} +4 -4
  154. package/web/assets/{phone-telephone.svg-CA8_wOQH.js → phone-telephone.svg-AdhrXmF7.js} +1 -1
  155. package/web/assets/{plus-CGTKvVZ7.js → plus-M3hWJrgM.js} +6 -6
  156. package/web/assets/process.store-DMSZ0UO0.js +1 -0
  157. package/web/assets/{programming-bug.svg-Cizii8p1.js → programming-bug.svg-CH-KL4Vs.js} +1 -1
  158. package/web/assets/{programming-cloud.svg-pnwxJHaK.js → programming-cloud.svg-iqzO95XV.js} +1 -1
  159. package/web/assets/{programming-computer-database-server.svg-CNt3Jbql.js → programming-computer-database-server.svg-CwYDnoeu.js} +1 -1
  160. package/web/assets/{programming-computer-database.svg-ESSkZX3t.js → programming-computer-database.svg-DIR7nexS.js} +1 -1
  161. package/web/assets/{programming-module-four-layout.svg-BGbJvE0O.js → programming-module-four-layout.svg-BLM5JSuM.js} +1 -1
  162. package/web/assets/{programming-module-three.svg-D3gOTAlw.js → programming-module-three.svg-VkTvwtGj.js} +1 -1
  163. package/web/assets/{programming-module.svg-CSHFfsFS.js → programming-module.svg-ploUKZF1.js} +1 -1
  164. package/web/assets/{programming-script-code.svg-DjFoDv0c.js → programming-script-code.svg-CBb1n9Wg.js} +1 -1
  165. package/web/assets/{python-MEGp0q_z.js → python-D50H1ABE.js} +1 -1
  166. package/web/assets/{razor-CEazjH4x.js → razor-DlRTIZjA.js} +1 -1
  167. package/web/assets/router-CJ2cAlAQ.js +1 -0
  168. package/web/assets/settings-scope-RHM8yNPa.js +1 -0
  169. package/web/assets/{settings.store-a49Jijfe.js → settings.store-D8H5j7LI.js} +1 -1
  170. package/web/assets/{shopping-cart.svg-Cu7M1oni.js → shopping-cart.svg-f8XztG2a.js} +1 -1
  171. package/web/assets/{shopping-gift-present.svg-Cdnu9uAQ.js → shopping-gift-present.svg-CCWvUU2s.js} +1 -1
  172. package/web/assets/{shopping-shipping-box-parcel-package.svg-C6BL6pCC.js → shopping-shipping-box-parcel-package.svg-B34dpKOx.js} +1 -1
  173. package/web/assets/src-BGDKWMIa.js +1 -0
  174. package/web/assets/{src-BKhMPhsU.js → src-BNFzRy6K.js} +34 -34
  175. package/web/assets/{src-BMVu6BfT.css → src-Bhd-KJy_.css} +1 -1
  176. package/web/assets/src-DIxcn8ra.css +1 -0
  177. package/web/assets/{tabpanel-B9VkBnSU.js → tabpanel-CNk_cZBK.js} +3 -3
  178. package/web/assets/{tag-new-circle.svg-BpXDXKC4.js → tag-new-circle.svg-DfVbdtgP.js} +1 -1
  179. package/web/assets/{travel-map-earth-globe.svg-B_t8kO2f.js → travel-map-earth-globe.svg-DtHjmNYO.js} +1 -1
  180. package/web/assets/trpc-zpvXCcIc.js +1 -0
  181. package/web/assets/{tsMode-lBRYpyez.js → tsMode-JB8srzcV.js} +6 -6
  182. package/web/assets/{typescript-DGOxNj9C.js → typescript-tyJPc3H7.js} +1 -1
  183. package/web/assets/useAiChatDrawer-DBi9CDz5.js +1 -0
  184. package/web/assets/useCloudOrg-BZaqB7v3.css +1 -0
  185. package/web/assets/useCloudOrg-DoXBgqMB.js +1 -0
  186. package/web/assets/{useProjectCatalog-CNbze2zg.js → useProjectCatalog-Dm1KHBII.js} +1 -1
  187. package/web/assets/{xml-Cqgx2kWf.js → xml-C7fJ7rgN.js} +1 -1
  188. package/web/assets/{yaml-CIs4cY7e.js → yaml-C7Vw_RLP.js} +1 -1
  189. package/web/index.html +1 -1
  190. package/agent-manager-RGDHYM64.js +0 -7
  191. package/src-4GK5OK3K.js.map +0 -1
  192. package/web/assets/AgentScalarChatInterface.vue-Cz4cGFw_.js +0 -13
  193. package/web/assets/AgentTerminalPage-ChRcIGvk.js +0 -1
  194. package/web/assets/AiChatPage-jeAEz3pL.js +0 -1
  195. package/web/assets/AppLayout-C8-7N9YJ.js +0 -1
  196. package/web/assets/AuditPage-DfJlEoaI.js +0 -1
  197. package/web/assets/CloudAccountPage--6fr9upU.js +0 -1
  198. package/web/assets/CloudAccountPage-CI6Vvfrv.js +0 -1
  199. package/web/assets/CloudMessagingPage-CWz2XG-O.js +0 -2
  200. package/web/assets/CloudMessagingPage-x4bDmgyb.css +0 -1
  201. package/web/assets/DashboardPage-Bkla6ZI9.js +0 -1
  202. package/web/assets/EnvironmentForm-Tody7LuY.js +0 -108
  203. package/web/assets/EnvironmentFormPage-r_Hn2SiC.js +0 -1
  204. package/web/assets/EnvironmentListPage-BPQL4Fdp.js +0 -1
  205. package/web/assets/EnvironmentSelector-CsXJXDJE.js +0 -1
  206. package/web/assets/KanbanBoardPage-C2Cj_u1W.js +0 -4
  207. package/web/assets/KanbanBoardPage-ZIYuV1kG.css +0 -1
  208. package/web/assets/KanbanListPage-DG04Ci-t.js +0 -1
  209. package/web/assets/KanbanListPage-yeTYeAas.css +0 -1
  210. package/web/assets/LaunchProjectPage-ZU10tRlq.js +0 -1
  211. package/web/assets/LaunchServicesPage-rLishQca.js +0 -1
  212. package/web/assets/LogViewer-DkR3A0v0.js +0 -3
  213. package/web/assets/ProcessDetailPage-vDdHOtno.js +0 -1
  214. package/web/assets/ProjectDetailPage-Bu2gDzDU.js +0 -1
  215. package/web/assets/ProjectListPage-zlXxla_K.js +0 -1
  216. package/web/assets/RandomJobTestPage-DkxLX-Uy.js +0 -2
  217. package/web/assets/ScenarioEditorPage-Dlgug19y.js +0 -14
  218. package/web/assets/SendToChatDialog-BbMjL5KU.js +0 -1
  219. package/web/assets/ServiceControlsBar-D9mA1wIv.js +0 -1
  220. package/web/assets/ServiceDetailPage-CPtHs7te.js +0 -2
  221. package/web/assets/ServiceFormPage-D6zoG4d2.js +0 -1
  222. package/web/assets/SettingsPage-BL1cbj_d.js +0 -2062
  223. package/web/assets/UnlockPage-tTNE4QTc.js +0 -1
  224. package/web/assets/VariablesTable-C8UT5LGj.js +0 -1
  225. package/web/assets/VaultMigrationPage-ee6mGXkE.js +0 -1
  226. package/web/assets/VersionBadge-XGdKeJYP.js +0 -1
  227. package/web/assets/WikiPage-DBxWCk1C.js +0 -1
  228. package/web/assets/WikiView-CtMG-Mpi.js +0 -1
  229. package/web/assets/add-scalar-classes-CjP6yoH9.js +0 -387
  230. package/web/assets/auth-errors-C7Lmr_5E.js +0 -1
  231. package/web/assets/card-C3zlSqpG.js +0 -32
  232. package/web/assets/client-CN9LxBfq.js +0 -24
  233. package/web/assets/cloud-chat.store-CKtcP8mx.js +0 -1
  234. package/web/assets/cloud-session-luM5H14C.js +0 -1
  235. package/web/assets/column-DlQNKY_S.js +0 -907
  236. package/web/assets/interface-content-folder.svg-BD3Sy4hk.js +0 -1
  237. package/web/assets/modal-DcxJxueq.js +0 -5
  238. package/web/assets/modal-n2wMDd7F.js +0 -1
  239. package/web/assets/process.store-CTLjlYjT.js +0 -1
  240. package/web/assets/router-BmJL8z_u.js +0 -1
  241. package/web/assets/settings-scope-BGuX4AI9.js +0 -1
  242. package/web/assets/src-DQvVUJe0.js +0 -1
  243. package/web/assets/src-DXFRFEWt.css +0 -1
  244. package/web/assets/trpc-B-qv_zm2.js +0 -1
  245. package/web/assets/useAiChatDrawer-xv2HAiHA.js +0 -1
  246. package/web/assets/useCloudOrg-DinvbrpR.css +0 -1
  247. package/web/assets/useCloudOrg-_Z_zfd63.js +0 -1
  248. /package/{agent-manager-RGDHYM64.js.map → agent-manager-LSAJSO3X.js.map} +0 -0
package/index.js CHANGED
@@ -201,7 +201,7 @@ function listenWithRetry(server, port, host, wss, maxRetries = 20, delay = 500)
201
201
  });
202
202
  }
203
203
  async function main() {
204
- const { createLocalServer, pullEnv, PullEnvError } = await import("./src-4GK5OK3K.js");
204
+ const { createLocalServer, pullEnv, PullEnvError } = await import("./src-WCSXKTXA.js");
205
205
  if (isPullEnv) {
206
206
  if (!serviceArg) {
207
207
  console.error("Error: --service (-s) is required with --pull-env");
@@ -173,6 +173,34 @@ var RUNEYA_CAPABILITIES = [
173
173
  ],
174
174
  buildInput: (p) => ({ boardId: p.boardId, cardId: p.cardId, comment: p.comment })
175
175
  },
176
+ {
177
+ name: "kanban_get_card_links",
178
+ description: "Read the filiation of a board: which card depends on which. Returns one entry per link (child card \u2194 parent card), plus the title, board, column, assignees and comment count of any linked card living on another board. Use it when a card context says it has a parent or sub-cards and you need their ids to read them.",
179
+ route: "kanban.getCardLinks",
180
+ method: "GET",
181
+ params: [
182
+ { name: "boardId", description: "The kanban board ID whose links to read", required: true }
183
+ ],
184
+ buildInput: (p) => ({ boardId: p.boardId })
185
+ },
186
+ {
187
+ name: "kanban_set_card_parent",
188
+ description: "Link a kanban card to a parent card, or detach it. The parent is the card the other one depends on \u2014 an epic and its tasks, a bug and its follow-ups. A card has at most one parent, and setting a new one replaces it. Omit parentCardId to detach. kanban_get_board reports the current filiation as parentCardId / childCardIds on each card.",
189
+ route: "kanban.setCardParent",
190
+ method: "POST",
191
+ params: [
192
+ { name: "boardId", description: "The kanban board ID of the card being linked", required: true },
193
+ { name: "cardId", description: "The card that depends on the parent (the child)", required: true },
194
+ { name: "parentCardId", description: "The parent card ID. Omit to detach the card from its parent.", required: false },
195
+ { name: "parentBoardId", description: "The parent's board, when it lives on another board of the same organization. Defaults to boardId.", required: false }
196
+ ],
197
+ buildInput: (p) => ({
198
+ boardId: p.boardId,
199
+ cardId: p.cardId,
200
+ ...p.parentCardId ? { parentCardId: p.parentCardId } : {},
201
+ ...p.parentBoardId ? { parentBoardId: p.parentBoardId } : {}
202
+ })
203
+ },
176
204
  {
177
205
  name: "kanban_add_card",
178
206
  description: "Add a new card to a kanban column.",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../../ai-capabilities/src/capabilities.ts","../../ai-capabilities/src/adapters/anthropic.ts","../../ai-capabilities/src/adapters/openai.ts","../../ai-capabilities/src/adapters/prompt.ts","../../ai-capabilities/src/trpc-caller.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { RUNEYA_CAPABILITIES, callTrpc } from '@runeya/packages-ai-capabilities';\n\nconst BASE_URL = process.env['RUNEYA_BASE_URL'] ?? 'http://localhost:4000';\nconst CONVERSATION_ID = process.env['RUNEYA_CONVERSATION_ID'] ?? '';\nconst INTERNAL_TOKEN = process.env['RUNEYA_INTERNAL_TOKEN'] ?? '';\nconst ENV_TOKEN = process.env['RUNEYA_API_TOKEN'] ?? '';\n\nconst server = new McpServer({ name: 'runeya', version: '1.0.0' });\n\n// ─── Register each capability as an MCP tool ─────────────────────────────────\n\nfor (const cap of RUNEYA_CAPABILITIES) {\n const zodShape: Record<string, z.ZodTypeAny> = {};\n\n for (const param of cap.params) {\n const base = z.string().describe(param.description);\n zodShape[param.name] = param.required ? base : base.optional();\n }\n\n // authToken is MCP-specific: CLI runners pass the JWT here\n zodShape['authToken'] = z.string().describe('Bearer token for authentication').optional();\n\n server.tool(cap.name, cap.description, zodShape, async (input) => {\n try {\n const raw = (input as Record<string, string | undefined>).authToken;\n const authToken = (raw && !raw.startsWith('$')) ? raw : (ENV_TOKEN || INTERNAL_TOKEN || undefined);\n if (!authToken) throw new Error('No auth token available');\n\n const params = input as Record<string, string | undefined>;\n const result = await callTrpc(BASE_URL, cap.route, cap.method, cap.buildInput(params), authToken);\n return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }] };\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: `Error: ${(err as Error).message}` }],\n isError: true,\n };\n }\n });\n}\n\n// ─── ask_user tool (scenario mode only) ─────────────────────────────────────\n\nif (CONVERSATION_ID && INTERNAL_TOKEN) {\n server.tool(\n 'ask_user',\n 'Ask the user a question and wait for their reply. Use this when you need clarification or input from the user to proceed.',\n { question: z.string().describe('The question to ask the user') },\n async ({ question }) => {\n try {\n const res = await fetch(`${BASE_URL}/api/trpc/scenario.requestInput`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${INTERNAL_TOKEN}`,\n },\n body: JSON.stringify({ conversationId: CONVERSATION_ID, question }),\n signal: AbortSignal.timeout(300_000), // 5 min\n });\n const json = await res.json() as Record<string, unknown>;\n const result = (json['result'] as Record<string, unknown> | undefined)?.['data'] ?? json;\n const text = typeof result === 'string' ? result : JSON.stringify(result);\n return { content: [{ type: 'text' as const, text }] };\n } catch (err) {\n return { content: [{ type: 'text' as const, text: `Error: ${(err as Error).message}` }], isError: true };\n }\n },\n );\n}\n\n// ─── Start the stdio transport ───────────────────────────────────────────────\n\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n","// ─── Runeya AI Capabilities — Single Source of Truth ─────────────────────────\n//\n// Adding a new capability:\n// 1. Add an entry to RUNEYA_CAPABILITIES below.\n// 2. Done. Anthropic tools, OpenAI tools, runner prompt docs, and MCP routes\n// are all generated automatically from this list.\n\nexport interface CapabilityParam {\n name: string;\n description: string;\n required: boolean;\n}\n\nexport interface RuneyaCapability {\n /** Tool name (snake_case, used as function name by LLMs). */\n name: string;\n /** Human-readable description shown to the LLM. */\n description: string;\n /** tRPC route segment, e.g. \"service.list\" or \"process.start\". */\n route: string;\n /** HTTP method for the tRPC call. */\n method: 'GET' | 'POST';\n /** Input parameters exposed to the LLM. */\n params: CapabilityParam[];\n /** Build the tRPC input object from raw LLM params. */\n buildInput: (params: Record<string, string | undefined>) => Record<string, unknown> | undefined;\n /** If true, safety instructions will warn the LLM to require explicit user intent. */\n destructive?: boolean;\n /**\n * Optional usage hint injected into the system prompt so the LLM knows when to use this tool.\n * Example: '\"wait 5s\" or \"pause for 10 seconds\" → call wait'\n */\n usageHint?: string;\n}\n\nexport const RUNEYA_CAPABILITIES: RuneyaCapability[] = [\n {\n name: 'list_services',\n description: 'List all available services. Returns serviceId and agentId for each — use these exact fields in other calls.',\n route: 'service.list',\n method: 'GET',\n params: [],\n buildInput: () => undefined,\n },\n {\n name: 'get_service_status',\n description: 'Get the current status (running, stopped, etc.) of a service.',\n route: 'process.get',\n method: 'GET',\n params: [\n { name: 'serviceId', description: 'The service ID', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, id: p.serviceId }),\n },\n {\n name: 'get_logs',\n description: 'Get the recent buffered logs for a service.',\n route: 'process.logs',\n method: 'GET',\n params: [\n { name: 'serviceId', description: 'The service ID', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),\n },\n {\n name: 'start_service',\n description: 'Start a service on an agent.',\n route: 'process.start',\n method: 'POST',\n params: [\n { name: 'serviceId', description: 'The service ID to start', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),\n destructive: true,\n },\n {\n name: 'stop_service',\n description: 'Stop a running service on an agent.',\n route: 'process.stop',\n method: 'POST',\n params: [\n { name: 'serviceId', description: 'The service ID to stop', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),\n destructive: true,\n },\n {\n name: 'restart_service',\n description: 'Restart a service on an agent (stop → redeploy → start).',\n route: 'process.restart',\n method: 'POST',\n params: [\n { name: 'serviceId', description: 'The service ID to restart', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),\n destructive: true,\n },\n\n // ─── Utility ─────────────────────────────────────────────────────────────\n\n {\n name: 'wait',\n description: 'Wait for a given number of milliseconds before continuing.',\n route: 'utility.wait',\n method: 'POST',\n params: [\n { name: 'ms', description: 'Number of MILLISECONDS to wait. Convert from seconds: 1s=1000, 10s=10000, 1min=60000. Max 300000.', required: true },\n ],\n buildInput: (p) => ({ ms: Number(p.ms) }),\n usageHint: '\"wait 5s\" → wait(ms=5000), \"pause 10 seconds\" → wait(ms=10000), \"attends 3 secondes\" → wait(ms=3000). Always convert to milliseconds.',\n },\n\n // ─── Kanban ───────────────────────────────────────────────────────────────\n\n {\n name: 'kanban_list_boards',\n description: 'List the kanban boards of the organization. Returns the boardId to use in the other kanban tools, plus column and card counts. Cards themselves are not included — use kanban_get_board for those.',\n route: 'kanban.listBoards',\n method: 'GET',\n params: [\n { name: 'includeArchived', description: 'Set to \"true\" to include archived boards. Default: false.', required: false },\n ],\n buildInput: (p) => ({ includeArchived: p.includeArchived === 'true' }),\n },\n {\n name: 'kanban_get_board',\n description: 'Read one kanban board: its columns, and the cards in each (id, title, markdown body, assignees, comment count, and attachment metadata — use kanban_download_attachment to fetch the bytes of a file). Use the exact column names it returns when moving or adding a card.',\n route: 'kanban.getBoard',\n method: 'GET',\n params: [\n { name: 'boardId', description: 'The kanban board ID, from kanban_list_boards', required: true },\n ],\n buildInput: (p) => ({ boardId: p.boardId }),\n },\n {\n name: 'kanban_get_card_comments',\n description: \"Read the comment thread of one kanban card, newest last: who wrote each comment (ai or user, with the person's name), when, its text, and its attachments. The comments in your task context are a snapshot taken when the task started — call this to see anything written since, whenever someone tells you a comment was added or kanban_get_board reports a higher commentCount than you have.\",\n route: 'kanban.getCardComments',\n method: 'GET',\n params: [\n { name: 'boardId', description: 'The kanban board ID', required: true },\n { name: 'cardId', description: 'The card ID whose comments to read', required: true },\n { name: 'limit', description: 'How many of the most recent comments to return (1-200). Default: 50.', required: false },\n ],\n buildInput: (p) => ({\n boardId: p.boardId,\n cardId: p.cardId,\n ...(p.limit ? { limit: Number(p.limit) } : {}),\n }),\n usageHint: '\"le support a ajouté un commentaire\" / \"regarde les nouveaux commentaires\" → kanban_get_card_comments(boardId, cardId). Never answer from the snapshot in your context when fresh comments are mentioned.',\n },\n {\n name: 'kanban_search_cards',\n description: 'Search kanban cards by free text, matched against their title and body (accent- and case-insensitive). Searches every board of the organization unless boardId narrows it down.',\n route: 'kanban.searchCards',\n method: 'GET',\n params: [\n { name: 'query', description: 'Text to look for in card titles and bodies', required: true },\n { name: 'boardId', description: 'Restrict the search to this board. Omit to search all boards.', required: false },\n { name: 'limit', description: 'Maximum number of cards to return (1-100). Default: 25.', required: false },\n ],\n buildInput: (p) => ({\n query: p.query,\n ...(p.boardId ? { boardId: p.boardId } : {}),\n ...(p.limit ? { limit: Number(p.limit) } : {}),\n }),\n },\n {\n name: 'kanban_download_attachment',\n description: 'Download a kanban card attachment (image, PDF, any file) onto this machine and return its local path, so it can be opened with file-reading tools. Attachment ids come from the card context, from kanban_get_board, or from kanban_get_card_comments — a file attached to a comment downloads exactly like one attached to the card.',\n route: 'kanban.downloadAttachment',\n method: 'POST',\n params: [\n { name: 'attachmentId', description: 'The attachment ID, as listed on the card', required: true },\n ],\n buildInput: (p) => ({ attachmentId: p.attachmentId }),\n },\n {\n name: 'kanban_move_card',\n description: 'Move a kanban card to another column. Use the exact column name.',\n route: 'kanban.moveCard',\n method: 'POST',\n params: [\n { name: 'boardId', description: 'The kanban board ID', required: true },\n { name: 'cardId', description: 'The card ID to move', required: true },\n { name: 'targetColumn', description: 'Exact name of the target column', required: true },\n ],\n buildInput: (p) => ({ boardId: p.boardId, cardId: p.cardId, targetColumn: p.targetColumn }),\n },\n {\n name: 'kanban_add_comment',\n description: 'Add a comment to a kanban card.',\n route: 'kanban.addComment',\n method: 'POST',\n params: [\n { name: 'boardId', description: 'The kanban board ID', required: true },\n { name: 'cardId', description: 'The card ID', required: true },\n { name: 'comment', description: 'The comment text (markdown supported)', required: true },\n ],\n buildInput: (p) => ({ boardId: p.boardId, cardId: p.cardId, comment: p.comment }),\n },\n {\n name: 'kanban_add_card',\n description: 'Add a new card to a kanban column.',\n route: 'kanban.addCard',\n method: 'POST',\n params: [\n { name: 'boardId', description: 'The kanban board ID', required: true },\n { name: 'column', description: 'Exact name of the target column', required: true },\n { name: 'title', description: 'Card title', required: true },\n { name: 'content', description: 'Card content in markdown', required: false },\n ],\n buildInput: (p) => ({ boardId: p.boardId, column: p.column, title: p.title, content: p.content }),\n },\n];\n","import type { RuneyaCapability } from '../capabilities.js';\n\nexport interface AnthropicTool {\n name: string;\n description: string;\n input_schema: {\n type: 'object';\n properties: Record<string, { type: string; description: string }>;\n required: string[];\n [k: string]: unknown;\n };\n}\n\nexport function buildAnthropicTools(capabilities: RuneyaCapability[]): AnthropicTool[] {\n return capabilities.map(cap => ({\n name: cap.name,\n description: cap.description,\n input_schema: {\n type: 'object' as const,\n properties: Object.fromEntries(\n cap.params.map(p => [p.name, { type: 'string', description: p.description }]),\n ),\n required: cap.params.filter(p => p.required).map(p => p.name),\n },\n }));\n}\n","import type { RuneyaCapability } from '../capabilities.js';\n\nexport interface OpenAITool {\n type: 'function';\n function: {\n name: string;\n description: string;\n parameters: {\n type: 'object';\n properties: Record<string, { type: string; description: string }>;\n required: string[];\n };\n };\n}\n\nexport function buildOpenAITools(capabilities: RuneyaCapability[]): OpenAITool[] {\n return capabilities.map(cap => ({\n type: 'function' as const,\n function: {\n name: cap.name,\n description: cap.description,\n parameters: {\n type: 'object' as const,\n properties: Object.fromEntries(\n cap.params.map(p => [p.name, { type: 'string', description: p.description }]),\n ),\n required: cap.params.filter(p => p.required).map(p => p.name),\n },\n },\n }));\n}\n","import type { RuneyaCapability } from '../capabilities.js';\nexport type { RuneyaCapability };\n\n/**\n * Build the tool safety instruction block injected into cloud provider system prompts.\n * Generated from capabilities so it stays in sync automatically.\n */\nexport function buildToolSafetyInstruction(capabilities: RuneyaCapability[]): string {\n const destructive = capabilities.filter(c => c.destructive).map(c => c.name);\n const withHints = capabilities.filter(c => c.usageHint);\n\n const lines = ['## Tool use safety rules'];\n\n if (destructive.length > 0) {\n lines.push(`CRITICAL: Never call ${destructive.join(', ')} unless the user has EXPLICITLY and UNAMBIGUOUSLY requested it.`);\n lines.push(`- Only call destructive tools (${destructive.join(', ')}) when the user explicitly uses action words for a specific service.`);\n }\n\n if (withHints.length > 0) {\n lines.push('');\n lines.push('## Tool usage hints');\n for (const cap of withHints) {\n lines.push(`- ${cap.usageHint}`);\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Build a markdown documentation block injected into runner system prompts.\n * Runners (ClaudeCodeRunner, CodexRunner) use this to know how to call the Runeya API.\n *\n * The generated doc is the single source of truth for all runner-facing API docs —\n * no need to maintain a separate runeya-api-docs.ts.\n */\nexport function buildPromptDocs(baseUrl: string, token: string, capabilities: RuneyaCapability[]): string {\n if (!token) return '';\n\n const lines: string[] = [\n '## Runeya API',\n '',\n `Tu peux interagir avec Runeya via l'API HTTP tRPC ci-dessous.`,\n `Base URL : ${baseUrl}/api/trpc`,\n 'Auth header : Authorization: Bearer $RUNEYA_API_TOKEN',\n '',\n ];\n\n const gets = capabilities.filter(c => c.method === 'GET');\n const posts = capabilities.filter(c => c.method === 'POST');\n\n if (gets.length > 0) {\n lines.push('### GET routes (paramètres en query string ?input=<JSON encodé>)', '');\n for (const cap of gets) {\n const example = cap.params.length > 0\n ? `?input=${JSON.stringify(Object.fromEntries(cap.params.map(p => [p.name === 'serviceId' ? 'id' : p.name, '...'])))}`\n : '';\n lines.push(`- \\`${cap.route}${example}\\` — ${cap.description}`);\n }\n lines.push('');\n }\n\n if (posts.length > 0) {\n lines.push('### POST routes (body JSON)', '');\n for (const cap of posts) {\n const bodyExample = cap.params.length > 0\n ? JSON.stringify(Object.fromEntries(cap.params.map(p => [p.name === 'serviceId' ? 'processId' : p.name, '...'])))\n : '{}';\n lines.push(`- \\`${cap.route}\\` — \\`${bodyExample}\\``);\n }\n lines.push('');\n }\n\n const hints = capabilities.filter(c => c.usageHint);\n if (hints.length > 0) {\n lines.push('### Usage hints', '');\n for (const cap of hints) {\n lines.push(`- ${cap.usageHint}`);\n }\n lines.push('');\n }\n\n lines.push(\n '### Exemple curl',\n '',\n '```bash',\n `curl -H \"Authorization: Bearer $RUNEYA_API_TOKEN\" \\\\`,\n ` \"${baseUrl}/api/trpc/service.list\"`,\n '',\n `curl -X POST -H \"Authorization: Bearer $RUNEYA_API_TOKEN\" \\\\`,\n ' -H \"Content-Type: application/json\" \\\\',\n ` -d '{\"agentId\":\"local\",\"processId\":\"my-service\"}' \\\\`,\n ` \"${baseUrl}/api/trpc/process.start\"`,\n '```',\n '',\n 'La réponse est de la forme `{\"result\":{\"data\":<résultat>}}`.',\n );\n\n return lines.join('\\n');\n}\n","/**\n * Shared tRPC HTTP caller used by:\n * - Server-side cloud tool executor (proxies cloud LLM tool calls to local tRPC)\n * - MCP server (calls tRPC on behalf of CLI runners)\n */\nexport async function callTrpc(\n baseUrl: string,\n route: string,\n method: 'GET' | 'POST',\n input: Record<string, unknown> | undefined,\n authToken: string,\n): Promise<unknown> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${authToken}`,\n };\n\n const url = method === 'GET' && input\n ? `${baseUrl}/api/trpc/${route}?input=${encodeURIComponent(JSON.stringify(input))}`\n : `${baseUrl}/api/trpc/${route}`;\n\n const res = await fetch(url, {\n method,\n headers,\n ...(method === 'POST' ? { body: JSON.stringify(input ?? {}) } : {}),\n signal: AbortSignal.timeout(15_000),\n });\n\n const json = await res.json() as Record<string, unknown>;\n if (json['error']) throw new Error(JSON.stringify(json['error']));\n const result = json['result'] as Record<string, unknown> | undefined;\n return result?.['data'] ?? result ?? json;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../../ai-capabilities/src/capabilities.ts","../../ai-capabilities/src/adapters/anthropic.ts","../../ai-capabilities/src/adapters/openai.ts","../../ai-capabilities/src/adapters/prompt.ts","../../ai-capabilities/src/trpc-caller.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { RUNEYA_CAPABILITIES, callTrpc } from '@runeya/packages-ai-capabilities';\n\nconst BASE_URL = process.env['RUNEYA_BASE_URL'] ?? 'http://localhost:4000';\nconst CONVERSATION_ID = process.env['RUNEYA_CONVERSATION_ID'] ?? '';\nconst INTERNAL_TOKEN = process.env['RUNEYA_INTERNAL_TOKEN'] ?? '';\nconst ENV_TOKEN = process.env['RUNEYA_API_TOKEN'] ?? '';\n\nconst server = new McpServer({ name: 'runeya', version: '1.0.0' });\n\n// ─── Register each capability as an MCP tool ─────────────────────────────────\n\nfor (const cap of RUNEYA_CAPABILITIES) {\n const zodShape: Record<string, z.ZodTypeAny> = {};\n\n for (const param of cap.params) {\n const base = z.string().describe(param.description);\n zodShape[param.name] = param.required ? base : base.optional();\n }\n\n // authToken is MCP-specific: CLI runners pass the JWT here\n zodShape['authToken'] = z.string().describe('Bearer token for authentication').optional();\n\n server.tool(cap.name, cap.description, zodShape, async (input) => {\n try {\n const raw = (input as Record<string, string | undefined>).authToken;\n const authToken = (raw && !raw.startsWith('$')) ? raw : (ENV_TOKEN || INTERNAL_TOKEN || undefined);\n if (!authToken) throw new Error('No auth token available');\n\n const params = input as Record<string, string | undefined>;\n const result = await callTrpc(BASE_URL, cap.route, cap.method, cap.buildInput(params), authToken);\n return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }] };\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: `Error: ${(err as Error).message}` }],\n isError: true,\n };\n }\n });\n}\n\n// ─── ask_user tool (scenario mode only) ─────────────────────────────────────\n\nif (CONVERSATION_ID && INTERNAL_TOKEN) {\n server.tool(\n 'ask_user',\n 'Ask the user a question and wait for their reply. Use this when you need clarification or input from the user to proceed.',\n { question: z.string().describe('The question to ask the user') },\n async ({ question }) => {\n try {\n const res = await fetch(`${BASE_URL}/api/trpc/scenario.requestInput`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${INTERNAL_TOKEN}`,\n },\n body: JSON.stringify({ conversationId: CONVERSATION_ID, question }),\n signal: AbortSignal.timeout(300_000), // 5 min\n });\n const json = await res.json() as Record<string, unknown>;\n const result = (json['result'] as Record<string, unknown> | undefined)?.['data'] ?? json;\n const text = typeof result === 'string' ? result : JSON.stringify(result);\n return { content: [{ type: 'text' as const, text }] };\n } catch (err) {\n return { content: [{ type: 'text' as const, text: `Error: ${(err as Error).message}` }], isError: true };\n }\n },\n );\n}\n\n// ─── Start the stdio transport ───────────────────────────────────────────────\n\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n","// ─── Runeya AI Capabilities — Single Source of Truth ─────────────────────────\n//\n// Adding a new capability:\n// 1. Add an entry to RUNEYA_CAPABILITIES below.\n// 2. Done. Anthropic tools, OpenAI tools, runner prompt docs, and MCP routes\n// are all generated automatically from this list.\n\nexport interface CapabilityParam {\n name: string;\n description: string;\n required: boolean;\n}\n\nexport interface RuneyaCapability {\n /** Tool name (snake_case, used as function name by LLMs). */\n name: string;\n /** Human-readable description shown to the LLM. */\n description: string;\n /** tRPC route segment, e.g. \"service.list\" or \"process.start\". */\n route: string;\n /** HTTP method for the tRPC call. */\n method: 'GET' | 'POST';\n /** Input parameters exposed to the LLM. */\n params: CapabilityParam[];\n /** Build the tRPC input object from raw LLM params. */\n buildInput: (params: Record<string, string | undefined>) => Record<string, unknown> | undefined;\n /** If true, safety instructions will warn the LLM to require explicit user intent. */\n destructive?: boolean;\n /**\n * Optional usage hint injected into the system prompt so the LLM knows when to use this tool.\n * Example: '\"wait 5s\" or \"pause for 10 seconds\" → call wait'\n */\n usageHint?: string;\n}\n\nexport const RUNEYA_CAPABILITIES: RuneyaCapability[] = [\n {\n name: 'list_services',\n description: 'List all available services. Returns serviceId and agentId for each — use these exact fields in other calls.',\n route: 'service.list',\n method: 'GET',\n params: [],\n buildInput: () => undefined,\n },\n {\n name: 'get_service_status',\n description: 'Get the current status (running, stopped, etc.) of a service.',\n route: 'process.get',\n method: 'GET',\n params: [\n { name: 'serviceId', description: 'The service ID', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, id: p.serviceId }),\n },\n {\n name: 'get_logs',\n description: 'Get the recent buffered logs for a service.',\n route: 'process.logs',\n method: 'GET',\n params: [\n { name: 'serviceId', description: 'The service ID', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),\n },\n {\n name: 'start_service',\n description: 'Start a service on an agent.',\n route: 'process.start',\n method: 'POST',\n params: [\n { name: 'serviceId', description: 'The service ID to start', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),\n destructive: true,\n },\n {\n name: 'stop_service',\n description: 'Stop a running service on an agent.',\n route: 'process.stop',\n method: 'POST',\n params: [\n { name: 'serviceId', description: 'The service ID to stop', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),\n destructive: true,\n },\n {\n name: 'restart_service',\n description: 'Restart a service on an agent (stop → redeploy → start).',\n route: 'process.restart',\n method: 'POST',\n params: [\n { name: 'serviceId', description: 'The service ID to restart', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),\n destructive: true,\n },\n\n // ─── Utility ─────────────────────────────────────────────────────────────\n\n {\n name: 'wait',\n description: 'Wait for a given number of milliseconds before continuing.',\n route: 'utility.wait',\n method: 'POST',\n params: [\n { name: 'ms', description: 'Number of MILLISECONDS to wait. Convert from seconds: 1s=1000, 10s=10000, 1min=60000. Max 300000.', required: true },\n ],\n buildInput: (p) => ({ ms: Number(p.ms) }),\n usageHint: '\"wait 5s\" → wait(ms=5000), \"pause 10 seconds\" → wait(ms=10000), \"attends 3 secondes\" → wait(ms=3000). Always convert to milliseconds.',\n },\n\n // ─── Kanban ───────────────────────────────────────────────────────────────\n\n {\n name: 'kanban_list_boards',\n description: 'List the kanban boards of the organization. Returns the boardId to use in the other kanban tools, plus column and card counts. Cards themselves are not included — use kanban_get_board for those.',\n route: 'kanban.listBoards',\n method: 'GET',\n params: [\n { name: 'includeArchived', description: 'Set to \"true\" to include archived boards. Default: false.', required: false },\n ],\n buildInput: (p) => ({ includeArchived: p.includeArchived === 'true' }),\n },\n {\n name: 'kanban_get_board',\n description: 'Read one kanban board: its columns, and the cards in each (id, title, markdown body, assignees, comment count, and attachment metadata — use kanban_download_attachment to fetch the bytes of a file). Use the exact column names it returns when moving or adding a card.',\n route: 'kanban.getBoard',\n method: 'GET',\n params: [\n { name: 'boardId', description: 'The kanban board ID, from kanban_list_boards', required: true },\n ],\n buildInput: (p) => ({ boardId: p.boardId }),\n },\n {\n name: 'kanban_get_card_comments',\n description: \"Read the comment thread of one kanban card, newest last: who wrote each comment (ai or user, with the person's name), when, its text, and its attachments. The comments in your task context are a snapshot taken when the task started — call this to see anything written since, whenever someone tells you a comment was added or kanban_get_board reports a higher commentCount than you have.\",\n route: 'kanban.getCardComments',\n method: 'GET',\n params: [\n { name: 'boardId', description: 'The kanban board ID', required: true },\n { name: 'cardId', description: 'The card ID whose comments to read', required: true },\n { name: 'limit', description: 'How many of the most recent comments to return (1-200). Default: 50.', required: false },\n ],\n buildInput: (p) => ({\n boardId: p.boardId,\n cardId: p.cardId,\n ...(p.limit ? { limit: Number(p.limit) } : {}),\n }),\n usageHint: '\"le support a ajouté un commentaire\" / \"regarde les nouveaux commentaires\" → kanban_get_card_comments(boardId, cardId). Never answer from the snapshot in your context when fresh comments are mentioned.',\n },\n {\n name: 'kanban_search_cards',\n description: 'Search kanban cards by free text, matched against their title and body (accent- and case-insensitive). Searches every board of the organization unless boardId narrows it down.',\n route: 'kanban.searchCards',\n method: 'GET',\n params: [\n { name: 'query', description: 'Text to look for in card titles and bodies', required: true },\n { name: 'boardId', description: 'Restrict the search to this board. Omit to search all boards.', required: false },\n { name: 'limit', description: 'Maximum number of cards to return (1-100). Default: 25.', required: false },\n ],\n buildInput: (p) => ({\n query: p.query,\n ...(p.boardId ? { boardId: p.boardId } : {}),\n ...(p.limit ? { limit: Number(p.limit) } : {}),\n }),\n },\n {\n name: 'kanban_download_attachment',\n description: 'Download a kanban card attachment (image, PDF, any file) onto this machine and return its local path, so it can be opened with file-reading tools. Attachment ids come from the card context, from kanban_get_board, or from kanban_get_card_comments — a file attached to a comment downloads exactly like one attached to the card.',\n route: 'kanban.downloadAttachment',\n method: 'POST',\n params: [\n { name: 'attachmentId', description: 'The attachment ID, as listed on the card', required: true },\n ],\n buildInput: (p) => ({ attachmentId: p.attachmentId }),\n },\n {\n name: 'kanban_move_card',\n description: 'Move a kanban card to another column. Use the exact column name.',\n route: 'kanban.moveCard',\n method: 'POST',\n params: [\n { name: 'boardId', description: 'The kanban board ID', required: true },\n { name: 'cardId', description: 'The card ID to move', required: true },\n { name: 'targetColumn', description: 'Exact name of the target column', required: true },\n ],\n buildInput: (p) => ({ boardId: p.boardId, cardId: p.cardId, targetColumn: p.targetColumn }),\n },\n {\n name: 'kanban_add_comment',\n description: 'Add a comment to a kanban card.',\n route: 'kanban.addComment',\n method: 'POST',\n params: [\n { name: 'boardId', description: 'The kanban board ID', required: true },\n { name: 'cardId', description: 'The card ID', required: true },\n { name: 'comment', description: 'The comment text (markdown supported)', required: true },\n ],\n buildInput: (p) => ({ boardId: p.boardId, cardId: p.cardId, comment: p.comment }),\n },\n {\n name: 'kanban_get_card_links',\n description: 'Read the filiation of a board: which card depends on which. Returns one entry per link (child card ↔ parent card), plus the title, board, column, assignees and comment count of any linked card living on another board. Use it when a card context says it has a parent or sub-cards and you need their ids to read them.',\n route: 'kanban.getCardLinks',\n method: 'GET',\n params: [\n { name: 'boardId', description: 'The kanban board ID whose links to read', required: true },\n ],\n buildInput: (p) => ({ boardId: p.boardId }),\n },\n {\n name: 'kanban_set_card_parent',\n description: 'Link a kanban card to a parent card, or detach it. The parent is the card the other one depends on — an epic and its tasks, a bug and its follow-ups. A card has at most one parent, and setting a new one replaces it. Omit parentCardId to detach. kanban_get_board reports the current filiation as parentCardId / childCardIds on each card.',\n route: 'kanban.setCardParent',\n method: 'POST',\n params: [\n { name: 'boardId', description: 'The kanban board ID of the card being linked', required: true },\n { name: 'cardId', description: 'The card that depends on the parent (the child)', required: true },\n { name: 'parentCardId', description: 'The parent card ID. Omit to detach the card from its parent.', required: false },\n { name: 'parentBoardId', description: \"The parent's board, when it lives on another board of the same organization. Defaults to boardId.\", required: false },\n ],\n buildInput: (p) => ({\n boardId: p.boardId,\n cardId: p.cardId,\n ...(p.parentCardId ? { parentCardId: p.parentCardId } : {}),\n ...(p.parentBoardId ? { parentBoardId: p.parentBoardId } : {}),\n }),\n },\n {\n name: 'kanban_add_card',\n description: 'Add a new card to a kanban column.',\n route: 'kanban.addCard',\n method: 'POST',\n params: [\n { name: 'boardId', description: 'The kanban board ID', required: true },\n { name: 'column', description: 'Exact name of the target column', required: true },\n { name: 'title', description: 'Card title', required: true },\n { name: 'content', description: 'Card content in markdown', required: false },\n ],\n buildInput: (p) => ({ boardId: p.boardId, column: p.column, title: p.title, content: p.content }),\n },\n];\n","import type { RuneyaCapability } from '../capabilities.js';\n\nexport interface AnthropicTool {\n name: string;\n description: string;\n input_schema: {\n type: 'object';\n properties: Record<string, { type: string; description: string }>;\n required: string[];\n [k: string]: unknown;\n };\n}\n\nexport function buildAnthropicTools(capabilities: RuneyaCapability[]): AnthropicTool[] {\n return capabilities.map(cap => ({\n name: cap.name,\n description: cap.description,\n input_schema: {\n type: 'object' as const,\n properties: Object.fromEntries(\n cap.params.map(p => [p.name, { type: 'string', description: p.description }]),\n ),\n required: cap.params.filter(p => p.required).map(p => p.name),\n },\n }));\n}\n","import type { RuneyaCapability } from '../capabilities.js';\n\nexport interface OpenAITool {\n type: 'function';\n function: {\n name: string;\n description: string;\n parameters: {\n type: 'object';\n properties: Record<string, { type: string; description: string }>;\n required: string[];\n };\n };\n}\n\nexport function buildOpenAITools(capabilities: RuneyaCapability[]): OpenAITool[] {\n return capabilities.map(cap => ({\n type: 'function' as const,\n function: {\n name: cap.name,\n description: cap.description,\n parameters: {\n type: 'object' as const,\n properties: Object.fromEntries(\n cap.params.map(p => [p.name, { type: 'string', description: p.description }]),\n ),\n required: cap.params.filter(p => p.required).map(p => p.name),\n },\n },\n }));\n}\n","import type { RuneyaCapability } from '../capabilities.js';\nexport type { RuneyaCapability };\n\n/**\n * Build the tool safety instruction block injected into cloud provider system prompts.\n * Generated from capabilities so it stays in sync automatically.\n */\nexport function buildToolSafetyInstruction(capabilities: RuneyaCapability[]): string {\n const destructive = capabilities.filter(c => c.destructive).map(c => c.name);\n const withHints = capabilities.filter(c => c.usageHint);\n\n const lines = ['## Tool use safety rules'];\n\n if (destructive.length > 0) {\n lines.push(`CRITICAL: Never call ${destructive.join(', ')} unless the user has EXPLICITLY and UNAMBIGUOUSLY requested it.`);\n lines.push(`- Only call destructive tools (${destructive.join(', ')}) when the user explicitly uses action words for a specific service.`);\n }\n\n if (withHints.length > 0) {\n lines.push('');\n lines.push('## Tool usage hints');\n for (const cap of withHints) {\n lines.push(`- ${cap.usageHint}`);\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Build a markdown documentation block injected into runner system prompts.\n * Runners (ClaudeCodeRunner, CodexRunner) use this to know how to call the Runeya API.\n *\n * The generated doc is the single source of truth for all runner-facing API docs —\n * no need to maintain a separate runeya-api-docs.ts.\n */\nexport function buildPromptDocs(baseUrl: string, token: string, capabilities: RuneyaCapability[]): string {\n if (!token) return '';\n\n const lines: string[] = [\n '## Runeya API',\n '',\n `Tu peux interagir avec Runeya via l'API HTTP tRPC ci-dessous.`,\n `Base URL : ${baseUrl}/api/trpc`,\n 'Auth header : Authorization: Bearer $RUNEYA_API_TOKEN',\n '',\n ];\n\n const gets = capabilities.filter(c => c.method === 'GET');\n const posts = capabilities.filter(c => c.method === 'POST');\n\n if (gets.length > 0) {\n lines.push('### GET routes (paramètres en query string ?input=<JSON encodé>)', '');\n for (const cap of gets) {\n const example = cap.params.length > 0\n ? `?input=${JSON.stringify(Object.fromEntries(cap.params.map(p => [p.name === 'serviceId' ? 'id' : p.name, '...'])))}`\n : '';\n lines.push(`- \\`${cap.route}${example}\\` — ${cap.description}`);\n }\n lines.push('');\n }\n\n if (posts.length > 0) {\n lines.push('### POST routes (body JSON)', '');\n for (const cap of posts) {\n const bodyExample = cap.params.length > 0\n ? JSON.stringify(Object.fromEntries(cap.params.map(p => [p.name === 'serviceId' ? 'processId' : p.name, '...'])))\n : '{}';\n lines.push(`- \\`${cap.route}\\` — \\`${bodyExample}\\``);\n }\n lines.push('');\n }\n\n const hints = capabilities.filter(c => c.usageHint);\n if (hints.length > 0) {\n lines.push('### Usage hints', '');\n for (const cap of hints) {\n lines.push(`- ${cap.usageHint}`);\n }\n lines.push('');\n }\n\n lines.push(\n '### Exemple curl',\n '',\n '```bash',\n `curl -H \"Authorization: Bearer $RUNEYA_API_TOKEN\" \\\\`,\n ` \"${baseUrl}/api/trpc/service.list\"`,\n '',\n `curl -X POST -H \"Authorization: Bearer $RUNEYA_API_TOKEN\" \\\\`,\n ' -H \"Content-Type: application/json\" \\\\',\n ` -d '{\"agentId\":\"local\",\"processId\":\"my-service\"}' \\\\`,\n ` \"${baseUrl}/api/trpc/process.start\"`,\n '```',\n '',\n 'La réponse est de la forme `{\"result\":{\"data\":<résultat>}}`.',\n );\n\n return lines.join('\\n');\n}\n","/**\n * Shared tRPC HTTP caller used by:\n * - Server-side cloud tool executor (proxies cloud LLM tool calls to local tRPC)\n * - MCP server (calls tRPC on behalf of CLI runners)\n */\nexport async function callTrpc(\n baseUrl: string,\n route: string,\n method: 'GET' | 'POST',\n input: Record<string, unknown> | undefined,\n authToken: string,\n): Promise<unknown> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${authToken}`,\n };\n\n const url = method === 'GET' && input\n ? `${baseUrl}/api/trpc/${route}?input=${encodeURIComponent(JSON.stringify(input))}`\n : `${baseUrl}/api/trpc/${route}`;\n\n const res = await fetch(url, {\n method,\n headers,\n ...(method === 'POST' ? { body: JSON.stringify(input ?? {}) } : {}),\n signal: AbortSignal.timeout(15_000),\n });\n\n const json = await res.json() as Record<string, unknown>;\n if (json['error']) throw new Error(JSON.stringify(json['error']));\n const result = json['result'] as Record<string, unknown> | undefined;\n return result?.['data'] ?? result ?? json;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runeya/runeya",
3
- "version": "2.0.53",
3
+ "version": "2.0.55",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "runeya": "./index.js"
@@ -90,7 +90,7 @@ import {
90
90
  vaultFor,
91
91
  vaultIdOfRoot,
92
92
  writeEntity
93
- } from "./chunk-EL75GG7O.js";
93
+ } from "./chunk-Q2WY6PYX.js";
94
94
 
95
95
  // ../server/src/create-server.ts
96
96
  import express from "express";
@@ -4290,6 +4290,34 @@ var RUNEYA_CAPABILITIES = [
4290
4290
  ],
4291
4291
  buildInput: (p) => ({ boardId: p.boardId, cardId: p.cardId, comment: p.comment })
4292
4292
  },
4293
+ {
4294
+ name: "kanban_get_card_links",
4295
+ description: "Read the filiation of a board: which card depends on which. Returns one entry per link (child card \u2194 parent card), plus the title, board, column, assignees and comment count of any linked card living on another board. Use it when a card context says it has a parent or sub-cards and you need their ids to read them.",
4296
+ route: "kanban.getCardLinks",
4297
+ method: "GET",
4298
+ params: [
4299
+ { name: "boardId", description: "The kanban board ID whose links to read", required: true }
4300
+ ],
4301
+ buildInput: (p) => ({ boardId: p.boardId })
4302
+ },
4303
+ {
4304
+ name: "kanban_set_card_parent",
4305
+ description: "Link a kanban card to a parent card, or detach it. The parent is the card the other one depends on \u2014 an epic and its tasks, a bug and its follow-ups. A card has at most one parent, and setting a new one replaces it. Omit parentCardId to detach. kanban_get_board reports the current filiation as parentCardId / childCardIds on each card.",
4306
+ route: "kanban.setCardParent",
4307
+ method: "POST",
4308
+ params: [
4309
+ { name: "boardId", description: "The kanban board ID of the card being linked", required: true },
4310
+ { name: "cardId", description: "The card that depends on the parent (the child)", required: true },
4311
+ { name: "parentCardId", description: "The parent card ID. Omit to detach the card from its parent.", required: false },
4312
+ { name: "parentBoardId", description: "The parent's board, when it lives on another board of the same organization. Defaults to boardId.", required: false }
4313
+ ],
4314
+ buildInput: (p) => ({
4315
+ boardId: p.boardId,
4316
+ cardId: p.cardId,
4317
+ ...p.parentCardId ? { parentCardId: p.parentCardId } : {},
4318
+ ...p.parentBoardId ? { parentBoardId: p.parentBoardId } : {}
4319
+ })
4320
+ },
4293
4321
  {
4294
4322
  name: "kanban_add_card",
4295
4323
  description: "Add a new card to a kanban column.",
@@ -6764,6 +6792,37 @@ var KanbanStore = class {
6764
6792
  });
6765
6793
  return res.ok;
6766
6794
  }
6795
+ /**
6796
+ * La filiation des cartes d'un tableau, dans les deux sens.
6797
+ *
6798
+ * Elle vit hors du tableau — une sauvegarde de tableau ne la transporte pas —
6799
+ * donc elle se demande à part. `cards` nomme les cartes liées qui vivent sur
6800
+ * un autre tableau ; celles d'ici sont déjà dans le tableau.
6801
+ */
6802
+ async cardLinks(boardId) {
6803
+ const res = await callCloud(
6804
+ `/kanban/card-link/list?boardId=${encodeURIComponent(boardId)}`
6805
+ );
6806
+ return { links: res.data?.links ?? [], cards: res.data?.cards ?? [] };
6807
+ }
6808
+ /**
6809
+ * Rattacher une carte à un parent, ou l'en détacher avec `parent: null`.
6810
+ *
6811
+ * Le parent peut vivre sur un autre tableau de la même organisation. Le cloud
6812
+ * refuse un parent qui descendrait déjà de la carte : l'arbre reste un arbre.
6813
+ */
6814
+ async setCardParent(boardId, cardId, parent) {
6815
+ const res = await callCloud("/kanban/card-link/set", {
6816
+ method: "POST",
6817
+ body: {
6818
+ boardId,
6819
+ cardId,
6820
+ parentBoardId: parent?.boardId ?? null,
6821
+ parentCardId: parent?.cardId ?? null
6822
+ }
6823
+ });
6824
+ return res.ok;
6825
+ }
6767
6826
  async create(input) {
6768
6827
  const organizationId = await resolveOrganizationId();
6769
6828
  if (!organizationId) return null;
@@ -6875,7 +6934,7 @@ function formatSize(bytes) {
6875
6934
  if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} Ko`;
6876
6935
  return `${(bytes / (1024 * 1024)).toFixed(1).replace(".", ",")} Mo`;
6877
6936
  }
6878
- function generateKanbanSystemPrompt(board, cardId, history) {
6937
+ function generateKanbanSystemPrompt(board, cardId, history, links) {
6879
6938
  let currentColTitle = "";
6880
6939
  let card = null;
6881
6940
  for (const col of board.columns) {
@@ -6950,6 +7009,21 @@ function generateKanbanSystemPrompt(board, cardId, history) {
6950
7009
  lines.push("");
6951
7010
  }
6952
7011
  }
7012
+ if (card && links?.length) {
7013
+ const parent = links.find((l) => l.childCardId === card.id);
7014
+ const children = links.filter((l) => l.parentCardId === card.id);
7015
+ if (parent || children.length) {
7016
+ lines.push("### Cartes li\xE9es");
7017
+ lines.push("");
7018
+ if (parent) lines.push("- Cette carte **d\xE9pend d'une carte parente**.");
7019
+ if (children.length) {
7020
+ lines.push(`- **${children.length} sous-carte${children.length !== 1 ? "s" : ""}** d\xE9pend${children.length !== 1 ? "ent" : ""} de cette carte.`);
7021
+ }
7022
+ lines.push("");
7023
+ lines.push("> Leur contenu n'est **pas** dans ce prompt. Appelle `kanban_get_card_links(boardId)` pour obtenir les identifiants des cartes li\xE9es, puis lis-les avec `kanban_get_board` ou `kanban_get_card_comments`.");
7024
+ lines.push("");
7025
+ }
7026
+ }
6953
7027
  lines.push("### Outils Kanban disponibles");
6954
7028
  lines.push("");
6955
7029
  lines.push(`- **boardId** (\xE0 passer dans tous les outils) : \`${board.id}\``);
@@ -6960,6 +7034,8 @@ function generateKanbanSystemPrompt(board, cardId, history) {
6960
7034
  lines.push("- `kanban_add_comment(boardId, cardId, comment)` \u2014 Ajouter un commentaire sur la carte");
6961
7035
  lines.push("- `kanban_get_card_comments(boardId, cardId)` \u2014 **Relire** le fil de commentaires \xE0 jour");
6962
7036
  lines.push("- `kanban_download_attachment(attachmentId)` \u2014 T\xE9l\xE9charger une pi\xE8ce jointe et obtenir son chemin local");
7037
+ lines.push("- `kanban_get_card_links(boardId)` \u2014 Lire la filiation des cartes du tableau (parent \u2194 sous-cartes)");
7038
+ lines.push("- `kanban_set_card_parent(boardId, cardId, parentCardId?)` \u2014 Rattacher une carte \xE0 une carte parente, ou l'en d\xE9tacher");
6963
7039
  lines.push("");
6964
7040
  lines.push("### OBLIGATOIRE \u2014 D\xE9cision Kanban");
6965
7041
  lines.push("");
@@ -6978,6 +7054,13 @@ function generateKanbanSystemPrompt(board, cardId, history) {
6978
7054
  lines.push("");
6979
7055
  return lines.join("\n");
6980
7056
  }
7057
+ async function buildKanbanCardPrompt(board, cardId) {
7058
+ const [history, links] = await Promise.all([
7059
+ kanbanStore.cardHistory(board.id, cardId),
7060
+ kanbanStore.cardLinks(board.id).then((r) => r.links)
7061
+ ]);
7062
+ return generateKanbanSystemPrompt(board, cardId, history, links);
7063
+ }
6981
7064
  function generateKanbanPopulatePrompt(board) {
6982
7065
  const lines = [];
6983
7066
  lines.push("## Kanban Board \u2014 Mode Populate");
@@ -7194,7 +7277,7 @@ function tailTranscript(opts) {
7194
7277
 
7195
7278
  // ../server/src/services/ai-runners/claude-pty-runner.ts
7196
7279
  async function getAgentManager() {
7197
- const { agentManager: agentManager2 } = await import("./agent-manager-RGDHYM64.js");
7280
+ const { agentManager: agentManager2 } = await import("./agent-manager-LSAJSO3X.js");
7198
7281
  return agentManager2;
7199
7282
  }
7200
7283
  function buildPtyArgs(params, sessionId, opts) {
@@ -7847,7 +7930,7 @@ async function shutdownCodexAppServer() {
7847
7930
  }
7848
7931
  }
7849
7932
  async function getAgentManager2() {
7850
- const { agentManager: agentManager2 } = await import("./agent-manager-RGDHYM64.js");
7933
+ const { agentManager: agentManager2 } = await import("./agent-manager-LSAJSO3X.js");
7851
7934
  return agentManager2;
7852
7935
  }
7853
7936
  function parseRuneyaCurlCommand(command) {
@@ -8531,13 +8614,7 @@ async function buildCliSystemContext(conv, jwt) {
8531
8614
  if (conv?.kanbanBoardId) {
8532
8615
  const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);
8533
8616
  if (kanbanBoard) {
8534
- systemContext += "\n\n" + (conv.kanbanCardId ? generateKanbanSystemPrompt(
8535
- kanbanBoard,
8536
- conv.kanbanCardId,
8537
- // Le journal ne vient plus avec le tableau : le contexte de l'agent
8538
- // le demande pour la seule carte qui le concerne.
8539
- await kanbanStore.cardHistory(kanbanBoard.id, conv.kanbanCardId)
8540
- ) : generateKanbanPopulatePrompt(kanbanBoard));
8617
+ systemContext += "\n\n" + (conv.kanbanCardId ? await buildKanbanCardPrompt(kanbanBoard, conv.kanbanCardId) : generateKanbanPopulatePrompt(kanbanBoard));
8541
8618
  }
8542
8619
  }
8543
8620
  return systemContext;
@@ -8998,13 +9075,7 @@ ${input.prompt}` : input.prompt;
8998
9075
  if (conv.kanbanBoardId) {
8999
9076
  const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);
9000
9077
  if (kanbanBoard) {
9001
- systemContext += "\n\n" + (conv.kanbanCardId ? generateKanbanSystemPrompt(
9002
- kanbanBoard,
9003
- conv.kanbanCardId,
9004
- // Le journal ne vient plus avec le tableau : le contexte de l'agent
9005
- // le demande pour la seule carte qui le concerne.
9006
- await kanbanStore.cardHistory(kanbanBoard.id, conv.kanbanCardId)
9007
- ) : generateKanbanPopulatePrompt(kanbanBoard));
9078
+ systemContext += "\n\n" + (conv.kanbanCardId ? await buildKanbanCardPrompt(kanbanBoard, conv.kanbanCardId) : generateKanbanPopulatePrompt(kanbanBoard));
9008
9079
  }
9009
9080
  }
9010
9081
  const mcpServerPath = fileURLToPath(new URL("../mcp-server/index.js", import.meta.url));
@@ -9120,13 +9191,7 @@ ${input.prompt}` : input.prompt;
9120
9191
  if (conv.kanbanBoardId) {
9121
9192
  const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);
9122
9193
  if (kanbanBoard) {
9123
- systemContext += "\n\n" + (conv.kanbanCardId ? generateKanbanSystemPrompt(
9124
- kanbanBoard,
9125
- conv.kanbanCardId,
9126
- // Le journal ne vient plus avec le tableau : le contexte de l'agent
9127
- // le demande pour la seule carte qui le concerne.
9128
- await kanbanStore.cardHistory(kanbanBoard.id, conv.kanbanCardId)
9129
- ) : generateKanbanPopulatePrompt(kanbanBoard));
9194
+ systemContext += "\n\n" + (conv.kanbanCardId ? await buildKanbanCardPrompt(kanbanBoard, conv.kanbanCardId) : generateKanbanPopulatePrompt(kanbanBoard));
9130
9195
  }
9131
9196
  }
9132
9197
  const resolvedImages = input.imageIds && input.imageIds.length > 0 ? await resolveImagesToBase64(input.imageIds.map((id) => ({ imageId: id, mimeType: "" })), input.conversationId) : [];
@@ -9221,13 +9286,7 @@ ${input.prompt}` : input.prompt;
9221
9286
  if (conv && conv.kanbanBoardId) {
9222
9287
  const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);
9223
9288
  if (kanbanBoard) {
9224
- system += "\n\n" + (conv.kanbanCardId ? generateKanbanSystemPrompt(
9225
- kanbanBoard,
9226
- conv.kanbanCardId,
9227
- // Le journal ne vient plus avec le tableau : le contexte de l'agent
9228
- // le demande pour la seule carte qui le concerne.
9229
- await kanbanStore.cardHistory(kanbanBoard.id, conv.kanbanCardId)
9230
- ) : generateKanbanPopulatePrompt(kanbanBoard));
9289
+ system += "\n\n" + (conv.kanbanCardId ? await buildKanbanCardPrompt(kanbanBoard, conv.kanbanCardId) : generateKanbanPopulatePrompt(kanbanBoard));
9231
9290
  }
9232
9291
  }
9233
9292
  const resolvedImages = input.imageIds && input.imageIds.length > 0 ? await resolveImagesToBase64(input.imageIds.map((id) => ({ imageId: id, mimeType: "" })), input.conversationId) : [];
@@ -12221,6 +12280,22 @@ var kanbanRouter = router({
12221
12280
  getBoard: protectedProcedure.input(z20.object({ boardId: z20.string().max(128) })).query(async ({ input }) => {
12222
12281
  const board = await kanbanStore.get(input.boardId);
12223
12282
  if (!board) return { board: null };
12283
+ const { links } = await kanbanStore.cardLinks(input.boardId);
12284
+ const parentOf = new Map(links.map((l) => [l.childCardId, l.parentCardId]));
12285
+ const childrenOf = /* @__PURE__ */ new Map();
12286
+ for (const link of links) {
12287
+ childrenOf.set(link.parentCardId, [...childrenOf.get(link.parentCardId) ?? [], link.childCardId]);
12288
+ }
12289
+ const withLinks = (card) => {
12290
+ const id = String(card["id"]);
12291
+ const parent = parentOf.get(id);
12292
+ const children = childrenOf.get(id) ?? [];
12293
+ return {
12294
+ ...card,
12295
+ ...parent ? { parentCardId: parent } : {},
12296
+ ...children.length ? { childCardIds: children } : {}
12297
+ };
12298
+ };
12224
12299
  return {
12225
12300
  board: {
12226
12301
  id: board.id,
@@ -12231,7 +12306,7 @@ var kanbanRouter = router({
12231
12306
  columns: [...board.columns].sort((a, b) => a.order - b.order).map((col) => ({
12232
12307
  id: col.id,
12233
12308
  title: col.title,
12234
- cards: [...col.cards].sort((a, b) => a.order - b.order).map((card) => summarizeCard(card, board.id, col.title))
12309
+ cards: [...col.cards].sort((a, b) => a.order - b.order).map((card) => withLinks(summarizeCard(card, board.id, col.title)))
12235
12310
  }))
12236
12311
  }
12237
12312
  };
@@ -12289,6 +12364,35 @@ var kanbanRouter = router({
12289
12364
  }))
12290
12365
  };
12291
12366
  }),
12367
+ /**
12368
+ * La filiation des cartes d'un tableau : qui dépend de qui.
12369
+ *
12370
+ * `getBoard` en donne déjà l'essentiel carte par carte ; cette route sert
12371
+ * quand c'est l'arbre lui-même qu'on veut, dates et auteurs compris.
12372
+ */
12373
+ getCardLinks: protectedProcedure.input(z20.object({ boardId: z20.string().max(128) })).query(async ({ input }) => kanbanStore.cardLinks(input.boardId)),
12374
+ /**
12375
+ * Rattacher une carte à une carte parente, ou l'en détacher.
12376
+ *
12377
+ * Sans `parentCardId`, le lien est retiré. Le parent peut vivre sur un autre
12378
+ * tableau : `parentBoardId` le désigne alors, sinon c'est celui de la carte.
12379
+ */
12380
+ setCardParent: protectedProcedure.input(z20.object({
12381
+ boardId: z20.string().max(128),
12382
+ cardId: z20.string().max(128),
12383
+ parentCardId: z20.string().max(128).optional(),
12384
+ parentBoardId: z20.string().max(128).optional()
12385
+ })).mutation(async ({ input }) => {
12386
+ const ok = await kanbanStore.setCardParent(
12387
+ input.boardId,
12388
+ input.cardId,
12389
+ input.parentCardId ? { boardId: input.parentBoardId ?? input.boardId, cardId: input.parentCardId } : null
12390
+ );
12391
+ if (!ok) {
12392
+ throw new TRPCError17({ code: "BAD_REQUEST", message: "The cloud refused the link (unknown card, or a cycle)." });
12393
+ }
12394
+ return { ok: true };
12395
+ }),
12292
12396
  moveCard: protectedProcedure.input(z20.object({
12293
12397
  boardId: z20.string().max(128),
12294
12398
  cardId: z20.string().max(128),
@@ -13466,7 +13570,16 @@ var OrgSyncConnection = class {
13466
13570
  if (name === "projects" && !isInitial) {
13467
13571
  for (const id of added) {
13468
13572
  if (deleted.has(id) || this.tracked.has(id)) continue;
13469
- await this.followProject(id);
13573
+ try {
13574
+ await this.followProject(id);
13575
+ } catch (err) {
13576
+ if (!(err instanceof ProjectHeldElsewhereError)) throw err;
13577
+ console.warn(
13578
+ "[cloud-sync] project %s appeared in org %s but is already held here \u2014 not followed",
13579
+ id,
13580
+ this.link.orgId
13581
+ );
13582
+ }
13470
13583
  }
13471
13584
  }
13472
13585
  for (const id of affected) {
@@ -16578,4 +16691,4 @@ export {
16578
16691
  createLocalServer,
16579
16692
  pullEnv
16580
16693
  };
16581
- //# sourceMappingURL=src-4GK5OK3K.js.map
16694
+ //# sourceMappingURL=src-WCSXKTXA.js.map