@runeya/runeya 2.0.54 → 2.0.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent/index.js +31 -0
- package/agent/index.js.map +1 -1
- package/agent-manager-LSAJSO3X.js +7 -0
- package/{chunk-EL75GG7O.js → chunk-Q2WY6PYX.js} +32 -1
- package/{chunk-EL75GG7O.js.map → chunk-Q2WY6PYX.js.map} +1 -1
- package/index.js +1 -1
- package/mcp-server/index.js +28 -0
- package/mcp-server/index.js.map +1 -1
- package/package.json +1 -1
- package/{src-WJLEZF7J.js → src-WCSXKTXA.js} +138 -34
- package/src-WCSXKTXA.js.map +1 -0
- package/web/assets/{AgentScalarChatInterface.vue-DL_6TCyZ.js → AgentScalarChatInterface.vue-CBm8pMxm.js} +1 -1
- package/web/assets/{AgentTerminalPage-BdwSh_cX.js → AgentTerminalPage-Cu2yebw0.js} +1 -1
- package/web/assets/AiChatPage-D_QT__oC.js +1 -0
- package/web/assets/{AppLayout-Dw9Wghps.js → AppLayout-B-JzLiuN.js} +1 -1
- package/web/assets/{AuditPage-C1f2R5st.js → AuditPage-O5w_rRoF.js} +1 -1
- package/web/assets/CloudAccountPage-8iUKumU1.js +1 -0
- package/web/assets/{CloudAccountPage-C5mDfQmz.js → CloudAccountPage-CxclkzzF.js} +1 -1
- package/web/assets/{CloudMessagingPage-BxBzOhw2.js → CloudMessagingPage-Cn4mBsGb.js} +1 -1
- package/web/assets/{DashboardPage-C08vuYJi.js → DashboardPage-CBPAacTy.js} +1 -1
- package/web/assets/{EditorIcon-CAjHyIr3.js → EditorIcon-CZLL1qox.js} +1 -1
- package/web/assets/{EnvironmentForm-ltFmzLp3.js → EnvironmentForm-A41dAsGK.js} +1 -1
- package/web/assets/{EnvironmentFormPage-o0RBmmyi.js → EnvironmentFormPage-seMzTipP.js} +1 -1
- package/web/assets/{EnvironmentListPage-xNiIdN6r.js → EnvironmentListPage-Bx_8aQ7W.js} +1 -1
- package/web/assets/{EnvironmentSelector-wuvg8idp.js → EnvironmentSelector-GuLEFkas.js} +1 -1
- package/web/assets/KanbanBoardPage-A-JNWTlH.css +1 -0
- package/web/assets/KanbanBoardPage-BV-1mFti.js +4 -0
- package/web/assets/{KanbanListPage-CHNn3y6v.js → KanbanListPage-BHmn0L7d.js} +1 -1
- package/web/assets/{LaunchProjectPage-DM7bPLwq.js → LaunchProjectPage-0x_cAt48.js} +1 -1
- package/web/assets/{LaunchServicesPage-BloAC07R.js → LaunchServicesPage-wC2HNYAu.js} +1 -1
- package/web/assets/{LogViewer-Ca6xjPhu.js → LogViewer-BRsgOXsv.js} +1 -1
- package/web/assets/{ProcessControls-E38EAl2f.js → ProcessControls-BKUKb6vL.js} +1 -1
- package/web/assets/{ProcessDetailPage-c77DeZWN.js → ProcessDetailPage-DqInQZoM.js} +1 -1
- package/web/assets/{ProcessMetrics-BXosNPyb.js → ProcessMetrics-4aaZekKw.js} +1 -1
- package/web/assets/{ProjectDetailPage-CI9LD3D-.js → ProjectDetailPage-DWdYGIm5.js} +1 -1
- package/web/assets/{ProjectListPage-BbVKfgrL.js → ProjectListPage-XKb11ZSl.js} +1 -1
- package/web/assets/{RandomJobTestPage-D9itVVeZ.js → RandomJobTestPage-D3mNVwkH.js} +1 -1
- package/web/assets/{ScenarioEditorPage-DIq3SUqe.js → ScenarioEditorPage-Bhp_uvLq.js} +1 -1
- package/web/assets/{SendToChatDialog-CR35LiAZ.js → SendToChatDialog-DdjtI7RN.js} +1 -1
- package/web/assets/{ServiceControlsBar-D3nWy1qm.js → ServiceControlsBar-CRzSTSbf.js} +1 -1
- package/web/assets/{ServiceDetailPage-DksG2QpV.js → ServiceDetailPage-ChZVB2uY.js} +1 -1
- package/web/assets/{ServiceFormPage-DWUBxcXw.js → ServiceFormPage-CXrwDYXc.js} +1 -1
- package/web/assets/{SettingsPage-DFFITOZC.js → SettingsPage-BKImNNGC.js} +4 -4
- package/web/assets/{UnlockPage-Dj6I8rIz.js → UnlockPage-IF_kNWCK.js} +1 -1
- package/web/assets/{VariablesTable-CvLewnq8.js → VariablesTable-BnfdPTJs.js} +1 -1
- package/web/assets/{VaultMigrationPage-91XI58FV.js → VaultMigrationPage-Dzn-moG9.js} +1 -1
- package/web/assets/{VersionBadge-Buj3F67o.js → VersionBadge-DJlVV7r7.js} +1 -1
- package/web/assets/WikiPage-DNm8r3l9.js +1 -0
- package/web/assets/{WikiView-Bv5z_dX5.js → WikiView-DCuU1ES2.js} +1 -1
- package/web/assets/{add-scalar-classes-CpiPzv_5.js → add-scalar-classes-DGIbkQ1f.js} +3 -3
- package/web/assets/auth-errors-DQYwI7Ju.js +1 -0
- package/web/assets/{autocomplete-DaWoxP-o.js → autocomplete-BIqGkkg7.js} +1 -1
- package/web/assets/{basic-shape-diamond.svg-DQSS51C2.js → basic-shape-diamond.svg-DH2telU3.js} +1 -1
- package/web/assets/{basic-shape-hexagon.svg-TxF0q-uH.js → basic-shape-hexagon.svg-CkFORYUC.js} +1 -1
- package/web/assets/{basic-shape-primary-circle-ellipse-round.svg-DS_gFTTk.js → basic-shape-primary-circle-ellipse-round.svg-BlV1CeJ6.js} +1 -1
- package/web/assets/{basic-shape-primary-square-rectangle.svg-CYVT80TP.js → basic-shape-primary-square-rectangle.svg-BaAO9T6a.js} +1 -1
- package/web/assets/{basic-shape-shield.svg-DXcZnD4-.js → basic-shape-shield.svg-CAX-F0Ai.js} +1 -1
- package/web/assets/{browser-CjRnDgaM.js → browser-CgnxRAK6.js} +1 -1
- package/web/assets/{browser-0MfODuvw.js → browser-DPOAuokj.js} +1 -1
- package/web/assets/{card-YlFuoCtV.js → card-BinmfAW6.js} +1 -1
- package/web/assets/{checkbox-BJSge8rp.js → checkbox-DRF4pbAa.js} +1 -1
- package/web/assets/{chip-tuB6x1ID.js → chip-Dvt1MVQM.js} +1 -1
- package/web/assets/{client-0UOUmViC.js → client-BqPXDxC1.js} +1 -1
- package/web/assets/{cloud-chat.store-DTuboyAt.js → cloud-chat.store-DqrDy_y_.js} +1 -1
- package/web/assets/{cloud-session-gFSq6ori.js → cloud-session-BPYJmCDW.js} +1 -1
- package/web/assets/{column-B7NErhBA.js → column-DFi06tD3.js} +1 -1
- package/web/assets/{computer-device-desktop-monitor.svg-B3bVipnm.js → computer-device-desktop-monitor.svg-CJMZ28bk.js} +1 -1
- package/web/assets/{computer-device-desktop.svg-BoXau9-z.js → computer-device-desktop.svg-BedAMKhR.js} +1 -1
- package/web/assets/{computer-device-laptop.svg-Cy7uHiJJ.js → computer-device-laptop.svg-DdhI-EdQ.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-android-samsung-back.svg-RYnQgms4.js → computer-device-mobile-phone-android-samsung-back.svg-C5diuYjt.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-android-samsung.svg-B2ehsGZ0.js → computer-device-mobile-phone-android-samsung.svg-DGHCufqU.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-iphone-x-back.svg-BkT0FW5i.js → computer-device-mobile-phone-iphone-x-back.svg-CMWyPtt9.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-iphone-x.svg-bRKI4fmE.js → computer-device-mobile-phone-iphone-x.svg-BRy5W1In.js} +1 -1
- package/web/assets/{computer-device-mobile-tablet-touch.svg-KjHtJ-BL.js → computer-device-mobile-tablet-touch.svg-BGnBo8Ih.js} +1 -1
- package/web/assets/{computer-device-mobile-tablet.svg-B8ZupwDd.js → computer-device-mobile-tablet.svg-xSg_XplW.js} +1 -1
- package/web/assets/{computer-device-network-ethernet-cat6.svg-Duh4Du3e.js → computer-device-network-ethernet-cat6.svg-hz-jiJFA.js} +1 -1
- package/web/assets/{computer-device-network-lan-www.svg-YVAsYA9U.js → computer-device-network-lan-www.svg-BF6NF79C.js} +1 -1
- package/web/assets/{computer-device-network-wifi-connection.svg-rIDxdWCb.js → computer-device-network-wifi-connection.svg-gwpaLcz6.js} +1 -1
- package/web/assets/{computer-device-network-wifi-router.svg-De8y0K7i.js → computer-device-network-wifi-router.svg-B4oSiJHk.js} +1 -1
- package/web/assets/{cssMode-EJVceBtB.js → cssMode-HHg8IzQM.js} +1 -1
- package/web/assets/{divider-CIiRgr15.js → divider-C5a--3VK.js} +1 -1
- package/web/assets/{ecology-science-erlenmeyer-flask.svg-DQBT-1Mu.js → ecology-science-erlenmeyer-flask.svg-DkoOes8O.js} +1 -1
- package/web/assets/{fieldset-BTjQUzQT.js → fieldset-c3hO4nzt.js} +1 -1
- package/web/assets/{freemarker2-B_kdm-Rq.js → freemarker2-BJSUPPPz.js} +1 -1
- package/web/assets/{handlebars-DzBw94Zz.js → handlebars-BAY2_Hod.js} +1 -1
- package/web/assets/{html-Xh6FYiF-.js → html-CNW7z0dM.js} +1 -1
- package/web/assets/{htmlMode-BNXzfaRq.js → htmlMode-SpxSLWYn.js} +1 -1
- package/web/assets/{image-flash-lightning.svg-BEyCczaZ.js → image-flash-lightning.svg-DzcaFZwQ.js} +1 -1
- package/web/assets/{image-picture-flower.svg-Dbg5NzOI.js → image-picture-flower.svg-DbYkuhs0.js} +1 -1
- package/web/assets/{index-CDOZ9nxJ.js → index-BIjjyvxm.js} +6 -6
- package/web/assets/{interface-alert-exclamation-diamond.svg-fZCD7XZD.js → interface-alert-exclamation-diamond.svg-VqQleX3x.js} +1 -1
- package/web/assets/{interface-alert-exclamation-triangle-warning.svg-CQRej94d.js → interface-alert-exclamation-triangle-warning.svg-B4xCH3UD.js} +1 -1
- package/web/assets/{interface-alert-information-circle.svg-DLHrC2Se.js → interface-alert-information-circle.svg-5k54XhJ-.js} +1 -1
- package/web/assets/{interface-award-crown.svg-BlUN7wR8.js → interface-award-crown.svg-BXVJGSgl.js} +1 -1
- package/web/assets/{interface-bookmark.svg-B6jtXu0i.js → interface-bookmark-tag.svg-CBUeCBGD.js} +1 -1
- package/web/assets/{interface-bookmark-tag.svg-BaUeUAdd.js → interface-bookmark.svg-D0afhfDQ.js} +1 -1
- package/web/assets/{interface-calendar-date-one.svg-BBxex0e_.js → interface-calendar-date-one.svg-CFO_cJx5.js} +1 -1
- package/web/assets/{interface-content-book-open-pages.svg-CjlIsfcr.js → interface-content-book-open-pages.svg-D_VJNLAI.js} +1 -1
- package/web/assets/{interface-content-book-page.svg-BzpGAAFD.js → interface-content-book-page.svg-BxdaWR7b.js} +1 -1
- package/web/assets/{interface-content-file.svg-Dyy73fgR.js → interface-content-file.svg-CCKgKAVi.js} +1 -1
- package/web/assets/interface-content-folder.svg-DnPIUwnJ.js +1 -0
- package/web/assets/{interface-content-folder.svg-CfXP8vIz.js → interface-content-folder.svg-Dw0SKwbv.js} +1 -1
- package/web/assets/{interface-copy-clipboard.svg-DDBGzK1F.js → interface-copy-clipboard.svg-Co7ESi9t.js} +1 -1
- package/web/assets/{interface-edit-attachment.svg-CVIogN1F.js → interface-edit-attachment.svg-DB4Fu5ck.js} +1 -1
- package/web/assets/{interface-edit-binocular.svg-CYoWoyqE.js → interface-edit-binocular.svg-DSEtWb7P.js} +1 -1
- package/web/assets/{interface-edit-magic-wand.svg-Byn796v2.js → interface-edit-magic-wand.svg-Bh9JP-_u.js} +1 -1
- package/web/assets/{interface-edit-tool-paint-roller.svg-DY94FiGr.js → interface-edit-tool-paint-roller.svg-DXODVJeW.js} +1 -1
- package/web/assets/{interface-edit-tool-pencil.svg-D4unJbHc.js → interface-edit-tool-pencil.svg-gJSTl1EM.js} +1 -1
- package/web/assets/{interface-favorite-award.svg-SfOIxE9l.js → interface-favorite-award.svg-Bv3Ditpr.js} +1 -1
- package/web/assets/{interface-favorite-flag.svg-m3lmhJfE.js → interface-favorite-flag.svg-RU02g1Zi.js} +1 -1
- package/web/assets/{interface-favorite-heart.svg-Ckud_SvW.js → interface-favorite-heart.svg-C9umX2vE.js} +1 -1
- package/web/assets/{interface-favorite-star.svg-CEutIMs0.js → interface-favorite-star.svg-CWsQ-mGb.js} +1 -1
- package/web/assets/{interface-favorite-stars-sparkles.svg-DO6jNWBO.js → interface-favorite-stars-sparkles.svg-C5z_gPrX.js} +1 -1
- package/web/assets/{interface-hierarchy-flowchart.svg-Dwh1qUA6.js → interface-hierarchy-flowchart.svg-CctM7HYF.js} +1 -1
- package/web/assets/{interface-home-house.svg-BuAfKEyV.js → interface-home-house.svg-Cd6GJDkx.js} +1 -1
- package/web/assets/{interface-hyperlink.svg-DZASdv5-.js → interface-hyperlink.svg-RUZY_MPS.js} +1 -1
- package/web/assets/{interface-lighting-brightness.svg-Grb-aAAr.js → interface-lighting-brightness.svg-CoJei7Uh.js} +1 -1
- package/web/assets/{interface-lock-closed.svg-CxTbFsuH.js → interface-lock-closed.svg-DHBiQkRu.js} +1 -1
- package/web/assets/{interface-lock-open-unlock.svg-CCz5I3Lo.js → interface-lock-open-unlock.svg-D9gUzkAe.js} +1 -1
- package/web/assets/{interface-login-key.svg-C2MW1kTq.js → interface-login-key.svg-BGNkKSCc.js} +1 -1
- package/web/assets/{interface-search.svg-C4wZrq71.js → interface-search.svg-a20xpUNh.js} +1 -1
- package/web/assets/{interface-setting-cog.svg-MBjOINAk.js → interface-setting-cog.svg-Du_6PHwV.js} +1 -1
- package/web/assets/{interface-share-megaphone-bullhorn.svg-Cruu6AYM.js → interface-share-megaphone-bullhorn.svg-cUXjeKNG.js} +1 -1
- package/web/assets/{interface-share-rocket.svg-CAcQv0d2.js → interface-share-rocket.svg-D5DY8-4Z.js} +1 -1
- package/web/assets/{interface-share-satellite.svg-DxYnGFC9.js → interface-share-satellite.svg-CxZ9ENCv.js} +1 -1
- package/web/assets/{interface-share-space-ship.svg-C2Aq6dA5.js → interface-share-space-ship.svg-DxRCAuZe.js} +1 -1
- package/web/assets/{interface-share.svg-CTQo-h6Y.js → interface-share.svg-CJ86d8ve.js} +1 -1
- package/web/assets/{interface-signal-square.svg-Ba7x9CZ2.js → interface-signal-square.svg-DaITtWso.js} +1 -1
- package/web/assets/{interface-time-clock-circle.svg-DWClfUkG.js → interface-time-clock-circle.svg-DOXyhrEi.js} +1 -1
- package/web/assets/{interface-time-hour-glass.svg-zAupR0sD.js → interface-time-hour-glass.svg-DEzjXGhd.js} +1 -1
- package/web/assets/{interface-users-multiple.svg-CirJdweX.js → interface-users-multiple.svg-DuW2zZO9.js} +1 -1
- package/web/assets/{interface-weather-moon.svg-IiiYrQWt.js → interface-weather-moon.svg-CAJTRm96.js} +1 -1
- package/web/assets/{javascript-Cx6vPkPK.js → javascript-DoNH7W21.js} +1 -1
- package/web/assets/{jsonMode-lDS_v8Da.js → jsonMode-Ba_3RQUr.js} +1 -1
- package/web/assets/{liquid-BnkZluqw.js → liquid-yqqVxQ3r.js} +1 -1
- package/web/assets/{lspLanguageFeatures-B5bvcdFy.js → lspLanguageFeatures-DsNvNJOK.js} +1 -1
- package/web/assets/{mail-chat-bubble-square.svg-D7vhvYFO.js → mail-chat-bubble-square.svg-DxuFTrxl.js} +1 -1
- package/web/assets/{mail-send-email-paper-airplane.svg-DsailhON.js → mail-send-email-paper-airplane.svg-fobU5Rru.js} +1 -1
- package/web/assets/{mail-send-envelope.svg-B-BycoCl.js → mail-send-envelope.svg-DjoyQmbK.js} +1 -1
- package/web/assets/{mdx-BFIK8jaW.js → mdx-We_KeaPg.js} +1 -1
- package/web/assets/{message-i04b-dxS.js → message-Cgzl10yY.js} +1 -1
- package/web/assets/{minus-Tm9UEaOA.js → minus-CWad93a9.js} +1 -1
- package/web/assets/{modal-D5vSU2r6.js → modal-BwAKEIsn.js} +1 -1
- package/web/assets/modal-tmtc9vXB.js +1 -0
- package/web/assets/{money-cashier-receipt.svg-DzpTJNCO.js → money-cashier-receipt.svg-Cd3vbq1N.js} +1 -1
- package/web/assets/{money-currency-dollar-pay.svg-B2Mc-zW7.js → money-currency-dollar-pay.svg-q2PhWmHi.js} +1 -1
- package/web/assets/{money-graph-arrow-increase.svg-DoVfmch1.js → money-graph-arrow-increase.svg-DFoTvPe7.js} +1 -1
- package/web/assets/{money-graph-bar-chart-increase.svg-Bxwo-gu_.js → money-graph-bar-chart-increase.svg-N1y-bW8g.js} +1 -1
- package/web/assets/{multiselect-B_ars9nN.js → multiselect-DlPZQWML.js} +1 -1
- package/web/assets/{nature-ecology-leaf.svg-w8d9ol4M.js → nature-ecology-leaf.svg-B759TwbF.js} +1 -1
- package/web/assets/{password-DQS9krym.js → password-Bbkf0Avi.js} +1 -1
- package/web/assets/{phone-telephone.svg-C0NltkQe.js → phone-telephone.svg-BAjrImUz.js} +1 -1
- package/web/assets/{plus-DKIQP6QI.js → plus-CSmkO4gT.js} +1 -1
- package/web/assets/process.store-f72KyYo3.js +1 -0
- package/web/assets/{programming-bug.svg-BxouI03Z.js → programming-bug.svg-C9yxLgbr.js} +1 -1
- package/web/assets/{programming-cloud.svg-XE-HuATq.js → programming-cloud.svg-Brnt7HfW.js} +1 -1
- package/web/assets/{programming-computer-database-server.svg-DSLXmwFD.js → programming-computer-database-server.svg-CA5tIDJ_.js} +1 -1
- package/web/assets/{programming-computer-database.svg-imJYg1MT.js → programming-computer-database.svg-BJ_fk-M0.js} +1 -1
- package/web/assets/{programming-module-four-layout.svg-CRS3Rq2L.js → programming-module-four-layout.svg-DULdtPL4.js} +1 -1
- package/web/assets/{programming-module-three.svg-Dswwx9Lp.js → programming-module-three.svg-B1vBli33.js} +1 -1
- package/web/assets/{programming-module.svg-elFXzobN.js → programming-module.svg-DpVKFxMS.js} +1 -1
- package/web/assets/{programming-script-code.svg-CjUwMG4y.js → programming-script-code.svg-CTNuSx8y.js} +1 -1
- package/web/assets/{python-Cww21QsF.js → python-B0GPM7en.js} +1 -1
- package/web/assets/{razor-i3c9eFt8.js → razor-YCIzBEVM.js} +1 -1
- package/web/assets/router-CRcngiuT.js +1 -0
- package/web/assets/settings-scope-BIR0n6j3.js +1 -0
- package/web/assets/{settings.store-CtVBaIt-.js → settings.store-DuwB5egt.js} +1 -1
- package/web/assets/{shopping-cart.svg-D3cDu63B.js → shopping-cart.svg-DinVLM6s.js} +1 -1
- package/web/assets/{shopping-gift-present.svg-0mZjAhao.js → shopping-gift-present.svg-CzHOD4sx.js} +1 -1
- package/web/assets/{shopping-shipping-box-parcel-package.svg-D-kwQviD.js → shopping-shipping-box-parcel-package.svg-Ct0cSZV2.js} +1 -1
- package/web/assets/{src-DtJSu0OS.js → src-DsmqQeZ9.js} +1 -1
- package/web/assets/{src-9nZpxZSM.js → src-HJHc4vH7.js} +1 -1
- package/web/assets/{tabpanel-7x3coX40.js → tabpanel-C4RQhLki.js} +1 -1
- package/web/assets/{tag-new-circle.svg-CnzZF0_Z.js → tag-new-circle.svg-DszV9Yu3.js} +1 -1
- package/web/assets/{travel-map-earth-globe.svg-nr8VeHpJ.js → travel-map-earth-globe.svg-DJS5nR0r.js} +1 -1
- package/web/assets/trpc-CTOLa5Ye.js +1 -0
- package/web/assets/{tsMode-BeRrx0OL.js → tsMode-DAiF0SK5.js} +1 -1
- package/web/assets/{typescript-Dl6mcWaX.js → typescript-Bs2RtJDr.js} +1 -1
- package/web/assets/useAiChatDrawer-CFsO_u5Q.js +1 -0
- package/web/assets/useCloudOrg-Ds7-Bvva.js +1 -0
- package/web/assets/useCloudOrg-zVC74FRC.css +1 -0
- package/web/assets/{useProjectCatalog-C0wpiEc8.js → useProjectCatalog-OUh8Jzm4.js} +1 -1
- package/web/assets/{xml-DxRZSDlN.js → xml-DNJakbU1.js} +1 -1
- package/web/assets/{yaml-hro6fN_i.js → yaml-CuCgMv5w.js} +1 -1
- package/web/index.html +1 -1
- package/agent-manager-RGDHYM64.js +0 -7
- package/src-WJLEZF7J.js.map +0 -1
- package/web/assets/AiChatPage-BXi0m35c.js +0 -1
- package/web/assets/CloudAccountPage-BupxvuzT.js +0 -1
- package/web/assets/KanbanBoardPage-BEMtdQgC.js +0 -4
- package/web/assets/KanbanBoardPage-Dqm-OLyl.css +0 -1
- package/web/assets/WikiPage-BPemESpQ.js +0 -1
- package/web/assets/auth-errors-C8rgEAtT.js +0 -1
- package/web/assets/interface-content-folder.svg-BlDgZDRg.js +0 -1
- package/web/assets/modal-3kPKB9Hw.js +0 -1
- package/web/assets/process.store-CM1rgJki.js +0 -1
- package/web/assets/router-Cf6LfgGn.js +0 -1
- package/web/assets/settings-scope-Cat7ah5j.js +0 -1
- package/web/assets/trpc-Byt6n6DG.js +0 -1
- package/web/assets/useAiChatDrawer-B0bdZFGU.js +0 -1
- package/web/assets/useCloudOrg--_BSeTMx.js +0 -1
- package/web/assets/useCloudOrg-C_1bonvR.css +0 -1
- /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-
|
|
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");
|
package/mcp-server/index.js
CHANGED
|
@@ -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.",
|
package/mcp-server/index.js.map
CHANGED
|
@@ -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
|
@@ -90,7 +90,7 @@ import {
|
|
|
90
90
|
vaultFor,
|
|
91
91
|
vaultIdOfRoot,
|
|
92
92
|
writeEntity
|
|
93
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
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 ?
|
|
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 ?
|
|
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 ?
|
|
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 ?
|
|
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),
|
|
@@ -16587,4 +16691,4 @@ export {
|
|
|
16587
16691
|
createLocalServer,
|
|
16588
16692
|
pullEnv
|
|
16589
16693
|
};
|
|
16590
|
-
//# sourceMappingURL=src-
|
|
16694
|
+
//# sourceMappingURL=src-WCSXKTXA.js.map
|