@runeya/runeya 2.0.25 → 2.0.27
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/index.js +1 -1
- package/mcp-server/index.js +36 -0
- package/mcp-server/index.js.map +1 -1
- package/package.json +1 -1
- package/{src-FC35JSTS.js → src-RMLLDYCE.js} +126 -1
- package/src-RMLLDYCE.js.map +1 -0
- package/web/assets/{AgentScalarChatInterface.vue-BeGU2gmp.js → AgentScalarChatInterface.vue-DSPI6Iw-.js} +1 -1
- package/web/assets/{AgentTerminalPage-HkN_XXSC.js → AgentTerminalPage-COqIEzlq.js} +1 -1
- package/web/assets/AiChatPage-CFc7KbNG.js +1 -0
- package/web/assets/{AppLayout-Bm2ABQ6Y.js → AppLayout-CduB5PAm.js} +1 -1
- package/web/assets/{AuditPage-BrwI6E-q.js → AuditPage-BKRt4q5p.js} +1 -1
- package/web/assets/{CloudAccountPage-tmBvOVFR.js → CloudAccountPage-BdtMRHqA.js} +1 -1
- package/web/assets/CloudAccountPage-HTRjahHK.js +1 -0
- package/web/assets/CloudMessagingPage-CKRgPVNR.js +2 -0
- package/web/assets/{DashboardPage-V0hVjwLS.js → DashboardPage-COXIB50G.js} +1 -1
- package/web/assets/{EditorIcon-CdWrFDVw.js → EditorIcon-DIdkqlIr.js} +1 -1
- package/web/assets/{EnvironmentForm-BfDCQjS3.js → EnvironmentForm-94JbjgMc.js} +1 -1
- package/web/assets/{EnvironmentFormPage-DZWH_Va6.js → EnvironmentFormPage-BPFoGLYG.js} +1 -1
- package/web/assets/{EnvironmentListPage-B2MxZg6d.js → EnvironmentListPage-DoWsGpIn.js} +1 -1
- package/web/assets/{EnvironmentSelector-DGsvYa4e.js → EnvironmentSelector-D7xKYoZZ.js} +1 -1
- package/web/assets/KanbanBoardPage-BDzDCbzp.css +1 -0
- package/web/assets/KanbanBoardPage-Ca7RBQtm.js +4 -0
- package/web/assets/KanbanListPage-BXWsI5ji.css +1 -0
- package/web/assets/KanbanListPage-Cgw2ik7W.js +1 -0
- package/web/assets/{LaunchProjectPage-B4KZx5Mz.js → LaunchProjectPage-447Nb6i3.js} +1 -1
- package/web/assets/{LaunchServicesPage-DUdW84pK.js → LaunchServicesPage-CFU9SkfH.js} +1 -1
- package/web/assets/{LogViewer-Mdk6mQ7E.js → LogViewer-DlDsNuvU.js} +1 -1
- package/web/assets/{ProcessControls-1Kif6fdv.js → ProcessControls-BvaAllZ_.js} +1 -1
- package/web/assets/{ProcessDetailPage-CuBvsSMU.js → ProcessDetailPage-pS2cLCxq.js} +1 -1
- package/web/assets/{ProcessMetrics-l_kfo9l-.js → ProcessMetrics-BLvaSlXi.js} +1 -1
- package/web/assets/{ProjectDetailPage-CyaT5mNt.js → ProjectDetailPage-Dg74KYBj.js} +1 -1
- package/web/assets/{ProjectListPage-C322DVID.js → ProjectListPage-CIhtK--_.js} +1 -1
- package/web/assets/{RandomJobTestPage-9AS1R_6k.js → RandomJobTestPage-34yoDjxB.js} +1 -1
- package/web/assets/{ScenarioEditorPage-DXN_BGTT.js → ScenarioEditorPage-C0qdLDFR.js} +1 -1
- package/web/assets/SendToChatDialog-COS28j81.js +1 -0
- package/web/assets/{ServiceControlsBar-DrA6gUrh.js → ServiceControlsBar-BDtQvmNc.js} +1 -1
- package/web/assets/{ServiceDetailPage-CDR6pMlG.js → ServiceDetailPage-C_drtJlU.js} +1 -1
- package/web/assets/{ServiceFormPage-B5WmiPvB.js → ServiceFormPage-mD2msQ6o.js} +1 -1
- package/web/assets/{SettingsPage-D7JdXTmc.js → SettingsPage-C8BPcYEM.js} +4 -4
- package/web/assets/{SetupPage-DsDicviA.js → SetupPage-DK2db8Hp.js} +1 -1
- package/web/assets/{UnlockPage-BQKlOS_I.js → UnlockPage-WopGWLhW.js} +1 -1
- package/web/assets/{VariablesTable-ClPdADe4.js → VariablesTable-D65CafB_.js} +1 -1
- package/web/assets/{VersionBadge-6nPfGW7X.js → VersionBadge-CE0ovTHa.js} +1 -1
- package/web/assets/WikiPage-BEAjl3sE.js +1 -0
- package/web/assets/{WikiView-BFaKevmg.js → WikiView-CF6FvyCm.js} +1 -1
- package/web/assets/{add-scalar-classes-DmcSYQJs.js → add-scalar-classes-CaO2Xice.js} +3 -3
- package/web/assets/auth-errors-ePzxFx8g.js +1 -0
- package/web/assets/{autocomplete-DTmxqXDg.js → autocomplete-CnW5yK7q.js} +1 -1
- package/web/assets/{basic-shape-diamond.svg-dQF1x9gk.js → basic-shape-diamond.svg-Bkv9ZjHf.js} +1 -1
- package/web/assets/{basic-shape-hexagon.svg-7tRw7hWy.js → basic-shape-hexagon.svg-D20uJxmK.js} +1 -1
- package/web/assets/{basic-shape-primary-circle-ellipse-round.svg-CfzQiud6.js → basic-shape-primary-circle-ellipse-round.svg-B5XhKGTG.js} +1 -1
- package/web/assets/{basic-shape-primary-square-rectangle.svg-D9Cb_fgq.js → basic-shape-primary-square-rectangle.svg-BWQZbeJS.js} +1 -1
- package/web/assets/{basic-shape-shield.svg-Duf12yNV.js → basic-shape-shield.svg-Cas8taBL.js} +1 -1
- package/web/assets/{browser-BGWGHNEi.js → browser-CKAGCYBM.js} +1 -1
- package/web/assets/{browser-DylFNbEQ.js → browser-ZjFgFnVC.js} +1 -1
- package/web/assets/{card-BE832h-K.js → card-C20l4eFB.js} +1 -1
- package/web/assets/{checkbox-CwLSUuB9.js → checkbox-DfnQXBty.js} +1 -1
- package/web/assets/{chip-DahODGzI.js → chip-BJLSl2tN.js} +1 -1
- package/web/assets/{client-FjTrgK1r.js → client-CiZKwix4.js} +1 -1
- package/web/assets/cloud-chat.store-D-s33s91.js +1 -0
- package/web/assets/{cloud-client-dqoyF-WO.js → cloud-client-BNiN622M.js} +1 -1
- package/web/assets/{column-CnVgK6Oc.js → column-Ce2OMgI5.js} +1 -1
- package/web/assets/{computer-device-desktop-monitor.svg-CWek7mxD.js → computer-device-desktop-monitor.svg-C1wBG8Sy.js} +1 -1
- package/web/assets/{computer-device-desktop.svg-D2QpEr02.js → computer-device-desktop.svg-CyY6f6_9.js} +1 -1
- package/web/assets/{computer-device-laptop.svg-CLURljDs.js → computer-device-laptop.svg-BPNvNYfT.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-android-samsung-back.svg-BV8Ycaeu.js → computer-device-mobile-phone-android-samsung-back.svg-DbltFZte.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-android-samsung.svg-DphjlFgk.js → computer-device-mobile-phone-android-samsung.svg-CrLSCe_x.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-iphone-x-back.svg-Dtjgepre.js → computer-device-mobile-phone-iphone-x-back.svg-BY19Nult.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-iphone-x.svg-Bjgw1ga4.js → computer-device-mobile-phone-iphone-x.svg-H7FI65UW.js} +1 -1
- package/web/assets/{computer-device-mobile-tablet-touch.svg-DZRThJrK.js → computer-device-mobile-tablet-touch.svg-Cmx8jUA5.js} +1 -1
- package/web/assets/{computer-device-mobile-tablet.svg-Bh0SJ1s6.js → computer-device-mobile-tablet.svg-C-ij0kaB.js} +1 -1
- package/web/assets/{computer-device-network-ethernet-cat6.svg-DwxiEi1h.js → computer-device-network-ethernet-cat6.svg-BxWINH6l.js} +1 -1
- package/web/assets/{computer-device-network-lan-www.svg-BIHwIHSX.js → computer-device-network-lan-www.svg-BSgN4bQe.js} +1 -1
- package/web/assets/{computer-device-network-wifi-connection.svg-DZ2hI4Ny.js → computer-device-network-wifi-connection.svg-9-Af1cyW.js} +1 -1
- package/web/assets/{computer-device-network-wifi-router.svg-BUr-oIXf.js → computer-device-network-wifi-router.svg-PGbsNleo.js} +1 -1
- package/web/assets/{cssMode-ClPc4s1f.js → cssMode-BXCNwJJl.js} +1 -1
- package/web/assets/{divider-DIznZLtk.js → divider-D15eSJOf.js} +1 -1
- package/web/assets/{ecology-science-erlenmeyer-flask.svg-CBxdfqcE.js → ecology-science-erlenmeyer-flask.svg-D1TcAurA.js} +1 -1
- package/web/assets/{fieldset-CVrdvAyq.js → fieldset-DpjemOKg.js} +1 -1
- package/web/assets/{freemarker2-YVakMc8c.js → freemarker2-vGwcFsrU.js} +1 -1
- package/web/assets/{handlebars-CsOTTClN.js → handlebars-CgczpBKv.js} +1 -1
- package/web/assets/{html-Dczae-Z_.js → html-BFGITMD0.js} +1 -1
- package/web/assets/{htmlMode-D0GPP7hd.js → htmlMode-B3rE7DS5.js} +1 -1
- package/web/assets/{image-flash-lightning.svg-CYj0nfja.js → image-flash-lightning.svg-xzLxZzA4.js} +1 -1
- package/web/assets/{image-picture-flower.svg-BHJs-_3f.js → image-picture-flower.svg-pnrEOEKg.js} +1 -1
- package/web/assets/{index-BLjclw5b.js → index-pgDYqJbK.js} +5 -5
- package/web/assets/{interface-alert-exclamation-diamond.svg-RaykYQv7.js → interface-alert-exclamation-diamond.svg-CI092Np8.js} +1 -1
- package/web/assets/{interface-alert-exclamation-triangle-warning.svg-DhwSnAnE.js → interface-alert-exclamation-triangle-warning.svg-C4mqQzrp.js} +1 -1
- package/web/assets/{interface-alert-information-circle.svg-DVWUQ-y3.js → interface-alert-information-circle.svg-BT4vnvBw.js} +1 -1
- package/web/assets/{interface-award-crown.svg-DeENvys4.js → interface-award-crown.svg-CRPOUMXT.js} +1 -1
- package/web/assets/{interface-bookmark.svg-mdhA9Rh2.js → interface-bookmark-tag.svg-DPVkmndo.js} +1 -1
- package/web/assets/{interface-bookmark-tag.svg-CYAmner4.js → interface-bookmark.svg-DTAetZsa.js} +1 -1
- package/web/assets/{interface-calendar-date-one.svg-CJvUtZQE.js → interface-calendar-date-one.svg-6dLyIX8s.js} +1 -1
- package/web/assets/{interface-content-book-open-pages.svg-BSyx1yDl.js → interface-content-book-open-pages.svg-6XF6zc4V.js} +1 -1
- package/web/assets/{interface-content-book-page.svg-DEVJ6w7S.js → interface-content-book-page.svg-bdqhi6K9.js} +1 -1
- package/web/assets/{interface-content-file.svg-BaP1e3Nz.js → interface-content-file.svg-1G5vO-Bf.js} +1 -1
- package/web/assets/interface-content-folder.svg-CPgJrZEE.js +1 -0
- package/web/assets/{interface-content-folder.svg-CV04ltBN.js → interface-content-folder.svg-D850sLcG.js} +1 -1
- package/web/assets/{interface-copy-clipboard.svg-BaZagGsx.js → interface-copy-clipboard.svg-BccvE8VI.js} +1 -1
- package/web/assets/{interface-edit-attachment.svg-C5GFgPK6.js → interface-edit-attachment.svg-Ce4FGCOQ.js} +1 -1
- package/web/assets/{interface-edit-binocular.svg-CJFCViVp.js → interface-edit-binocular.svg-DPRn5hZu.js} +1 -1
- package/web/assets/{interface-edit-magic-wand.svg-BilOGWmP.js → interface-edit-magic-wand.svg-DXe8x6h5.js} +1 -1
- package/web/assets/{interface-edit-tool-paint-roller.svg-CPezzO7i.js → interface-edit-tool-paint-roller.svg-DiSg_nu0.js} +1 -1
- package/web/assets/{interface-edit-tool-pencil.svg-DUKWRoUQ.js → interface-edit-tool-pencil.svg-CJ7nntID.js} +1 -1
- package/web/assets/{interface-favorite-award.svg-tqu9IiX8.js → interface-favorite-award.svg-Bp7EXD5O.js} +1 -1
- package/web/assets/{interface-favorite-flag.svg-CU3NPmWt.js → interface-favorite-flag.svg-X3mutHkA.js} +1 -1
- package/web/assets/{interface-favorite-heart.svg-C2ET2hMX.js → interface-favorite-heart.svg-BZN7wndr.js} +1 -1
- package/web/assets/{interface-favorite-star.svg-DUfVOTM4.js → interface-favorite-star.svg-DLgGRGba.js} +1 -1
- package/web/assets/{interface-favorite-stars-sparkles.svg--67FQwdB.js → interface-favorite-stars-sparkles.svg-B4M9nCgv.js} +1 -1
- package/web/assets/{interface-hierarchy-flowchart.svg-bIwdcO4j.js → interface-hierarchy-flowchart.svg-CU5Tp_c9.js} +1 -1
- package/web/assets/{interface-home-house.svg-DgnUi2fS.js → interface-home-house.svg-B1qI4Bnk.js} +1 -1
- package/web/assets/{interface-hyperlink.svg-B4K64Qkm.js → interface-hyperlink.svg-DDLaWCwm.js} +1 -1
- package/web/assets/{interface-lighting-brightness.svg-CeivbpcI.js → interface-lighting-brightness.svg-C0XYahxq.js} +1 -1
- package/web/assets/{interface-lock-closed.svg-D9wDdzAa.js → interface-lock-closed.svg-BJGiYphz.js} +1 -1
- package/web/assets/{interface-lock-open-unlock.svg-BDhNbpwy.js → interface-lock-open-unlock.svg-B9mZbDai.js} +1 -1
- package/web/assets/{interface-login-key.svg-zDG7iQqT.js → interface-login-key.svg-CLg9rb5N.js} +1 -1
- package/web/assets/{interface-search.svg-C1ikM7Fp.js → interface-search.svg-C_hyT038.js} +1 -1
- package/web/assets/{interface-setting-cog.svg-DfauNRIw.js → interface-setting-cog.svg-CPJEcVaX.js} +1 -1
- package/web/assets/{interface-share-megaphone-bullhorn.svg-DlZkgD98.js → interface-share-megaphone-bullhorn.svg-D9mnWTl1.js} +1 -1
- package/web/assets/{interface-share-rocket.svg-CfdFbFn5.js → interface-share-rocket.svg-Cv-mm6Sf.js} +1 -1
- package/web/assets/{interface-share-satellite.svg-BPWvCxF-.js → interface-share-satellite.svg-KG8vUTu7.js} +1 -1
- package/web/assets/{interface-share-space-ship.svg-DD5a3FQB.js → interface-share-space-ship.svg-G-gPwAXE.js} +1 -1
- package/web/assets/{interface-share.svg-CslEcXSJ.js → interface-share.svg-DqUCb7Ru.js} +1 -1
- package/web/assets/{interface-signal-square.svg-97fxVp0a.js → interface-signal-square.svg-D3hMImVy.js} +1 -1
- package/web/assets/{interface-time-clock-circle.svg-YQa3RM7B.js → interface-time-clock-circle.svg-BJygBdct.js} +1 -1
- package/web/assets/{interface-time-hour-glass.svg-mT6k70ML.js → interface-time-hour-glass.svg-C6VAxVap.js} +1 -1
- package/web/assets/{interface-users-multiple.svg-BFmlze9D.js → interface-users-multiple.svg-CoxyjUld.js} +1 -1
- package/web/assets/{interface-weather-moon.svg-DXUXbIT9.js → interface-weather-moon.svg-D-X12JVO.js} +1 -1
- package/web/assets/{javascript-5H3a_0CA.js → javascript-C84J6-4w.js} +1 -1
- package/web/assets/{jsonMode-CFOGBWqe.js → jsonMode-C27w1Qms.js} +1 -1
- package/web/assets/{liquid-E1_IvJr0.js → liquid-DgfNbtcl.js} +1 -1
- package/web/assets/{lspLanguageFeatures-BCDFU4kJ.js → lspLanguageFeatures-C_7i29Bj.js} +1 -1
- package/web/assets/{mail-chat-bubble-square.svg-Dhbd3Xfc.js → mail-chat-bubble-square.svg-DkpMmHLK.js} +1 -1
- package/web/assets/{mail-send-email-paper-airplane.svg-CevFQrWK.js → mail-send-email-paper-airplane.svg-D6NabH2T.js} +1 -1
- package/web/assets/{mail-send-envelope.svg-D19N4sc3.js → mail-send-envelope.svg-BbPAyASY.js} +1 -1
- package/web/assets/{mdx-D8s1fbke.js → mdx-BCuKGABs.js} +1 -1
- package/web/assets/{message-Cr0BwTm_.js → message-CoRxRh0u.js} +1 -1
- package/web/assets/{minus-CI2cVWjb.js → minus-5Bqt5ofK.js} +1 -1
- package/web/assets/{modal-Chwq5gKI.js → modal-DwRiR841.js} +1 -1
- package/web/assets/modal-WUB9U4Dm.js +1 -0
- package/web/assets/{money-cashier-receipt.svg-BLP9GUd9.js → money-cashier-receipt.svg-VmdcIGRH.js} +1 -1
- package/web/assets/{money-currency-dollar-pay.svg-Do2E6a5c.js → money-currency-dollar-pay.svg-BmWJQEO0.js} +1 -1
- package/web/assets/{money-graph-arrow-increase.svg-Bb3u0hJD.js → money-graph-arrow-increase.svg-D0-SVIVY.js} +1 -1
- package/web/assets/{money-graph-bar-chart-increase.svg-xUhybHE-.js → money-graph-bar-chart-increase.svg-DTdIZ1yD.js} +1 -1
- package/web/assets/{multiselect-XRf_T4Uw.js → multiselect-yuMT5FAw.js} +1 -1
- package/web/assets/{nature-ecology-leaf.svg-DB7iOqbY.js → nature-ecology-leaf.svg-ftrud9Ee.js} +1 -1
- package/web/assets/{password-CZuxGflc.js → password-Cw64wBy9.js} +1 -1
- package/web/assets/{phone-telephone.svg-CwD3MXAf.js → phone-telephone.svg-BukpdVe6.js} +1 -1
- package/web/assets/{plus-8vMiA_51.js → plus-DUWBjv5i.js} +1 -1
- package/web/assets/process.store-f7QERgRI.js +1 -0
- package/web/assets/{programming-bug.svg-BA3xodvx.js → programming-bug.svg-BCduWuVf.js} +1 -1
- package/web/assets/{programming-cloud.svg-CxDkrX5U.js → programming-cloud.svg-BkuU9JZc.js} +1 -1
- package/web/assets/{programming-computer-database-server.svg-DFIzARea.js → programming-computer-database-server.svg-Dz36JAv6.js} +1 -1
- package/web/assets/{programming-computer-database.svg-RCs91fes.js → programming-computer-database.svg-CgLUxdNj.js} +1 -1
- package/web/assets/{programming-module-four-layout.svg-BXBeL5K6.js → programming-module-four-layout.svg-CUcqFbuN.js} +1 -1
- package/web/assets/{programming-module-three.svg-Bnh7ohT1.js → programming-module-three.svg-Drh_K9UP.js} +1 -1
- package/web/assets/{programming-module.svg-D7jgqlmK.js → programming-module.svg-DpmnuolN.js} +1 -1
- package/web/assets/{programming-script-code.svg-Dq6WcUby.js → programming-script-code.svg-aLlzlZCt.js} +1 -1
- package/web/assets/{python-DdoNAc6t.js → python-Ch8jlEn0.js} +1 -1
- package/web/assets/{radiobutton-ChJ0LAp_.js → radiobutton-DG85qUd5.js} +1 -1
- package/web/assets/{razor-Bbu6rnR_.js → razor-CUll3FMU.js} +1 -1
- package/web/assets/router-Ckd39-Uf.js +1 -0
- package/web/assets/{settings.store-CLKxPOr0.js → settings.store-qZCJj_4D.js} +1 -1
- package/web/assets/{shopping-cart.svg-DyTT_utS.js → shopping-cart.svg-yEPUTw_R.js} +1 -1
- package/web/assets/{shopping-gift-present.svg-D5rYK_Eh.js → shopping-gift-present.svg-DaqJhwWl.js} +1 -1
- package/web/assets/{shopping-shipping-box-parcel-package.svg-CHifMyyo.js → shopping-shipping-box-parcel-package.svg-DV5YYoia.js} +1 -1
- package/web/assets/{src-22A8ZClN.js → src-CZvpZlaR.js} +1 -1
- package/web/assets/{src-Cv7ljgAd.js → src-mw3qp820.js} +1 -1
- package/web/assets/{tabpanel-Wmd_glRR.js → tabpanel-Gp2kHree.js} +1 -1
- package/web/assets/{tag-new-circle.svg-CXC14Y_h.js → tag-new-circle.svg-BHRX-TYk.js} +1 -1
- package/web/assets/{travel-map-earth-globe.svg-BcIQupJd.js → travel-map-earth-globe.svg-CmrszNdx.js} +1 -1
- package/web/assets/trpc-C-XGFhkf.js +1 -0
- package/web/assets/{tsMode-DDjjqSJY.js → tsMode-CjoWwALS.js} +1 -1
- package/web/assets/{typescript-Db7dGMfb.js → typescript-BpONFNP8.js} +1 -1
- package/web/assets/useAiChatDrawer-DTJO3AGB.js +1 -0
- package/web/assets/useCloudOrg-BEGIZ5Sw.css +1 -0
- package/web/assets/useCloudOrg-Bbpui8U3.js +1 -0
- package/web/assets/{xml-BTwnZCys.js → xml-CmjkohVQ.js} +1 -1
- package/web/assets/{yaml-BlQL6hn2.js → yaml-CKv_rPtX.js} +1 -1
- package/web/index.html +1 -1
- package/src-FC35JSTS.js.map +0 -1
- package/web/assets/AiChatPage-vHekVj1z.js +0 -1
- package/web/assets/CloudAccountPage-CUSmF2AM.js +0 -1
- package/web/assets/CloudMessagingPage-Dzs94g9N.js +0 -2
- package/web/assets/KanbanBoardPage-DYy6CU-h.css +0 -1
- package/web/assets/KanbanBoardPage-Dtlb4Ckr.js +0 -4
- package/web/assets/KanbanListPage-BoNcgR3h.css +0 -1
- package/web/assets/KanbanListPage-DwLKf2p3.js +0 -1
- package/web/assets/SendToChatDialog-Ca9fp3iF.js +0 -1
- package/web/assets/WikiPage-G2uB2wmw.js +0 -1
- package/web/assets/auth-errors-CAYjLLRT.js +0 -1
- package/web/assets/cloud-chat.store-Did0a970.js +0 -1
- package/web/assets/interface-content-folder.svg-Btjerk-2.js +0 -1
- package/web/assets/modal-DpbT_461.js +0 -1
- package/web/assets/process.store-D3xabzeZ.js +0 -1
- package/web/assets/router-BtwhNVsa.js +0 -1
- package/web/assets/trpc-tLQvBzr5.js +0 -1
- package/web/assets/useAiChatDrawer-BuFd6p1B.js +0 -1
- package/web/assets/useCloudOrg-CkFtLy01.css +0 -1
- package/web/assets/useCloudOrg-S0bXfbRx.js +0 -1
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-RMLLDYCE.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
|
@@ -86,6 +86,42 @@ var RUNEYA_CAPABILITIES = [
|
|
|
86
86
|
usageHint: '"wait 5s" \u2192 wait(ms=5000), "pause 10 seconds" \u2192 wait(ms=10000), "attends 3 secondes" \u2192 wait(ms=3000). Always convert to milliseconds.'
|
|
87
87
|
},
|
|
88
88
|
// ─── Kanban ───────────────────────────────────────────────────────────────
|
|
89
|
+
{
|
|
90
|
+
name: "kanban_list_boards",
|
|
91
|
+
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 \u2014 use kanban_get_board for those.",
|
|
92
|
+
route: "kanban.listBoards",
|
|
93
|
+
method: "GET",
|
|
94
|
+
params: [
|
|
95
|
+
{ name: "includeArchived", description: 'Set to "true" to include archived boards. Default: false.', required: false }
|
|
96
|
+
],
|
|
97
|
+
buildInput: (p) => ({ includeArchived: p.includeArchived === "true" })
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: "kanban_get_board",
|
|
101
|
+
description: "Read one kanban board: its columns, and the cards in each (id, title, markdown body, assignees, comment count). Use the exact column names it returns when moving or adding a card.",
|
|
102
|
+
route: "kanban.getBoard",
|
|
103
|
+
method: "GET",
|
|
104
|
+
params: [
|
|
105
|
+
{ name: "boardId", description: "The kanban board ID, from kanban_list_boards", required: true }
|
|
106
|
+
],
|
|
107
|
+
buildInput: (p) => ({ boardId: p.boardId })
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
name: "kanban_search_cards",
|
|
111
|
+
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.",
|
|
112
|
+
route: "kanban.searchCards",
|
|
113
|
+
method: "GET",
|
|
114
|
+
params: [
|
|
115
|
+
{ name: "query", description: "Text to look for in card titles and bodies", required: true },
|
|
116
|
+
{ name: "boardId", description: "Restrict the search to this board. Omit to search all boards.", required: false },
|
|
117
|
+
{ name: "limit", description: "Maximum number of cards to return (1-100). Default: 25.", required: false }
|
|
118
|
+
],
|
|
119
|
+
buildInput: (p) => ({
|
|
120
|
+
query: p.query,
|
|
121
|
+
...p.boardId ? { boardId: p.boardId } : {},
|
|
122
|
+
...p.limit ? { limit: Number(p.limit) } : {}
|
|
123
|
+
})
|
|
124
|
+
},
|
|
89
125
|
{
|
|
90
126
|
name: "kanban_move_card",
|
|
91
127
|
description: "Move a kanban card to another column. Use the exact column name.",
|
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_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). 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_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_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":[]}
|
package/package.json
CHANGED
|
@@ -3428,6 +3428,42 @@ var RUNEYA_CAPABILITIES = [
|
|
|
3428
3428
|
usageHint: '"wait 5s" \u2192 wait(ms=5000), "pause 10 seconds" \u2192 wait(ms=10000), "attends 3 secondes" \u2192 wait(ms=3000). Always convert to milliseconds.'
|
|
3429
3429
|
},
|
|
3430
3430
|
// ─── Kanban ───────────────────────────────────────────────────────────────
|
|
3431
|
+
{
|
|
3432
|
+
name: "kanban_list_boards",
|
|
3433
|
+
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 \u2014 use kanban_get_board for those.",
|
|
3434
|
+
route: "kanban.listBoards",
|
|
3435
|
+
method: "GET",
|
|
3436
|
+
params: [
|
|
3437
|
+
{ name: "includeArchived", description: 'Set to "true" to include archived boards. Default: false.', required: false }
|
|
3438
|
+
],
|
|
3439
|
+
buildInput: (p) => ({ includeArchived: p.includeArchived === "true" })
|
|
3440
|
+
},
|
|
3441
|
+
{
|
|
3442
|
+
name: "kanban_get_board",
|
|
3443
|
+
description: "Read one kanban board: its columns, and the cards in each (id, title, markdown body, assignees, comment count). Use the exact column names it returns when moving or adding a card.",
|
|
3444
|
+
route: "kanban.getBoard",
|
|
3445
|
+
method: "GET",
|
|
3446
|
+
params: [
|
|
3447
|
+
{ name: "boardId", description: "The kanban board ID, from kanban_list_boards", required: true }
|
|
3448
|
+
],
|
|
3449
|
+
buildInput: (p) => ({ boardId: p.boardId })
|
|
3450
|
+
},
|
|
3451
|
+
{
|
|
3452
|
+
name: "kanban_search_cards",
|
|
3453
|
+
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.",
|
|
3454
|
+
route: "kanban.searchCards",
|
|
3455
|
+
method: "GET",
|
|
3456
|
+
params: [
|
|
3457
|
+
{ name: "query", description: "Text to look for in card titles and bodies", required: true },
|
|
3458
|
+
{ name: "boardId", description: "Restrict the search to this board. Omit to search all boards.", required: false },
|
|
3459
|
+
{ name: "limit", description: "Maximum number of cards to return (1-100). Default: 25.", required: false }
|
|
3460
|
+
],
|
|
3461
|
+
buildInput: (p) => ({
|
|
3462
|
+
query: p.query,
|
|
3463
|
+
...p.boardId ? { boardId: p.boardId } : {},
|
|
3464
|
+
...p.limit ? { limit: Number(p.limit) } : {}
|
|
3465
|
+
})
|
|
3466
|
+
},
|
|
3431
3467
|
{
|
|
3432
3468
|
name: "kanban_move_card",
|
|
3433
3469
|
description: "Move a kanban card to another column. Use the exact column name.",
|
|
@@ -10820,7 +10856,96 @@ var kanbanQueueRouter = router({
|
|
|
10820
10856
|
|
|
10821
10857
|
// ../server/src/trpc/routers/kanban.ts
|
|
10822
10858
|
import { z as z20 } from "zod";
|
|
10859
|
+
function summarizeCard(card, boardId, columnTitle) {
|
|
10860
|
+
return {
|
|
10861
|
+
boardId,
|
|
10862
|
+
column: columnTitle,
|
|
10863
|
+
id: card.id,
|
|
10864
|
+
title: card.title,
|
|
10865
|
+
markdown: card.markdown ?? "",
|
|
10866
|
+
assignees: (card.assignees ?? []).map((a) => a.name),
|
|
10867
|
+
commentCount: (card.history ?? []).filter((e) => e.type === "comment").length,
|
|
10868
|
+
attachmentCount: (card.attachments ?? []).length,
|
|
10869
|
+
createdAt: card.createdAt,
|
|
10870
|
+
updatedAt: card.updatedAt
|
|
10871
|
+
};
|
|
10872
|
+
}
|
|
10873
|
+
function boardCards(board) {
|
|
10874
|
+
return [...board.columns].sort((a, b) => a.order - b.order).flatMap(
|
|
10875
|
+
(col) => [...col.cards].sort((a, b) => a.order - b.order).map((card) => summarizeCard(card, board.id, col.title))
|
|
10876
|
+
);
|
|
10877
|
+
}
|
|
10878
|
+
function boardCounts(board) {
|
|
10879
|
+
const summary = board;
|
|
10880
|
+
const columns = board.columns ?? [];
|
|
10881
|
+
return {
|
|
10882
|
+
columnCount: summary.columnCount ?? columns.length,
|
|
10883
|
+
cardCount: summary.cardCount ?? columns.reduce((sum, c) => sum + c.cards.length, 0),
|
|
10884
|
+
columns: columns.map((c) => c.title)
|
|
10885
|
+
};
|
|
10886
|
+
}
|
|
10887
|
+
function normalize(value) {
|
|
10888
|
+
return value.normalize("NFD").replace(new RegExp("\\p{Diacritic}", "gu"), "").toLowerCase();
|
|
10889
|
+
}
|
|
10823
10890
|
var kanbanRouter = router({
|
|
10891
|
+
/**
|
|
10892
|
+
* The organization's boards, without their cards — a board carries its whole
|
|
10893
|
+
* card graph, so listing them in full would be megabytes to answer "which
|
|
10894
|
+
* boards exist?". Use `getBoard` for the cards of one.
|
|
10895
|
+
*/
|
|
10896
|
+
listBoards: protectedProcedure.input(z20.object({ includeArchived: z20.boolean().optional() }).optional()).query(async ({ input }) => {
|
|
10897
|
+
const boards = await kanbanStore.list(input?.includeArchived ?? false);
|
|
10898
|
+
return {
|
|
10899
|
+
boards: boards.map((b) => {
|
|
10900
|
+
const counts = boardCounts(b);
|
|
10901
|
+
return {
|
|
10902
|
+
id: b.id,
|
|
10903
|
+
name: b.name,
|
|
10904
|
+
description: b.description,
|
|
10905
|
+
archived: b.archived,
|
|
10906
|
+
columnCount: counts.columnCount,
|
|
10907
|
+
cardCount: counts.cardCount,
|
|
10908
|
+
updatedAt: b.updatedAt
|
|
10909
|
+
};
|
|
10910
|
+
})
|
|
10911
|
+
};
|
|
10912
|
+
}),
|
|
10913
|
+
/** One board: its columns, and the cards in each. */
|
|
10914
|
+
getBoard: protectedProcedure.input(z20.object({ boardId: z20.string().max(128) })).query(async ({ input }) => {
|
|
10915
|
+
const board = await kanbanStore.get(input.boardId);
|
|
10916
|
+
if (!board) return { board: null };
|
|
10917
|
+
return {
|
|
10918
|
+
board: {
|
|
10919
|
+
id: board.id,
|
|
10920
|
+
name: board.name,
|
|
10921
|
+
description: board.description,
|
|
10922
|
+
archived: board.archived,
|
|
10923
|
+
columns: [...board.columns].sort((a, b) => a.order - b.order).map((col) => ({
|
|
10924
|
+
id: col.id,
|
|
10925
|
+
title: col.title,
|
|
10926
|
+
cards: [...col.cards].sort((a, b) => a.order - b.order).map((card) => summarizeCard(card, board.id, col.title))
|
|
10927
|
+
}))
|
|
10928
|
+
}
|
|
10929
|
+
};
|
|
10930
|
+
}),
|
|
10931
|
+
/**
|
|
10932
|
+
* Free-text search over card titles and bodies, across every board of the
|
|
10933
|
+
* organization — or one board when `boardId` is given. Archived boards are
|
|
10934
|
+
* left out: they are what the team decided to stop looking at.
|
|
10935
|
+
*/
|
|
10936
|
+
searchCards: protectedProcedure.input(z20.object({
|
|
10937
|
+
query: z20.string().min(1).max(256),
|
|
10938
|
+
boardId: z20.string().max(128).optional(),
|
|
10939
|
+
limit: z20.number().int().min(1).max(100).optional()
|
|
10940
|
+
})).query(async ({ input }) => {
|
|
10941
|
+
const needle = normalize(input.query);
|
|
10942
|
+
const ids = input.boardId ? [input.boardId] : (await kanbanStore.list()).map((b) => b.id);
|
|
10943
|
+
const boards = (await Promise.all(ids.map((id) => kanbanStore.get(id)))).filter((b) => b !== null);
|
|
10944
|
+
const matches = boards.flatMap((board) => boardCards(board).map((card) => ({ board: board.name, ...card }))).filter(
|
|
10945
|
+
(card) => normalize(String(card["title"] ?? "")).includes(needle) || normalize(String(card["markdown"] ?? "")).includes(needle)
|
|
10946
|
+
);
|
|
10947
|
+
return { total: matches.length, cards: matches.slice(0, input.limit ?? 25) };
|
|
10948
|
+
}),
|
|
10824
10949
|
moveCard: protectedProcedure.input(z20.object({
|
|
10825
10950
|
boardId: z20.string().max(128),
|
|
10826
10951
|
cardId: z20.string().max(128),
|
|
@@ -13965,4 +14090,4 @@ export {
|
|
|
13965
14090
|
createLocalServer,
|
|
13966
14091
|
pullEnv
|
|
13967
14092
|
};
|
|
13968
|
-
//# sourceMappingURL=src-
|
|
14093
|
+
//# sourceMappingURL=src-RMLLDYCE.js.map
|