@runeya/runeya 2.0.96 → 2.0.98
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 +20 -8
- package/agent/index.js.map +1 -1
- package/{chat-N7Y4JE62.js → chat-76SRZP43.js} +3 -3
- package/{chunk-BV7A2N5C.js → chunk-3SKXNOMC.js} +3 -3
- package/{chunk-ZVUSEO5P.js → chunk-MBHLFZ7C.js} +912 -719
- package/chunk-MBHLFZ7C.js.map +1 -0
- package/{companion-ZYOHTSVL.js → companion-SIHG2RVK.js} +2 -2
- package/index.js +1 -1
- package/mcp-server/index.js +289 -5
- package/mcp-server/index.js.map +1 -1
- package/mcp-server/launch.d.ts +20 -1
- package/mcp-server/launch.js +10 -5
- package/mcp-server/launch.js.map +1 -1
- package/package.json +1 -1
- package/{src-4ZDCENPU.js → src-333ZVPV4.js} +13 -5
- package/{src-4ZDCENPU.js.map → src-333ZVPV4.js.map} +1 -1
- package/web/assets/AgentScalarChatInterface.vue-BCP4oQ-O.js +13 -0
- package/web/assets/AgentTerminalPage-C-Bu_ecg.js +1 -0
- package/web/assets/AiChatPage-CKSREmOR.js +1 -0
- package/web/assets/AppLayout-CVnZmwWH.js +1 -0
- package/web/assets/AppLayout-DEJw20nu.css +1 -0
- package/web/assets/AuditPage-D2raGocK.js +1 -0
- package/web/assets/CloudAccountPage-0qN5ieof.js +1 -0
- package/web/assets/CloudAccountPage-CV9TTdVk.js +1 -0
- package/web/assets/CloudMessagingPage-CWD7RpQ-.js +2 -0
- package/web/assets/CloudMessagingPage-DWd3bv_1.css +1 -0
- package/web/assets/DashboardPage-EcAF6x0P.js +1 -0
- package/web/assets/DirectoryPickerDialog-BryfhQms.js +1 -0
- package/web/assets/{EditorIcon-CN5NnRuP.js → EditorIcon-C_aOVJRt.js} +2 -2
- package/web/assets/{EnvironmentForm-C3XYN-u_.js → EnvironmentForm-BkapwtPM.js} +2 -2
- package/web/assets/EnvironmentFormPage-C7QAs1ce.js +1 -0
- package/web/assets/EnvironmentListPage-DMTEAlor.js +1 -0
- package/web/assets/KanbanBoardPage-CcEmdrkF.js +4 -0
- package/web/assets/KanbanListPage-BWJww5Sd.js +1 -0
- package/web/assets/LaunchProjectPage-DsPeoRJM.js +1 -0
- package/web/assets/LaunchServicesPage-sNv4eWh6.js +1 -0
- package/web/assets/LogViewer-BygMlrsG.js +3 -0
- package/web/assets/{LogViewer-Ci_cA8uT.css → LogViewer-CS9CtzUm.css} +1 -1
- package/web/assets/OrgKeyPrompt-Dtb1_S1G.js +1 -0
- package/web/assets/ProcessControls-B6jRjOvZ.js +1 -0
- package/web/assets/ProcessDetailPage-BWwJeqrL.js +1 -0
- package/web/assets/{ProcessMetrics-B8ReKltW.js → ProcessMetrics-bcJ_kHKZ.js} +2 -2
- package/web/assets/ProjectDetailPage-BypoDGXZ.js +1 -0
- package/web/assets/ProjectListPage-DY-cApny.js +1 -0
- package/web/assets/RandomJobTestPage-CG4yuPP3.js +2 -0
- package/web/assets/ScenarioEditorPage-C69LbLjs.js +14 -0
- package/web/assets/SendToChatDialog-YNumW3mj.js +1 -0
- package/web/assets/ServiceControlsBar-VIhGJ7dT.js +1 -0
- package/web/assets/ServiceDetailPage-BRfqo_ID.js +2 -0
- package/web/assets/ServiceFormPage-Dpv3X6KL.js +1 -0
- package/web/assets/SettingsPage-CjmyWBD9.js +2063 -0
- package/web/assets/UnlockPage-Cbfn2hXK.js +1 -0
- package/web/assets/VariablesTable-CX7XJfqO.js +1 -0
- package/web/assets/VaultMigrationPage-CoRr0xyn.js +1 -0
- package/web/assets/VersionBadge-CXCPlkLe.js +1 -0
- package/web/assets/WikiPage-CkcQJ2fE.js +1 -0
- package/web/assets/WikiView-DPGhKRAV.js +1 -0
- package/web/assets/add-scalar-classes-D7X53yAR.js +387 -0
- package/web/assets/auth-errors-DnpRNHod.js +1 -0
- package/web/assets/{autocomplete-eQhMihkm.js → autocomplete-DWWjDeP2.js} +3 -3
- package/web/assets/{basic-shape-diamond.svg-B79z96pk.js → basic-shape-diamond.svg-giVc-mOc.js} +1 -1
- package/web/assets/{basic-shape-hexagon.svg-DAlWXIQS.js → basic-shape-hexagon.svg-Cs0yG19E.js} +1 -1
- package/web/assets/{basic-shape-primary-circle-ellipse-round.svg-C5OZu4mS.js → basic-shape-primary-circle-ellipse-round.svg-CzxM3e1f.js} +1 -1
- package/web/assets/{basic-shape-primary-square-rectangle.svg-BykiIk1Y.js → basic-shape-primary-square-rectangle.svg-C95cJI4d.js} +1 -1
- package/web/assets/{basic-shape-shield.svg-BVcBjIsG.js → basic-shape-shield.svg-wTCwdnRC.js} +1 -1
- package/web/assets/{browser-BeUKu6QW.js → browser-CZciy3st.js} +1 -1
- package/web/assets/{browser-2YDfpiMy.js → browser-KodijhgE.js} +1 -1
- package/web/assets/card-C25ChBpF.js +32 -0
- package/web/assets/{checkbox-CmaD3L1T.js → checkbox-DEAMlJft.js} +3 -3
- package/web/assets/{chip-CRmYXa8f.js → chip-uE963n-s.js} +2 -2
- package/web/assets/client-je42aE2e.js +24 -0
- package/web/assets/cloud-chat.store-Zzg8ll0J.js +1 -0
- package/web/assets/cloud-session-BuCz6UQP.js +1 -0
- package/web/assets/column-Cms5SVPR.js +907 -0
- package/web/assets/{computer-device-desktop-monitor.svg-DgYmz8if.js → computer-device-desktop-monitor.svg-BylgGK07.js} +1 -1
- package/web/assets/{computer-device-desktop.svg-CN3hxMSt.js → computer-device-desktop.svg-qoXFyQry.js} +1 -1
- package/web/assets/{computer-device-laptop.svg-LDsA7kc5.js → computer-device-laptop.svg-DWcxSkHU.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-android-samsung-back.svg-BDfCASg6.js → computer-device-mobile-phone-android-samsung-back.svg-nyGcK2AV.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-android-samsung.svg-BMMyDOdR.js → computer-device-mobile-phone-android-samsung.svg-B-B9DnnD.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-iphone-x-back.svg-BMcE4PZg.js → computer-device-mobile-phone-iphone-x-back.svg-D1xWmS-2.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-iphone-x.svg-DCaO9pra.js → computer-device-mobile-phone-iphone-x.svg-BG31euIf.js} +1 -1
- package/web/assets/{computer-device-mobile-tablet-touch.svg-CL-ZgWuC.js → computer-device-mobile-tablet-touch.svg-CA9G0U0-.js} +1 -1
- package/web/assets/{computer-device-mobile-tablet.svg-DDOk54bt.js → computer-device-mobile-tablet.svg-CRxAMxXj.js} +1 -1
- package/web/assets/{computer-device-network-ethernet-cat6.svg-BlCpBZ1-.js → computer-device-network-ethernet-cat6.svg-Kr3zCE41.js} +1 -1
- package/web/assets/{computer-device-network-lan-www.svg-BnDixCMz.js → computer-device-network-lan-www.svg-CPLhhOUs.js} +1 -1
- package/web/assets/{computer-device-network-wifi-connection.svg-CVBp6RTa.js → computer-device-network-wifi-connection.svg-ClRAdq1j.js} +1 -1
- package/web/assets/{computer-device-network-wifi-router.svg-DC_hG81D.js → computer-device-network-wifi-router.svg-_8aeHm8n.js} +1 -1
- package/web/assets/{cssMode-CvjBWwcj.js → cssMode-CbB-baIv.js} +1 -1
- package/web/assets/{divider-DtkApHDJ.js → divider-B6_1Ju2t.js} +2 -2
- package/web/assets/{docx-preview-D-0_AO3N.js → docx-preview-DeKYOymU.js} +1 -1
- package/web/assets/{ecology-science-erlenmeyer-flask.svg-Dou8Xul9.js → ecology-science-erlenmeyer-flask.svg-CvdMWoub.js} +1 -1
- package/web/assets/{fieldset-CaTLOGqs.js → fieldset-DTWlcVOh.js} +2 -2
- package/web/assets/{freemarker2-DS7rB38N.js → freemarker2-HU2-ude_.js} +1 -1
- package/web/assets/{handlebars-D_6N9S4t.js → handlebars-DEfTSnH3.js} +1 -1
- package/web/assets/{html-aq8_YJ2V.js → html-DJwlf-_0.js} +1 -1
- package/web/assets/{htmlMode-CVlBX1og.js → htmlMode-B_2W_FNG.js} +1 -1
- package/web/assets/{image-flash-lightning.svg-DIcyUXwz.js → image-flash-lightning.svg-DxDmYt-K.js} +1 -1
- package/web/assets/{image-picture-flower.svg-CZjlyM5Y.js → image-picture-flower.svg-B2ysY7Ez.js} +1 -1
- package/web/assets/{index-BPOeXMH7.js → index-BqL8zZUd.js} +366 -366
- package/web/assets/{index-BBYieFBt.css → index-C0Lt6sdY.css} +1 -1
- package/web/assets/{interface-alert-exclamation-diamond.svg-yMZPAslx.js → interface-alert-exclamation-diamond.svg-Cy-q0PPD.js} +1 -1
- package/web/assets/{interface-alert-exclamation-triangle-warning.svg-B-t1Ml9l.js → interface-alert-exclamation-triangle-warning.svg-5GTUkGyl.js} +1 -1
- package/web/assets/{interface-alert-information-circle.svg-B8HdecEH.js → interface-alert-information-circle.svg-CULAFRLG.js} +1 -1
- package/web/assets/{interface-award-crown.svg-DDbSGaEo.js → interface-award-crown.svg-IfA0R219.js} +1 -1
- package/web/assets/{interface-bookmark.svg-BZwwsorn.js → interface-bookmark-tag.svg-CK7uh_UM.js} +1 -1
- package/web/assets/{interface-bookmark-tag.svg-C5dS6Wy_.js → interface-bookmark.svg-B6DP-eOU.js} +1 -1
- package/web/assets/{interface-calendar-date-one.svg-B_lSSDJQ.js → interface-calendar-date-one.svg-HeuC-uLL.js} +1 -1
- package/web/assets/{interface-content-book-open-pages.svg-CPjHk5dC.js → interface-content-book-open-pages.svg-BbVGNhbo.js} +1 -1
- package/web/assets/{interface-content-book-page.svg-DLBNBM0O.js → interface-content-book-page.svg-TgiMUTDz.js} +1 -1
- package/web/assets/{interface-content-file.svg-dZo-oryw.js → interface-content-file.svg-vBz32nix.js} +1 -1
- package/web/assets/interface-content-folder.svg-DWRLYbXv.js +1 -0
- package/web/assets/{interface-content-folder.svg-D3PMAR0L.js → interface-content-folder.svg-Dh6i4WMj.js} +1 -1
- package/web/assets/{interface-copy-clipboard.svg-hGQ6TIiI.js → interface-copy-clipboard.svg-D5iacSkg.js} +1 -1
- package/web/assets/{interface-edit-attachment.svg-r3GzouWU.js → interface-edit-attachment.svg-BuDlvGLW.js} +1 -1
- package/web/assets/{interface-edit-binocular.svg-Cfv2KJGW.js → interface-edit-binocular.svg-CkRvNsTG.js} +1 -1
- package/web/assets/{interface-edit-magic-wand.svg-DgdmCAUF.js → interface-edit-magic-wand.svg-U2D8Txx_.js} +1 -1
- package/web/assets/{interface-edit-tool-paint-roller.svg-D9b8KTHm.js → interface-edit-tool-paint-roller.svg-B1tbUZdf.js} +1 -1
- package/web/assets/{interface-edit-tool-pencil.svg-6EZF-4AD.js → interface-edit-tool-pencil.svg-DSu15aW1.js} +1 -1
- package/web/assets/{interface-favorite-award.svg-CX7vjSmO.js → interface-favorite-award.svg-BVkYy4-X.js} +1 -1
- package/web/assets/{interface-favorite-flag.svg-Bf-5zzqB.js → interface-favorite-flag.svg-DH2kZwOe.js} +1 -1
- package/web/assets/{interface-favorite-heart.svg-CuDUk_-U.js → interface-favorite-heart.svg-CSiLFjiO.js} +1 -1
- package/web/assets/{interface-favorite-star.svg-jiT9sBTw.js → interface-favorite-star.svg-3MpBVvJ5.js} +1 -1
- package/web/assets/{interface-favorite-stars-sparkles.svg-B14YHOWj.js → interface-favorite-stars-sparkles.svg-Do5o_8CI.js} +1 -1
- package/web/assets/{interface-hierarchy-flowchart.svg-DxZmAHe8.js → interface-hierarchy-flowchart.svg-B1-j3kUD.js} +1 -1
- package/web/assets/{interface-home-house.svg-CPRm99Q5.js → interface-home-house.svg-D1HguPAL.js} +1 -1
- package/web/assets/{interface-hyperlink.svg-CYpU8zdB.js → interface-hyperlink.svg-DqPngT30.js} +1 -1
- package/web/assets/{interface-lighting-brightness.svg-Bm2pypGs.js → interface-lighting-brightness.svg-DClYpH8v.js} +1 -1
- package/web/assets/{interface-lock-closed.svg-BJbzqDi9.js → interface-lock-closed.svg-DDnsn-BI.js} +1 -1
- package/web/assets/{interface-lock-open-unlock.svg-Be2miC-V.js → interface-lock-open-unlock.svg-uL6o62w3.js} +1 -1
- package/web/assets/{interface-login-key.svg-BvPEKsKK.js → interface-login-key.svg-e73NKVRd.js} +1 -1
- package/web/assets/{interface-search.svg-CxqA1oOe.js → interface-search.svg-DpkvQinQ.js} +1 -1
- package/web/assets/{interface-setting-cog.svg-RjIklwFA.js → interface-setting-cog.svg---AIvweU.js} +1 -1
- package/web/assets/{interface-share-megaphone-bullhorn.svg-CqesMCvG.js → interface-share-megaphone-bullhorn.svg-D2badk6M.js} +1 -1
- package/web/assets/{interface-share-rocket.svg-Du5P2iVk.js → interface-share-rocket.svg-6B06C_7X.js} +1 -1
- package/web/assets/{interface-share-satellite.svg-BMzUK6ux.js → interface-share-satellite.svg-P0R4jbH7.js} +1 -1
- package/web/assets/{interface-share-space-ship.svg-BWpbb-zz.js → interface-share-space-ship.svg-CPc2Kr86.js} +1 -1
- package/web/assets/{interface-share.svg-C044g6pa.js → interface-share.svg-DNGRMU5_.js} +1 -1
- package/web/assets/{interface-signal-square.svg-DypNLn80.js → interface-signal-square.svg-BnGGCn_I.js} +1 -1
- package/web/assets/{interface-time-clock-circle.svg-CRNvdPs5.js → interface-time-clock-circle.svg-DSq7D7IE.js} +1 -1
- package/web/assets/{interface-time-hour-glass.svg-BYTiCdVN.js → interface-time-hour-glass.svg-C3xRi1SV.js} +1 -1
- package/web/assets/{interface-users-multiple.svg-B0BO30tc.js → interface-users-multiple.svg-CPVqJeNN.js} +1 -1
- package/web/assets/{interface-weather-moon.svg-C9dWP7q-.js → interface-weather-moon.svg-BZFQlmJ8.js} +1 -1
- package/web/assets/{javascript-DCs9TLWg.js → javascript-hGBVLh1i.js} +1 -1
- package/web/assets/{jsonMode-BE2uSFxY.js → jsonMode-DlGxKO4o.js} +2 -2
- package/web/assets/{liquid-BZjYukYL.js → liquid-CHZa4fn-.js} +1 -1
- package/web/assets/{lspLanguageFeatures-4LyxjQPX.js → lspLanguageFeatures-B3XS0Aab.js} +3 -3
- package/web/assets/{mail-chat-bubble-square.svg-CTGFukhv.js → mail-chat-bubble-square.svg-B-m_8Ftp.js} +1 -1
- package/web/assets/{mail-send-email-paper-airplane.svg-DD-FZNCw.js → mail-send-email-paper-airplane.svg-pdfuG_gi.js} +1 -1
- package/web/assets/{mail-send-envelope.svg-AuHOjRAo.js → mail-send-envelope.svg-BbRGrHIB.js} +1 -1
- package/web/assets/{mdx-9unslLAn.js → mdx-O6Bp6Wm_.js} +1 -1
- package/web/assets/{minus-CHP_QK2B.js → minus-9fOaQxxR.js} +2 -2
- package/web/assets/modal-BE3TL0KL.js +1 -0
- package/web/assets/modal-Djtbj5Rv.js +5 -0
- package/web/assets/{money-cashier-receipt.svg-B3aJCJ9h.js → money-cashier-receipt.svg-B5w6NN65.js} +1 -1
- package/web/assets/{money-currency-dollar-pay.svg-xdKFuxOB.js → money-currency-dollar-pay.svg-CvB1o8rf.js} +1 -1
- package/web/assets/{money-graph-arrow-increase.svg-wWmaxtEW.js → money-graph-arrow-increase.svg-CBF_1ZI5.js} +1 -1
- package/web/assets/{money-graph-bar-chart-increase.svg-BEhoD6l7.js → money-graph-bar-chart-increase.svg-Da_V0hyb.js} +1 -1
- package/web/assets/multiselect-DDoSYwWj.js +251 -0
- package/web/assets/{nature-ecology-leaf.svg-DjdQrhs6.js → nature-ecology-leaf.svg-BcpJmi4O.js} +1 -1
- package/web/assets/{password-CrFWhx7M.js → password-C0iEyf8i.js} +4 -4
- package/web/assets/{phone-telephone.svg-CLNYyQne.js → phone-telephone.svg-DX3q6G6y.js} +1 -1
- package/web/assets/{plus-DW-wbR7B.js → plus-BYi81Tr8.js} +6 -6
- package/web/assets/process.store-BpUWGSdq.js +1 -0
- package/web/assets/{programming-bug.svg-MarViUOk.js → programming-bug.svg-BehKMs-E.js} +1 -1
- package/web/assets/{programming-cloud.svg-W3xHdUnB.js → programming-cloud.svg-B61GYVre.js} +1 -1
- package/web/assets/{programming-computer-database-server.svg-CKehXNTl.js → programming-computer-database-server.svg-3DGUioUy.js} +1 -1
- package/web/assets/{programming-computer-database.svg-gCA_mBCi.js → programming-computer-database.svg-wQpWxR3M.js} +1 -1
- package/web/assets/{programming-module-four-layout.svg-BqwwSEVQ.js → programming-module-four-layout.svg-DzgTiLIk.js} +1 -1
- package/web/assets/{programming-module-three.svg-DqwYgzpA.js → programming-module-three.svg-M0DCgTjN.js} +1 -1
- package/web/assets/{programming-module.svg-BV--KFzc.js → programming-module.svg-BOC6URSy.js} +1 -1
- package/web/assets/{programming-script-code.svg-CBCpPkxq.js → programming-script-code.svg-C3xFaN0l.js} +1 -1
- package/web/assets/{python-CCsqTZHL.js → python-eMHIZQyy.js} +1 -1
- package/web/assets/{razor-BRMeTt-k.js → razor-UJ0I37b5.js} +1 -1
- package/web/assets/router-C1Ext_ri.js +1 -0
- package/web/assets/settings-scope-By7npmQf.js +1 -0
- package/web/assets/{settings.store-erZiUPuR.js → settings.store-B3TGTzZS.js} +1 -1
- package/web/assets/{shopping-cart.svg-jc4kXbD3.js → shopping-cart.svg-6EFaCdBY.js} +1 -1
- package/web/assets/{shopping-gift-present.svg-Bqvvhp3D.js → shopping-gift-present.svg-Ts4I3V_5.js} +1 -1
- package/web/assets/{shopping-shipping-box-parcel-package.svg-D2SgWwJp.js → shopping-shipping-box-parcel-package.svg-C8_ozIk3.js} +1 -1
- package/web/assets/src-D1-b3cJF.js +1 -0
- package/web/assets/src-dpFgucNZ.css +1 -0
- package/web/assets/{src-dSgRs0bd.js → src-wi7XOQt2.js} +13 -13
- package/web/assets/tabpanel-CgfewHLu.js +150 -0
- package/web/assets/{tag-new-circle.svg-CkA4UdUB.js → tag-new-circle.svg-DycuoP-e.js} +1 -1
- package/web/assets/{toggleswitch-DKBXnmzT.js → toggleswitch-BRXSsqba.js} +2 -2
- package/web/assets/{travel-map-earth-globe.svg-kl6fMv7M.js → travel-map-earth-globe.svg-B4NyICHP.js} +1 -1
- package/web/assets/trpc-C4Crlf9C.js +1 -0
- package/web/assets/{tsMode-DA6ejbio.js → tsMode-DBth4O86.js} +5 -5
- package/web/assets/{typescript-Bfy7_Fw8.js → typescript-Bh9YpsFc.js} +1 -1
- package/web/assets/useAiChatDrawer-D7Vpm-Ax.js +1 -0
- package/web/assets/useCloudOrg-arsGRyWT.js +572 -0
- package/web/assets/useProjectCatalog-DcDvQvqC.js +1 -0
- package/web/assets/{xml-D5p3PPs0.js → xml-D10bhlvQ.js} +1 -1
- package/web/assets/{yaml-CzBSY9q-.js → yaml-Dum5r-cT.js} +1 -1
- package/web/index.html +2 -2
- package/chunk-ZVUSEO5P.js.map +0 -1
- package/web/assets/AgentScalarChatInterface.vue-Cg4DrH5-.js +0 -13
- package/web/assets/AgentTerminalPage-ClgOOzjC.js +0 -1
- package/web/assets/AiChatPage-CrqIi3zp.js +0 -1
- package/web/assets/AppLayout-nrP0jOZ1.css +0 -1
- package/web/assets/AppLayout-tfKCrE0A.js +0 -1
- package/web/assets/AuditPage-BwjVcB_e.js +0 -1
- package/web/assets/CloudAccountPage-DJMj6rlx.js +0 -1
- package/web/assets/CloudAccountPage-YqD1oWcl.js +0 -1
- package/web/assets/CloudMessagingPage-CGAN3l_2.js +0 -2
- package/web/assets/CloudMessagingPage-DJGOTMJG.css +0 -1
- package/web/assets/DashboardPage-uzdaeNvE.js +0 -1
- package/web/assets/DirectoryPickerDialog-_nki96n0.js +0 -1
- package/web/assets/EnvironmentFormPage-DzpLGPiH.js +0 -1
- package/web/assets/EnvironmentListPage-C2EfOvUQ.js +0 -1
- package/web/assets/KanbanBoardPage-D62-0_x0.js +0 -4
- package/web/assets/KanbanListPage-mgJfhVzZ.js +0 -1
- package/web/assets/LaunchProjectPage-CRL5enYT.js +0 -1
- package/web/assets/LaunchServicesPage-BaIi1u2l.js +0 -1
- package/web/assets/LogViewer-CQmf3bkB.js +0 -3
- package/web/assets/OrgKeyPrompt-x919NFZU.js +0 -1
- package/web/assets/ProcessControls-Bxuzo9xu.js +0 -1
- package/web/assets/ProcessDetailPage-CM4gv6qW.js +0 -1
- package/web/assets/ProjectDetailPage-DiaanTyL.js +0 -1
- package/web/assets/ProjectListPage-eq12Vdsi.js +0 -1
- package/web/assets/RandomJobTestPage-CJbdpqF0.js +0 -2
- package/web/assets/ScenarioEditorPage-D8xmK-aZ.js +0 -14
- package/web/assets/SendToChatDialog-B0m5-H1l.js +0 -1
- package/web/assets/ServiceControlsBar-BdT0XYtF.js +0 -1
- package/web/assets/ServiceDetailPage-DGojuDKp.js +0 -2
- package/web/assets/ServiceFormPage-6aPMUBjp.js +0 -1
- package/web/assets/SettingsPage-DisZogYn.js +0 -2063
- package/web/assets/UnlockPage-QEUvn5MU.js +0 -1
- package/web/assets/VariablesTable-B9UiC69p.js +0 -1
- package/web/assets/VaultMigrationPage-BKammxdb.js +0 -1
- package/web/assets/VersionBadge-B5SmMtZS.js +0 -1
- package/web/assets/WikiPage-ChtHYLsn.js +0 -1
- package/web/assets/WikiView-Brud4K4u.js +0 -1
- package/web/assets/add-scalar-classes-CF1ZlVmT.js +0 -387
- package/web/assets/auth-errors-1gmtFIpl.js +0 -1
- package/web/assets/card-BAlWlIgX.js +0 -32
- package/web/assets/client-Bv9-b6hD.js +0 -24
- package/web/assets/cloud-chat.store-D9e_ZoEW.js +0 -1
- package/web/assets/cloud-session-CfIHVKlU.js +0 -1
- package/web/assets/column-C9854MaP.js +0 -907
- package/web/assets/interface-content-folder.svg-CeaK9A2u.js +0 -1
- package/web/assets/modal-BTKNoQeE.js +0 -1
- package/web/assets/modal-OQde8W0w.js +0 -5
- package/web/assets/multiselect-DtWF2AZf.js +0 -251
- package/web/assets/process.store-DrmMxxoc.js +0 -1
- package/web/assets/router-CV1Vunn0.js +0 -1
- package/web/assets/settings-scope-BTe7KdSG.js +0 -1
- package/web/assets/src-CGoYw9sv.css +0 -1
- package/web/assets/src-CeApk0FF.js +0 -1
- package/web/assets/tabpanel-CeLflR6J.js +0 -150
- package/web/assets/trpc-CgcMlFhM.js +0 -1
- package/web/assets/useAiChatDrawer-DPZ2UftQ.js +0 -1
- package/web/assets/useCloudOrg-CsuqKLSU.js +0 -572
- package/web/assets/useProjectCatalog-4ks7Tpfb.js +0 -1
- /package/{chat-N7Y4JE62.js.map → chat-76SRZP43.js.map} +0 -0
- /package/{chunk-BV7A2N5C.js.map → chunk-3SKXNOMC.js.map} +0 -0
- /package/{companion-ZYOHTSVL.js.map → companion-SIHG2RVK.js.map} +0 -0
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
resetRelaunches,
|
|
25
25
|
syncConversationFromClaudeTranscript,
|
|
26
26
|
verifyJwt
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-3SKXNOMC.js";
|
|
28
28
|
import {
|
|
29
29
|
agentManager,
|
|
30
30
|
agentStore,
|
|
@@ -87,466 +87,104 @@ import { execFile } from "child_process";
|
|
|
87
87
|
import { promisify } from "util";
|
|
88
88
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
89
89
|
|
|
90
|
-
// ../../packages/
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
// ../../packages/mcp-server/src/launch.ts
|
|
91
|
+
import { fileURLToPath } from "url";
|
|
92
|
+
import { createRequire } from "module";
|
|
93
|
+
import { existsSync } from "fs";
|
|
94
|
+
function resolveMcpServerPath() {
|
|
95
|
+
try {
|
|
96
|
+
const req = createRequire(import.meta.url);
|
|
97
|
+
return req.resolve("@runeya/packages-mcp-server");
|
|
98
|
+
} catch {
|
|
99
|
+
}
|
|
100
|
+
const candidates = [
|
|
101
|
+
// Build packagé du CLI : dist/agent/index.js et dist/index.js côtoient
|
|
102
|
+
// dist/mcp-server/, copié là par le post-build.
|
|
103
|
+
new URL("../mcp-server/index.js", import.meta.url),
|
|
104
|
+
new URL("./mcp-server/index.js", import.meta.url),
|
|
105
|
+
// Monorepo, depuis un dist d'app.
|
|
106
|
+
new URL("../../../packages/mcp-server/dist/index.js", import.meta.url),
|
|
107
|
+
new URL("../../../../packages/mcp-server/dist/index.js", import.meta.url)
|
|
108
|
+
];
|
|
109
|
+
for (const c of candidates) {
|
|
110
|
+
const p = fileURLToPath(c);
|
|
111
|
+
if (existsSync(p)) return p;
|
|
112
|
+
}
|
|
113
|
+
throw new Error("Could not locate @runeya/packages-mcp-server (built dist not found)");
|
|
114
|
+
}
|
|
115
|
+
function pickEnv(env2) {
|
|
116
|
+
return {
|
|
117
|
+
...env2.RUNEYA_BASE_URL ? { RUNEYA_BASE_URL: env2.RUNEYA_BASE_URL } : {},
|
|
118
|
+
...env2.RUNEYA_API_TOKEN ? { RUNEYA_API_TOKEN: env2.RUNEYA_API_TOKEN } : {},
|
|
119
|
+
...env2.RUNEYA_PROJECT_ID ? { RUNEYA_PROJECT_ID: env2.RUNEYA_PROJECT_ID } : {},
|
|
120
|
+
...env2.RUNEYA_ORG_ID ? { RUNEYA_ORG_ID: env2.RUNEYA_ORG_ID } : {}
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function runeyaMcpConfig(env2) {
|
|
124
|
+
return JSON.stringify({
|
|
125
|
+
mcpServers: {
|
|
126
|
+
runeya: {
|
|
127
|
+
command: "node",
|
|
128
|
+
args: [resolveMcpServerPath()],
|
|
129
|
+
env: pickEnv(env2)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
function codexMcpArgs(env2) {
|
|
135
|
+
const fields = [
|
|
136
|
+
`command=${tomlString("node")}`,
|
|
137
|
+
`args=[${tomlString(resolveMcpServerPath())}]`
|
|
138
|
+
];
|
|
139
|
+
const entries = Object.entries(pickEnv(env2));
|
|
140
|
+
if (entries.length > 0) {
|
|
141
|
+
const inline = entries.map(([k, v]) => `${k}=${tomlString(v)}`).join(",");
|
|
142
|
+
fields.push(`env={${inline}}`);
|
|
143
|
+
}
|
|
144
|
+
return ["-c", `mcp_servers.runeya={${fields.join(",")}}`];
|
|
145
|
+
}
|
|
146
|
+
function tomlString(value) {
|
|
147
|
+
const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/[\u0000-\u001f\u007f]/g, (c) => `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`);
|
|
148
|
+
return `"${escaped}"`;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ../server/src/services/codex-sessions.ts
|
|
152
|
+
import { readdir } from "fs/promises";
|
|
153
|
+
import { homedir } from "os";
|
|
154
|
+
import { join } from "path";
|
|
155
|
+
var CODEX_SESSIONS_DIR = join(homedir(), ".codex", "sessions");
|
|
156
|
+
async function findCodexSessionFile(sessionId) {
|
|
157
|
+
const suffix = `-${sessionId}.jsonl`;
|
|
158
|
+
async function walk(dir) {
|
|
159
|
+
let entries;
|
|
95
160
|
try {
|
|
96
|
-
|
|
97
|
-
if (Array.isArray(parsed)) return parsed.map((v) => String(v).trim()).filter(Boolean);
|
|
161
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
98
162
|
} catch {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
for (const entry of entries) {
|
|
166
|
+
const full = join(dir, entry.name);
|
|
167
|
+
if (entry.isDirectory()) {
|
|
168
|
+
const found = await walk(full);
|
|
169
|
+
if (found) return found;
|
|
170
|
+
} else if (entry.name.endsWith(suffix)) {
|
|
171
|
+
return full;
|
|
172
|
+
}
|
|
99
173
|
}
|
|
174
|
+
return null;
|
|
100
175
|
}
|
|
101
|
-
return
|
|
176
|
+
return walk(CODEX_SESSIONS_DIR);
|
|
102
177
|
}
|
|
103
|
-
function
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
return { [key]: parse2(text) };
|
|
178
|
+
async function codexSessionExists(sessionId) {
|
|
179
|
+
const { threadExists } = await import("./codex-thread-db-LE5FYDDA.js");
|
|
180
|
+
if (threadExists(sessionId)) return true;
|
|
181
|
+
return await findCodexSessionFile(sessionId) !== null;
|
|
108
182
|
}
|
|
109
|
-
|
|
110
|
-
{
|
|
111
|
-
|
|
112
|
-
description: "List all available services. Returns serviceId and agentId for each \u2014 use these exact fields in other calls.",
|
|
113
|
-
route: "service.list",
|
|
114
|
-
method: "GET",
|
|
115
|
-
params: [],
|
|
116
|
-
buildInput: () => void 0
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
name: "get_service_status",
|
|
120
|
-
description: "Get the current status (running, stopped, etc.) of a service.",
|
|
121
|
-
route: "process.get",
|
|
122
|
-
method: "GET",
|
|
123
|
-
params: [
|
|
124
|
-
{ name: "serviceId", description: "The service ID", required: true },
|
|
125
|
-
{ name: "agentId", description: "The agent ID hosting this service", required: true }
|
|
126
|
-
],
|
|
127
|
-
buildInput: (p) => ({ agentId: p.agentId, id: p.serviceId })
|
|
128
|
-
},
|
|
129
|
-
{
|
|
130
|
-
name: "get_logs",
|
|
131
|
-
description: "Get the recent buffered logs for a service.",
|
|
132
|
-
route: "process.logs",
|
|
133
|
-
method: "GET",
|
|
134
|
-
params: [
|
|
135
|
-
{ name: "serviceId", description: "The service ID", required: true },
|
|
136
|
-
{ name: "agentId", description: "The agent ID hosting this service", required: true }
|
|
137
|
-
],
|
|
138
|
-
buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId })
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
name: "start_service",
|
|
142
|
-
description: "Start a service on an agent.",
|
|
143
|
-
route: "process.start",
|
|
144
|
-
method: "POST",
|
|
145
|
-
params: [
|
|
146
|
-
{ name: "serviceId", description: "The service ID to start", required: true },
|
|
147
|
-
{ name: "agentId", description: "The agent ID hosting this service", required: true }
|
|
148
|
-
],
|
|
149
|
-
buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),
|
|
150
|
-
destructive: true
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
name: "stop_service",
|
|
154
|
-
description: "Stop a running service on an agent.",
|
|
155
|
-
route: "process.stop",
|
|
156
|
-
method: "POST",
|
|
157
|
-
params: [
|
|
158
|
-
{ name: "serviceId", description: "The service ID to stop", required: true },
|
|
159
|
-
{ name: "agentId", description: "The agent ID hosting this service", required: true }
|
|
160
|
-
],
|
|
161
|
-
buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),
|
|
162
|
-
destructive: true
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
name: "restart_service",
|
|
166
|
-
description: "Restart a service on an agent (stop \u2192 redeploy \u2192 start).",
|
|
167
|
-
route: "process.restart",
|
|
168
|
-
method: "POST",
|
|
169
|
-
params: [
|
|
170
|
-
{ name: "serviceId", description: "The service ID to restart", required: true },
|
|
171
|
-
{ name: "agentId", description: "The agent ID hosting this service", required: true }
|
|
172
|
-
],
|
|
173
|
-
buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),
|
|
174
|
-
destructive: true
|
|
175
|
-
},
|
|
176
|
-
// ─── Utility ─────────────────────────────────────────────────────────────
|
|
177
|
-
{
|
|
178
|
-
name: "wait",
|
|
179
|
-
description: "Wait for a given number of milliseconds before continuing.",
|
|
180
|
-
route: "utility.wait",
|
|
181
|
-
method: "POST",
|
|
182
|
-
params: [
|
|
183
|
-
{ name: "ms", description: "Number of MILLISECONDS to wait. Convert from seconds: 1s=1000, 10s=10000, 1min=60000. Max 300000.", required: true }
|
|
184
|
-
],
|
|
185
|
-
buildInput: (p) => ({ ms: Number(p.ms) }),
|
|
186
|
-
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.'
|
|
187
|
-
},
|
|
188
|
-
// ─── Kanban ───────────────────────────────────────────────────────────────
|
|
189
|
-
{
|
|
190
|
-
name: "kanban_list_boards",
|
|
191
|
-
description: "List the kanban boards of the organization. Returns the organizationId actually queried, 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. An empty list means that organization really has no board: a failure to reach the cloud is reported as an error instead, never as an empty list.",
|
|
192
|
-
route: "kanban.listBoards",
|
|
193
|
-
method: "GET",
|
|
194
|
-
params: [
|
|
195
|
-
{ name: "includeArchived", description: 'Set to "true" to include archived boards. Default: false.', required: false },
|
|
196
|
-
{ name: "organizationId", description: "Which organization to read. Optional: needed only when the account belongs to several and the error message asks for it.", required: false }
|
|
197
|
-
],
|
|
198
|
-
buildInput: (p) => ({
|
|
199
|
-
includeArchived: p.includeArchived === "true",
|
|
200
|
-
...p.organizationId ? { organizationId: p.organizationId } : {}
|
|
201
|
-
})
|
|
202
|
-
},
|
|
203
|
-
{
|
|
204
|
-
name: "kanban_get_board",
|
|
205
|
-
description: "Read one kanban board: its columns, and the cards in each (id, title, markdown body, assignees, comment count, and attachment metadata \u2014 use kanban_download_attachment to fetch the bytes of a file). Use the exact column names it returns when moving or adding a card.",
|
|
206
|
-
route: "kanban.getBoard",
|
|
207
|
-
method: "GET",
|
|
208
|
-
params: [
|
|
209
|
-
{ name: "boardId", description: "The kanban board ID, from kanban_list_boards", required: true }
|
|
210
|
-
],
|
|
211
|
-
buildInput: (p) => ({ boardId: p.boardId })
|
|
212
|
-
},
|
|
213
|
-
{
|
|
214
|
-
name: "kanban_get_card_comments",
|
|
215
|
-
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 \u2014 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.",
|
|
216
|
-
route: "kanban.getCardComments",
|
|
217
|
-
method: "GET",
|
|
218
|
-
params: [
|
|
219
|
-
{ name: "boardId", description: "The kanban board ID", required: true },
|
|
220
|
-
{ name: "cardId", description: "The card ID whose comments to read", required: true },
|
|
221
|
-
{ name: "limit", description: "How many of the most recent comments to return (1-200). Default: 50.", required: false }
|
|
222
|
-
],
|
|
223
|
-
buildInput: (p) => ({
|
|
224
|
-
boardId: p.boardId,
|
|
225
|
-
cardId: p.cardId,
|
|
226
|
-
...p.limit ? { limit: Number(p.limit) } : {}
|
|
227
|
-
}),
|
|
228
|
-
usageHint: '"le support a ajout\xE9 un commentaire" / "regarde les nouveaux commentaires" \u2192 kanban_get_card_comments(boardId, cardId). Never answer from the snapshot in your context when fresh comments are mentioned.'
|
|
229
|
-
},
|
|
230
|
-
{
|
|
231
|
-
name: "kanban_search_cards",
|
|
232
|
-
description: "Search kanban cards by free text, matched against their title, body and comments (accent- and case-insensitive). Archived cards are included. Searches every board of the organization unless boardId narrows it down.",
|
|
233
|
-
route: "kanban.searchCards",
|
|
234
|
-
method: "GET",
|
|
235
|
-
params: [
|
|
236
|
-
{ name: "query", description: "Text to look for in card titles, bodies and comments", required: true },
|
|
237
|
-
{ name: "boardId", description: "Restrict the search to this board. Omit to search all boards.", required: false },
|
|
238
|
-
{ name: "limit", description: "Maximum number of cards to return (1-100). Default: 25.", required: false },
|
|
239
|
-
{ name: "organizationId", description: "Which organization to search. Optional: needed only when the account belongs to several and the error message asks for it.", required: false }
|
|
240
|
-
],
|
|
241
|
-
buildInput: (p) => ({
|
|
242
|
-
query: p.query,
|
|
243
|
-
...p.boardId ? { boardId: p.boardId } : {},
|
|
244
|
-
...p.limit ? { limit: Number(p.limit) } : {},
|
|
245
|
-
...p.organizationId ? { organizationId: p.organizationId } : {}
|
|
246
|
-
})
|
|
247
|
-
},
|
|
248
|
-
{
|
|
249
|
-
name: "kanban_download_attachment",
|
|
250
|
-
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 \u2014 a file attached to a comment downloads exactly like one attached to the card.",
|
|
251
|
-
route: "kanban.downloadAttachment",
|
|
252
|
-
method: "POST",
|
|
253
|
-
params: [
|
|
254
|
-
{ name: "attachmentId", description: "The attachment ID, as listed on the card", required: true }
|
|
255
|
-
],
|
|
256
|
-
buildInput: (p) => ({ attachmentId: p.attachmentId })
|
|
257
|
-
},
|
|
258
|
-
{
|
|
259
|
-
name: "kanban_move_card",
|
|
260
|
-
description: "Move a kanban card to another column. Use the exact column name.",
|
|
261
|
-
route: "kanban.moveCard",
|
|
262
|
-
method: "POST",
|
|
263
|
-
params: [
|
|
264
|
-
{ name: "boardId", description: "The kanban board ID", required: true },
|
|
265
|
-
{ name: "cardId", description: "The card ID to move", required: true },
|
|
266
|
-
{ name: "targetColumn", description: "Exact name of the target column", required: true }
|
|
267
|
-
],
|
|
268
|
-
buildInput: (p) => ({ boardId: p.boardId, cardId: p.cardId, targetColumn: p.targetColumn })
|
|
269
|
-
},
|
|
270
|
-
{
|
|
271
|
-
name: "kanban_add_comment",
|
|
272
|
-
description: "Add a comment to a kanban card.",
|
|
273
|
-
route: "kanban.addComment",
|
|
274
|
-
method: "POST",
|
|
275
|
-
params: [
|
|
276
|
-
{ name: "boardId", description: "The kanban board ID", required: true },
|
|
277
|
-
{ name: "cardId", description: "The card ID", required: true },
|
|
278
|
-
{ name: "comment", description: "The comment text (markdown supported)", required: true }
|
|
279
|
-
],
|
|
280
|
-
buildInput: (p) => ({ boardId: p.boardId, cardId: p.cardId, comment: p.comment })
|
|
281
|
-
},
|
|
282
|
-
{
|
|
283
|
-
name: "kanban_get_card_links",
|
|
284
|
-
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.",
|
|
285
|
-
route: "kanban.getCardLinks",
|
|
286
|
-
method: "GET",
|
|
287
|
-
params: [
|
|
288
|
-
{ name: "boardId", description: "The kanban board ID whose links to read", required: true }
|
|
289
|
-
],
|
|
290
|
-
buildInput: (p) => ({ boardId: p.boardId })
|
|
291
|
-
},
|
|
292
|
-
{
|
|
293
|
-
name: "kanban_set_card_parent",
|
|
294
|
-
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.",
|
|
295
|
-
route: "kanban.setCardParent",
|
|
296
|
-
method: "POST",
|
|
297
|
-
params: [
|
|
298
|
-
{ name: "boardId", description: "The kanban board ID of the card being linked", required: true },
|
|
299
|
-
{ name: "cardId", description: "The card that depends on the parent (the child)", required: true },
|
|
300
|
-
{ name: "parentCardId", description: "The parent card ID. Omit to detach the card from its parent.", required: false },
|
|
301
|
-
{ name: "parentBoardId", description: "The parent's board, when it lives on another board of the same organization. Defaults to boardId.", required: false }
|
|
302
|
-
],
|
|
303
|
-
buildInput: (p) => ({
|
|
304
|
-
boardId: p.boardId,
|
|
305
|
-
cardId: p.cardId,
|
|
306
|
-
...p.parentCardId ? { parentCardId: p.parentCardId } : {},
|
|
307
|
-
...p.parentBoardId ? { parentBoardId: p.parentBoardId } : {}
|
|
308
|
-
})
|
|
309
|
-
},
|
|
310
|
-
{
|
|
311
|
-
name: "kanban_add_card",
|
|
312
|
-
description: "Add a new card to a kanban column.",
|
|
313
|
-
route: "kanban.addCard",
|
|
314
|
-
method: "POST",
|
|
315
|
-
params: [
|
|
316
|
-
{ name: "boardId", description: "The kanban board ID", required: true },
|
|
317
|
-
{ name: "column", description: "Exact name of the target column", required: true },
|
|
318
|
-
{ name: "title", description: "Card title", required: true },
|
|
319
|
-
{ name: "content", description: "Card content in markdown", required: false }
|
|
320
|
-
],
|
|
321
|
-
buildInput: (p) => ({ boardId: p.boardId, column: p.column, title: p.title, content: p.content })
|
|
322
|
-
},
|
|
323
|
-
{
|
|
324
|
-
name: "kanban_get_card",
|
|
325
|
-
description: "Read one kanban card by id, including archived ones. Cheaper than fetching the whole board, and the only way to read a card that has been archived.",
|
|
326
|
-
route: "kanban.getCard",
|
|
327
|
-
method: "GET",
|
|
328
|
-
params: [
|
|
329
|
-
{ name: "boardId", description: "The kanban board ID", required: true },
|
|
330
|
-
{ name: "cardId", description: "The card ID", required: true }
|
|
331
|
-
],
|
|
332
|
-
buildInput: (p) => ({ boardId: p.boardId, cardId: p.cardId })
|
|
333
|
-
},
|
|
334
|
-
{
|
|
335
|
-
name: "kanban_update_card",
|
|
336
|
-
description: "Update an existing kanban card. Only the fields you pass are changed; passing null to priority, color or deadline clears it. Prefer this over creating a second card when something needs correcting.",
|
|
337
|
-
route: "kanban.updateCard",
|
|
338
|
-
method: "POST",
|
|
339
|
-
params: [
|
|
340
|
-
{ name: "boardId", description: "The kanban board ID", required: true },
|
|
341
|
-
{ name: "cardId", description: "The card ID", required: true },
|
|
342
|
-
{ name: "title", description: "New title", required: false },
|
|
343
|
-
{ name: "content", description: "New card content, in markdown", required: false },
|
|
344
|
-
{ name: "priority", description: "Priority from 1 to 10, or null to clear it", required: false },
|
|
345
|
-
{ name: "color", description: "Card colour, or null to clear it", required: false },
|
|
346
|
-
{ name: "groups", description: "Labels, as a list of strings. Replaces the current ones.", required: false },
|
|
347
|
-
{ name: "deadline", description: "Due date as YYYY-MM-DD, or null to clear it", required: false },
|
|
348
|
-
{ name: "assignees", description: "User ids to assign, as a list. Replaces the current ones; use kanban_list_members to find the ids.", required: false }
|
|
349
|
-
],
|
|
350
|
-
buildInput: (p) => ({
|
|
351
|
-
boardId: p.boardId,
|
|
352
|
-
cardId: p.cardId,
|
|
353
|
-
...p.title !== void 0 ? { title: p.title } : {},
|
|
354
|
-
...p.content !== void 0 ? { content: p.content } : {},
|
|
355
|
-
// Tout arrive en chaîne : un modèle n'écrit pas des nombres, des listes
|
|
356
|
-
// ni des `null` typés. `clearable` distingue « efface » de « ne touche
|
|
357
|
-
// pas » — sans quoi vider une couleur serait impossible à exprimer, et
|
|
358
|
-
// changer un titre risquerait de vider le reste.
|
|
359
|
-
...clearable(p.priority, (v) => Number(v), "priority"),
|
|
360
|
-
...clearable(p.color, (v) => v, "color"),
|
|
361
|
-
...clearable(p.deadline, (v) => v, "deadline"),
|
|
362
|
-
...p.groups !== void 0 ? { groups: toList(p.groups) } : {},
|
|
363
|
-
...p.assignees !== void 0 ? { assignees: toList(p.assignees) } : {}
|
|
364
|
-
})
|
|
365
|
-
},
|
|
366
|
-
{
|
|
367
|
-
name: "kanban_set_card_archived",
|
|
368
|
-
description: "Archive a kanban card (it leaves the board but is not deleted) or bring it back. An unarchived card returns to the column it left.",
|
|
369
|
-
route: "kanban.setCardArchived",
|
|
370
|
-
method: "POST",
|
|
371
|
-
params: [
|
|
372
|
-
{ name: "boardId", description: "The kanban board ID", required: true },
|
|
373
|
-
{ name: "cardId", description: "The card ID", required: true },
|
|
374
|
-
{ name: "archived", description: "true to archive, false to bring the card back", required: true }
|
|
375
|
-
],
|
|
376
|
-
buildInput: (p) => ({ boardId: p.boardId, cardId: p.cardId, archived: p.archived === "true" })
|
|
377
|
-
},
|
|
378
|
-
{
|
|
379
|
-
name: "kanban_list_members",
|
|
380
|
-
description: "List the people of the organization who can be assigned to a card, with their ids. Needed before assigning anyone with kanban_update_card.",
|
|
381
|
-
route: "kanban.listMembers",
|
|
382
|
-
method: "GET",
|
|
383
|
-
params: [
|
|
384
|
-
{ name: "organizationId", description: "Which organization. Optional: needed only when the account belongs to several and the error message asks for it.", required: false }
|
|
385
|
-
],
|
|
386
|
-
buildInput: (p) => p.organizationId ? { organizationId: p.organizationId } : {}
|
|
387
|
-
}
|
|
388
|
-
];
|
|
389
|
-
|
|
390
|
-
// ../../packages/ai-capabilities/src/adapters/anthropic.ts
|
|
391
|
-
function buildAnthropicTools(capabilities) {
|
|
392
|
-
return capabilities.map((cap) => ({
|
|
393
|
-
name: cap.name,
|
|
394
|
-
description: cap.description,
|
|
395
|
-
input_schema: {
|
|
396
|
-
type: "object",
|
|
397
|
-
properties: Object.fromEntries(
|
|
398
|
-
cap.params.map((p) => [p.name, { type: "string", description: p.description }])
|
|
399
|
-
),
|
|
400
|
-
required: cap.params.filter((p) => p.required).map((p) => p.name)
|
|
401
|
-
}
|
|
402
|
-
}));
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
// ../../packages/ai-capabilities/src/adapters/openai.ts
|
|
406
|
-
function buildOpenAITools(capabilities) {
|
|
407
|
-
return capabilities.map((cap) => ({
|
|
408
|
-
type: "function",
|
|
409
|
-
function: {
|
|
410
|
-
name: cap.name,
|
|
411
|
-
description: cap.description,
|
|
412
|
-
parameters: {
|
|
413
|
-
type: "object",
|
|
414
|
-
properties: Object.fromEntries(
|
|
415
|
-
cap.params.map((p) => [p.name, { type: "string", description: p.description }])
|
|
416
|
-
),
|
|
417
|
-
required: cap.params.filter((p) => p.required).map((p) => p.name)
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
}));
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
// ../../packages/ai-capabilities/src/adapters/prompt.ts
|
|
424
|
-
function buildToolSafetyInstruction(capabilities) {
|
|
425
|
-
const destructive = capabilities.filter((c) => c.destructive).map((c) => c.name);
|
|
426
|
-
const withHints = capabilities.filter((c) => c.usageHint);
|
|
427
|
-
const lines = ["## Tool use safety rules"];
|
|
428
|
-
if (destructive.length > 0) {
|
|
429
|
-
lines.push(`CRITICAL: Never call ${destructive.join(", ")} unless the user has EXPLICITLY and UNAMBIGUOUSLY requested it.`);
|
|
430
|
-
lines.push(`- Only call destructive tools (${destructive.join(", ")}) when the user explicitly uses action words for a specific service.`);
|
|
431
|
-
}
|
|
432
|
-
if (withHints.length > 0) {
|
|
433
|
-
lines.push("");
|
|
434
|
-
lines.push("## Tool usage hints");
|
|
435
|
-
for (const cap of withHints) {
|
|
436
|
-
lines.push(`- ${cap.usageHint}`);
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
return lines.join("\n");
|
|
440
|
-
}
|
|
441
|
-
function buildPromptDocs(baseUrl, token, capabilities) {
|
|
442
|
-
if (!token) return "";
|
|
443
|
-
const lines = [
|
|
444
|
-
"## Runeya API",
|
|
445
|
-
"",
|
|
446
|
-
`Tu peux interagir avec Runeya via l'API HTTP tRPC ci-dessous.`,
|
|
447
|
-
`Base URL : ${baseUrl}/api/trpc`,
|
|
448
|
-
"Auth header : Authorization: Bearer $RUNEYA_API_TOKEN",
|
|
449
|
-
""
|
|
450
|
-
];
|
|
451
|
-
const gets = capabilities.filter((c) => c.method === "GET");
|
|
452
|
-
const posts = capabilities.filter((c) => c.method === "POST");
|
|
453
|
-
if (gets.length > 0) {
|
|
454
|
-
lines.push("### GET routes (param\xE8tres en query string ?input=<JSON encod\xE9>)", "");
|
|
455
|
-
for (const cap of gets) {
|
|
456
|
-
const example = cap.params.length > 0 ? `?input=${JSON.stringify(Object.fromEntries(cap.params.map((p) => [p.name === "serviceId" ? "id" : p.name, "..."])))}` : "";
|
|
457
|
-
lines.push(`- \`${cap.route}${example}\` \u2014 ${cap.description}`);
|
|
458
|
-
}
|
|
459
|
-
lines.push("");
|
|
460
|
-
}
|
|
461
|
-
if (posts.length > 0) {
|
|
462
|
-
lines.push("### POST routes (body JSON)", "");
|
|
463
|
-
for (const cap of posts) {
|
|
464
|
-
const bodyExample = cap.params.length > 0 ? JSON.stringify(Object.fromEntries(cap.params.map((p) => [p.name === "serviceId" ? "processId" : p.name, "..."]))) : "{}";
|
|
465
|
-
lines.push(`- \`${cap.route}\` \u2014 \`${bodyExample}\``);
|
|
466
|
-
}
|
|
467
|
-
lines.push("");
|
|
468
|
-
}
|
|
469
|
-
const hints = capabilities.filter((c) => c.usageHint);
|
|
470
|
-
if (hints.length > 0) {
|
|
471
|
-
lines.push("### Usage hints", "");
|
|
472
|
-
for (const cap of hints) {
|
|
473
|
-
lines.push(`- ${cap.usageHint}`);
|
|
474
|
-
}
|
|
475
|
-
lines.push("");
|
|
476
|
-
}
|
|
477
|
-
lines.push(
|
|
478
|
-
"### Exemple curl",
|
|
479
|
-
"",
|
|
480
|
-
"```bash",
|
|
481
|
-
`curl -H "Authorization: Bearer $RUNEYA_API_TOKEN" \\`,
|
|
482
|
-
` "${baseUrl}/api/trpc/service.list"`,
|
|
483
|
-
"",
|
|
484
|
-
`curl -X POST -H "Authorization: Bearer $RUNEYA_API_TOKEN" \\`,
|
|
485
|
-
' -H "Content-Type: application/json" \\',
|
|
486
|
-
` -d '{"agentId":"local","processId":"my-service"}' \\`,
|
|
487
|
-
` "${baseUrl}/api/trpc/process.start"`,
|
|
488
|
-
"```",
|
|
489
|
-
"",
|
|
490
|
-
'La r\xE9ponse est de la forme `{"result":{"data":<r\xE9sultat>}}`.'
|
|
491
|
-
);
|
|
492
|
-
return lines.join("\n");
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
// ../../packages/ai-capabilities/src/trpc-caller.ts
|
|
496
|
-
async function callTrpc(baseUrl, route, method, input, authToken) {
|
|
497
|
-
const headers = {
|
|
498
|
-
"Content-Type": "application/json",
|
|
499
|
-
"Authorization": `Bearer ${authToken}`
|
|
500
|
-
};
|
|
501
|
-
const url = method === "GET" && input ? `${baseUrl}/api/trpc/${route}?input=${encodeURIComponent(JSON.stringify(input))}` : `${baseUrl}/api/trpc/${route}`;
|
|
502
|
-
const res = await fetch(url, {
|
|
503
|
-
method,
|
|
504
|
-
headers,
|
|
505
|
-
...method === "POST" ? { body: JSON.stringify(input ?? {}) } : {},
|
|
506
|
-
signal: AbortSignal.timeout(15e3)
|
|
507
|
-
});
|
|
508
|
-
const json = await res.json();
|
|
509
|
-
if (json["error"]) throw new Error(JSON.stringify(json["error"]));
|
|
510
|
-
const result = json["result"];
|
|
511
|
-
return result?.["data"] ?? result ?? json;
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
// ../server/src/services/ai-runners/runeya-api-docs.ts
|
|
515
|
-
function buildApiDocs(apiBaseUrl, apiToken) {
|
|
516
|
-
return buildPromptDocs(apiBaseUrl, apiToken, RUNEYA_CAPABILITIES);
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
// ../server/src/services/codex-sessions.ts
|
|
520
|
-
import { readdir } from "fs/promises";
|
|
521
|
-
import { homedir } from "os";
|
|
522
|
-
import { join } from "path";
|
|
523
|
-
var CODEX_SESSIONS_DIR = join(homedir(), ".codex", "sessions");
|
|
524
|
-
async function findCodexSessionFile(sessionId) {
|
|
525
|
-
const suffix = `-${sessionId}.jsonl`;
|
|
526
|
-
async function walk(dir) {
|
|
527
|
-
let entries;
|
|
528
|
-
try {
|
|
529
|
-
entries = await readdir(dir, { withFileTypes: true });
|
|
530
|
-
} catch {
|
|
531
|
-
return null;
|
|
532
|
-
}
|
|
533
|
-
for (const entry of entries) {
|
|
534
|
-
const full = join(dir, entry.name);
|
|
535
|
-
if (entry.isDirectory()) {
|
|
536
|
-
const found = await walk(full);
|
|
537
|
-
if (found) return found;
|
|
538
|
-
} else if (entry.name.endsWith(suffix)) {
|
|
539
|
-
return full;
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
return null;
|
|
183
|
+
async function resolveCodexResumeId(sessionId, codexThreadId) {
|
|
184
|
+
for (const candidate of [codexThreadId, sessionId]) {
|
|
185
|
+
if (candidate && await codexSessionExists(candidate)) return candidate;
|
|
543
186
|
}
|
|
544
|
-
return
|
|
545
|
-
}
|
|
546
|
-
async function codexSessionExists(sessionId) {
|
|
547
|
-
const { threadExists } = await import("./codex-thread-db-LE5FYDDA.js");
|
|
548
|
-
if (threadExists(sessionId)) return true;
|
|
549
|
-
return await findCodexSessionFile(sessionId) !== null;
|
|
187
|
+
return null;
|
|
550
188
|
}
|
|
551
189
|
|
|
552
190
|
// ../server/src/trpc/routers/chat.ts
|
|
@@ -1386,112 +1024,752 @@ var EnvironmentResolver = class {
|
|
|
1386
1024
|
}
|
|
1387
1025
|
return byKey;
|
|
1388
1026
|
}
|
|
1389
|
-
async resolveDag(environmentId, visited, project) {
|
|
1390
|
-
if (visited.has(environmentId)) {
|
|
1391
|
-
throw new Error(`Circular dependency detected in environment inheritance for ${environmentId}`);
|
|
1392
|
-
}
|
|
1393
|
-
const environment = await environmentStore.get(environmentId);
|
|
1394
|
-
if (!environment) {
|
|
1395
|
-
throw new Error(`Environment "${environmentId}" not found`);
|
|
1396
|
-
}
|
|
1397
|
-
visited.add(environmentId);
|
|
1398
|
-
const effectiveParentIds = await this.getEffectiveParentIds(environment);
|
|
1399
|
-
const parentResults = [];
|
|
1400
|
-
for (const parentId of effectiveParentIds) {
|
|
1401
|
-
const parentVisited = new Set(visited);
|
|
1402
|
-
const parentResult = await this.resolveDag(parentId, parentVisited, project);
|
|
1403
|
-
parentResults.push(parentResult);
|
|
1404
|
-
}
|
|
1405
|
-
const mergedVariables = {};
|
|
1406
|
-
const sources = {};
|
|
1407
|
-
for (const result of parentResults) {
|
|
1408
|
-
for (const [varId, variable] of Object.entries(result.variables)) {
|
|
1409
|
-
for (const [existingId, existingVar] of Object.entries(mergedVariables)) {
|
|
1410
|
-
if (existingVar.key === variable.key && existingId !== varId) {
|
|
1411
|
-
delete mergedVariables[existingId];
|
|
1412
|
-
delete sources[existingId];
|
|
1413
|
-
}
|
|
1414
|
-
}
|
|
1415
|
-
mergedVariables[varId] = variable;
|
|
1416
|
-
sources[varId] = result.sources[varId] ?? sources[varId];
|
|
1417
|
-
}
|
|
1418
|
-
}
|
|
1419
|
-
const parentEnv = {};
|
|
1420
|
-
const parentSecretKeys = /* @__PURE__ */ new Set();
|
|
1421
|
-
const parentKeySources = {};
|
|
1422
|
-
for (const [varId, variable] of Object.entries(mergedVariables)) {
|
|
1423
|
-
const slot = variable.value;
|
|
1424
|
-
parentEnv[variable.key] = slot.pre + slot.value + slot.post;
|
|
1425
|
-
if (slot.isSecret) {
|
|
1426
|
-
parentSecretKeys.add(variable.key);
|
|
1427
|
-
}
|
|
1428
|
-
const source = sources[varId];
|
|
1429
|
-
if (source) {
|
|
1430
|
-
parentKeySources[variable.key] = { environmentId: source.environmentId, environmentName: source.environmentName };
|
|
1431
|
-
}
|
|
1027
|
+
async resolveDag(environmentId, visited, project) {
|
|
1028
|
+
if (visited.has(environmentId)) {
|
|
1029
|
+
throw new Error(`Circular dependency detected in environment inheritance for ${environmentId}`);
|
|
1030
|
+
}
|
|
1031
|
+
const environment = await environmentStore.get(environmentId);
|
|
1032
|
+
if (!environment) {
|
|
1033
|
+
throw new Error(`Environment "${environmentId}" not found`);
|
|
1034
|
+
}
|
|
1035
|
+
visited.add(environmentId);
|
|
1036
|
+
const effectiveParentIds = await this.getEffectiveParentIds(environment);
|
|
1037
|
+
const parentResults = [];
|
|
1038
|
+
for (const parentId of effectiveParentIds) {
|
|
1039
|
+
const parentVisited = new Set(visited);
|
|
1040
|
+
const parentResult = await this.resolveDag(parentId, parentVisited, project);
|
|
1041
|
+
parentResults.push(parentResult);
|
|
1042
|
+
}
|
|
1043
|
+
const mergedVariables = {};
|
|
1044
|
+
const sources = {};
|
|
1045
|
+
for (const result of parentResults) {
|
|
1046
|
+
for (const [varId, variable] of Object.entries(result.variables)) {
|
|
1047
|
+
for (const [existingId, existingVar] of Object.entries(mergedVariables)) {
|
|
1048
|
+
if (existingVar.key === variable.key && existingId !== varId) {
|
|
1049
|
+
delete mergedVariables[existingId];
|
|
1050
|
+
delete sources[existingId];
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
mergedVariables[varId] = variable;
|
|
1054
|
+
sources[varId] = result.sources[varId] ?? sources[varId];
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
const parentEnv = {};
|
|
1058
|
+
const parentSecretKeys = /* @__PURE__ */ new Set();
|
|
1059
|
+
const parentKeySources = {};
|
|
1060
|
+
for (const [varId, variable] of Object.entries(mergedVariables)) {
|
|
1061
|
+
const slot = variable.value;
|
|
1062
|
+
parentEnv[variable.key] = slot.pre + slot.value + slot.post;
|
|
1063
|
+
if (slot.isSecret) {
|
|
1064
|
+
parentSecretKeys.add(variable.key);
|
|
1065
|
+
}
|
|
1066
|
+
const source = sources[varId];
|
|
1067
|
+
if (source) {
|
|
1068
|
+
parentKeySources[variable.key] = { environmentId: source.environmentId, environmentName: source.environmentName };
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
const isInterpRef = (v) => /\{\{environment\.[^}]+\}\}/.test(v);
|
|
1072
|
+
for (const result of parentResults) {
|
|
1073
|
+
for (const [key, value] of Object.entries(result.parentEnv)) {
|
|
1074
|
+
const existingIsRef = key in parentEnv && isInterpRef(parentEnv[key]);
|
|
1075
|
+
const newIsConcrete = !isInterpRef(value);
|
|
1076
|
+
if (!(key in parentEnv) || existingIsRef && newIsConcrete) {
|
|
1077
|
+
parentEnv[key] = value;
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
for (const key of result.parentSecretKeys) {
|
|
1081
|
+
parentSecretKeys.add(key);
|
|
1082
|
+
}
|
|
1083
|
+
for (const [key, source] of Object.entries(result.parentKeySources)) {
|
|
1084
|
+
if (!(key in parentKeySources)) {
|
|
1085
|
+
parentKeySources[key] = source;
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
for (const key of this.collectSecretKeys(mergedVariables, parentSecretKeys)) {
|
|
1090
|
+
parentSecretKeys.add(key);
|
|
1091
|
+
}
|
|
1092
|
+
const ownVariables = project ? project(environment.variables) : environment.variables;
|
|
1093
|
+
for (const [varId, variable] of Object.entries(ownVariables)) {
|
|
1094
|
+
let wasInherited = varId in mergedVariables;
|
|
1095
|
+
for (const [existingId, existingVar] of Object.entries(mergedVariables)) {
|
|
1096
|
+
if (existingVar.key === variable.key && existingId !== varId) {
|
|
1097
|
+
delete mergedVariables[existingId];
|
|
1098
|
+
delete sources[existingId];
|
|
1099
|
+
wasInherited = true;
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
mergedVariables[varId] = variable;
|
|
1103
|
+
sources[varId] = {
|
|
1104
|
+
environmentId: environment.id,
|
|
1105
|
+
environmentName: environment.name,
|
|
1106
|
+
overridden: wasInherited
|
|
1107
|
+
};
|
|
1108
|
+
}
|
|
1109
|
+
return {
|
|
1110
|
+
variables: mergedVariables,
|
|
1111
|
+
sources,
|
|
1112
|
+
parentEnv,
|
|
1113
|
+
parentSecretKeys,
|
|
1114
|
+
parentKeySources
|
|
1115
|
+
};
|
|
1116
|
+
}
|
|
1117
|
+
};
|
|
1118
|
+
var environmentResolver = new EnvironmentResolver();
|
|
1119
|
+
|
|
1120
|
+
// ../../packages/ai-capabilities/src/capabilities.ts
|
|
1121
|
+
function toList(raw) {
|
|
1122
|
+
if (!raw) return [];
|
|
1123
|
+
const text = raw.trim();
|
|
1124
|
+
if (text.startsWith("[")) {
|
|
1125
|
+
try {
|
|
1126
|
+
const parsed = JSON.parse(text);
|
|
1127
|
+
if (Array.isArray(parsed)) return parsed.map((v) => String(v).trim()).filter(Boolean);
|
|
1128
|
+
} catch {
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
return text.split(",").map((v) => v.trim().replace(/^["'[]+|["'\]]+$/g, "")).filter(Boolean);
|
|
1132
|
+
}
|
|
1133
|
+
function clearable(raw, parse2, key) {
|
|
1134
|
+
if (raw === void 0) return {};
|
|
1135
|
+
const text = String(raw).trim();
|
|
1136
|
+
if (!text || text === "null") return { [key]: null };
|
|
1137
|
+
return { [key]: parse2(text) };
|
|
1138
|
+
}
|
|
1139
|
+
function gitTarget(p) {
|
|
1140
|
+
return {
|
|
1141
|
+
...p.serviceId ? { serviceId: p.serviceId } : {},
|
|
1142
|
+
...p.projectId ? { projectId: p.projectId } : {},
|
|
1143
|
+
...p.agentId ? { agentId: p.agentId } : {},
|
|
1144
|
+
...p.orgId ? { orgId: p.orgId } : {}
|
|
1145
|
+
};
|
|
1146
|
+
}
|
|
1147
|
+
var RUNEYA_CAPABILITIES = [
|
|
1148
|
+
{
|
|
1149
|
+
name: "list_services",
|
|
1150
|
+
description: "List services, with the serviceId and agentId to use in other calls. Pass the projectId your context names to stay on the project the user is looking at, or another one from list_projects to look elsewhere. Called with no project, this can answer for every project of every organization on the machine \u2014 far more than the interface shows.",
|
|
1151
|
+
route: "service.list",
|
|
1152
|
+
method: "GET",
|
|
1153
|
+
params: [
|
|
1154
|
+
{ name: "projectId", description: "Restrict to this project, from list_projects. Omit to list every service on the machine.", required: false },
|
|
1155
|
+
{ name: "orgId", description: "Its organization. Needed only when the same project id exists in several.", required: false }
|
|
1156
|
+
],
|
|
1157
|
+
buildInput: (p) => p.projectId ? { projectId: p.projectId, ...p.orgId ? { orgId: p.orgId } : {} } : void 0
|
|
1158
|
+
},
|
|
1159
|
+
{
|
|
1160
|
+
name: "get_service_status",
|
|
1161
|
+
description: "Get the current status (running, stopped, etc.) of a service. A service that has never been started on this agent has no process yet, and this answers 404 Process not found \u2014 that means STOPPED, not forbidden and not missing. Start it, or read its configuration with get_service.",
|
|
1162
|
+
route: "process.get",
|
|
1163
|
+
method: "GET",
|
|
1164
|
+
params: [
|
|
1165
|
+
{ name: "serviceId", description: "The service ID", required: true },
|
|
1166
|
+
{ name: "agentId", description: "The agent ID hosting this service", required: true }
|
|
1167
|
+
],
|
|
1168
|
+
buildInput: (p) => ({ agentId: p.agentId, id: p.serviceId })
|
|
1169
|
+
},
|
|
1170
|
+
{
|
|
1171
|
+
name: "get_logs",
|
|
1172
|
+
description: "Get the recent buffered logs for a service.",
|
|
1173
|
+
route: "process.logs",
|
|
1174
|
+
method: "GET",
|
|
1175
|
+
params: [
|
|
1176
|
+
{ name: "serviceId", description: "The service ID", required: true },
|
|
1177
|
+
{ name: "agentId", description: "The agent ID hosting this service", required: true }
|
|
1178
|
+
],
|
|
1179
|
+
buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId })
|
|
1180
|
+
},
|
|
1181
|
+
{
|
|
1182
|
+
name: "start_service",
|
|
1183
|
+
description: "Start a service on an agent.",
|
|
1184
|
+
route: "process.start",
|
|
1185
|
+
method: "POST",
|
|
1186
|
+
params: [
|
|
1187
|
+
{ name: "serviceId", description: "The service ID to start", required: true },
|
|
1188
|
+
{ name: "agentId", description: "The agent ID hosting this service", required: true }
|
|
1189
|
+
],
|
|
1190
|
+
buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),
|
|
1191
|
+
destructive: true
|
|
1192
|
+
},
|
|
1193
|
+
{
|
|
1194
|
+
name: "stop_service",
|
|
1195
|
+
description: "Stop a running service on an agent.",
|
|
1196
|
+
route: "process.stop",
|
|
1197
|
+
method: "POST",
|
|
1198
|
+
params: [
|
|
1199
|
+
{ name: "serviceId", description: "The service ID to stop", required: true },
|
|
1200
|
+
{ name: "agentId", description: "The agent ID hosting this service", required: true }
|
|
1201
|
+
],
|
|
1202
|
+
buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),
|
|
1203
|
+
destructive: true
|
|
1204
|
+
},
|
|
1205
|
+
{
|
|
1206
|
+
name: "restart_service",
|
|
1207
|
+
description: "Restart a service on an agent (stop \u2192 redeploy \u2192 start).",
|
|
1208
|
+
route: "process.restart",
|
|
1209
|
+
method: "POST",
|
|
1210
|
+
params: [
|
|
1211
|
+
{ name: "serviceId", description: "The service ID to restart", required: true },
|
|
1212
|
+
{ name: "agentId", description: "The agent ID hosting this service", required: true }
|
|
1213
|
+
],
|
|
1214
|
+
buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),
|
|
1215
|
+
destructive: true
|
|
1216
|
+
},
|
|
1217
|
+
// ─── Utility ─────────────────────────────────────────────────────────────
|
|
1218
|
+
{
|
|
1219
|
+
name: "wait",
|
|
1220
|
+
description: "Wait for a given number of milliseconds before continuing.",
|
|
1221
|
+
route: "utility.wait",
|
|
1222
|
+
method: "POST",
|
|
1223
|
+
params: [
|
|
1224
|
+
{ name: "ms", description: "Number of MILLISECONDS to wait. Convert from seconds: 1s=1000, 10s=10000, 1min=60000. Max 300000.", required: true }
|
|
1225
|
+
],
|
|
1226
|
+
buildInput: (p) => ({ ms: Number(p.ms) }),
|
|
1227
|
+
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.'
|
|
1228
|
+
},
|
|
1229
|
+
// ─── Kanban ───────────────────────────────────────────────────────────────
|
|
1230
|
+
{
|
|
1231
|
+
name: "kanban_list_boards",
|
|
1232
|
+
description: "List the kanban boards of the organization. Returns the organizationId actually queried, 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. An empty list means that organization really has no board: a failure to reach the cloud is reported as an error instead, never as an empty list.",
|
|
1233
|
+
route: "kanban.listBoards",
|
|
1234
|
+
method: "GET",
|
|
1235
|
+
params: [
|
|
1236
|
+
{ name: "includeArchived", description: 'Set to "true" to include archived boards. Default: false.', required: false },
|
|
1237
|
+
{ name: "organizationId", description: "Which organization to read. Optional: needed only when the account belongs to several and the error message asks for it.", required: false }
|
|
1238
|
+
],
|
|
1239
|
+
buildInput: (p) => ({
|
|
1240
|
+
includeArchived: p.includeArchived === "true",
|
|
1241
|
+
...p.organizationId ? { organizationId: p.organizationId } : {}
|
|
1242
|
+
})
|
|
1243
|
+
},
|
|
1244
|
+
{
|
|
1245
|
+
name: "kanban_get_board",
|
|
1246
|
+
description: "Read one kanban board: its columns, and the cards in each (id, title, markdown body, assignees, comment count, and attachment metadata \u2014 use kanban_download_attachment to fetch the bytes of a file). Use the exact column names it returns when moving or adding a card.",
|
|
1247
|
+
route: "kanban.getBoard",
|
|
1248
|
+
method: "GET",
|
|
1249
|
+
params: [
|
|
1250
|
+
{ name: "boardId", description: "The kanban board ID, from kanban_list_boards", required: true }
|
|
1251
|
+
],
|
|
1252
|
+
buildInput: (p) => ({ boardId: p.boardId })
|
|
1253
|
+
},
|
|
1254
|
+
{
|
|
1255
|
+
name: "kanban_get_card_comments",
|
|
1256
|
+
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 \u2014 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.",
|
|
1257
|
+
route: "kanban.getCardComments",
|
|
1258
|
+
method: "GET",
|
|
1259
|
+
params: [
|
|
1260
|
+
{ name: "boardId", description: "The kanban board ID", required: true },
|
|
1261
|
+
{ name: "cardId", description: "The card ID whose comments to read", required: true },
|
|
1262
|
+
{ name: "limit", description: "How many of the most recent comments to return (1-200). Default: 50.", required: false }
|
|
1263
|
+
],
|
|
1264
|
+
buildInput: (p) => ({
|
|
1265
|
+
boardId: p.boardId,
|
|
1266
|
+
cardId: p.cardId,
|
|
1267
|
+
...p.limit ? { limit: Number(p.limit) } : {}
|
|
1268
|
+
}),
|
|
1269
|
+
usageHint: '"le support a ajout\xE9 un commentaire" / "regarde les nouveaux commentaires" \u2192 kanban_get_card_comments(boardId, cardId). Never answer from the snapshot in your context when fresh comments are mentioned.'
|
|
1270
|
+
},
|
|
1271
|
+
{
|
|
1272
|
+
name: "kanban_search_cards",
|
|
1273
|
+
description: "Search kanban cards by free text, matched against their title, body and comments (accent- and case-insensitive). Archived cards are included. Searches every board of the organization unless boardId narrows it down.",
|
|
1274
|
+
route: "kanban.searchCards",
|
|
1275
|
+
method: "GET",
|
|
1276
|
+
params: [
|
|
1277
|
+
{ name: "query", description: "Text to look for in card titles, bodies and comments", required: true },
|
|
1278
|
+
{ name: "boardId", description: "Restrict the search to this board. Omit to search all boards.", required: false },
|
|
1279
|
+
{ name: "limit", description: "Maximum number of cards to return (1-100). Default: 25.", required: false },
|
|
1280
|
+
{ name: "organizationId", description: "Which organization to search. Optional: needed only when the account belongs to several and the error message asks for it.", required: false }
|
|
1281
|
+
],
|
|
1282
|
+
buildInput: (p) => ({
|
|
1283
|
+
query: p.query,
|
|
1284
|
+
...p.boardId ? { boardId: p.boardId } : {},
|
|
1285
|
+
...p.limit ? { limit: Number(p.limit) } : {},
|
|
1286
|
+
...p.organizationId ? { organizationId: p.organizationId } : {}
|
|
1287
|
+
})
|
|
1288
|
+
},
|
|
1289
|
+
{
|
|
1290
|
+
name: "kanban_download_attachment",
|
|
1291
|
+
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 \u2014 a file attached to a comment downloads exactly like one attached to the card.",
|
|
1292
|
+
route: "kanban.downloadAttachment",
|
|
1293
|
+
method: "POST",
|
|
1294
|
+
params: [
|
|
1295
|
+
{ name: "attachmentId", description: "The attachment ID, as listed on the card", required: true }
|
|
1296
|
+
],
|
|
1297
|
+
buildInput: (p) => ({ attachmentId: p.attachmentId })
|
|
1298
|
+
},
|
|
1299
|
+
{
|
|
1300
|
+
name: "kanban_move_card",
|
|
1301
|
+
description: "Move a kanban card to another column. Use the exact column name.",
|
|
1302
|
+
route: "kanban.moveCard",
|
|
1303
|
+
method: "POST",
|
|
1304
|
+
params: [
|
|
1305
|
+
{ name: "boardId", description: "The kanban board ID", required: true },
|
|
1306
|
+
{ name: "cardId", description: "The card ID to move", required: true },
|
|
1307
|
+
{ name: "targetColumn", description: "Exact name of the target column", required: true }
|
|
1308
|
+
],
|
|
1309
|
+
buildInput: (p) => ({ boardId: p.boardId, cardId: p.cardId, targetColumn: p.targetColumn })
|
|
1310
|
+
},
|
|
1311
|
+
{
|
|
1312
|
+
name: "kanban_add_comment",
|
|
1313
|
+
description: "Add a comment to a kanban card.",
|
|
1314
|
+
route: "kanban.addComment",
|
|
1315
|
+
method: "POST",
|
|
1316
|
+
params: [
|
|
1317
|
+
{ name: "boardId", description: "The kanban board ID", required: true },
|
|
1318
|
+
{ name: "cardId", description: "The card ID", required: true },
|
|
1319
|
+
{ name: "comment", description: "The comment text (markdown supported)", required: true }
|
|
1320
|
+
],
|
|
1321
|
+
buildInput: (p) => ({ boardId: p.boardId, cardId: p.cardId, comment: p.comment })
|
|
1322
|
+
},
|
|
1323
|
+
{
|
|
1324
|
+
name: "kanban_get_card_links",
|
|
1325
|
+
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.",
|
|
1326
|
+
route: "kanban.getCardLinks",
|
|
1327
|
+
method: "GET",
|
|
1328
|
+
params: [
|
|
1329
|
+
{ name: "boardId", description: "The kanban board ID whose links to read", required: true }
|
|
1330
|
+
],
|
|
1331
|
+
buildInput: (p) => ({ boardId: p.boardId })
|
|
1332
|
+
},
|
|
1333
|
+
{
|
|
1334
|
+
name: "kanban_set_card_parent",
|
|
1335
|
+
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.",
|
|
1336
|
+
route: "kanban.setCardParent",
|
|
1337
|
+
method: "POST",
|
|
1338
|
+
params: [
|
|
1339
|
+
{ name: "boardId", description: "The kanban board ID of the card being linked", required: true },
|
|
1340
|
+
{ name: "cardId", description: "The card that depends on the parent (the child)", required: true },
|
|
1341
|
+
{ name: "parentCardId", description: "The parent card ID. Omit to detach the card from its parent.", required: false },
|
|
1342
|
+
{ name: "parentBoardId", description: "The parent's board, when it lives on another board of the same organization. Defaults to boardId.", required: false }
|
|
1343
|
+
],
|
|
1344
|
+
buildInput: (p) => ({
|
|
1345
|
+
boardId: p.boardId,
|
|
1346
|
+
cardId: p.cardId,
|
|
1347
|
+
...p.parentCardId ? { parentCardId: p.parentCardId } : {},
|
|
1348
|
+
...p.parentBoardId ? { parentBoardId: p.parentBoardId } : {}
|
|
1349
|
+
})
|
|
1350
|
+
},
|
|
1351
|
+
{
|
|
1352
|
+
name: "kanban_add_card",
|
|
1353
|
+
description: "Add a new card to a kanban column.",
|
|
1354
|
+
route: "kanban.addCard",
|
|
1355
|
+
method: "POST",
|
|
1356
|
+
params: [
|
|
1357
|
+
{ name: "boardId", description: "The kanban board ID", required: true },
|
|
1358
|
+
{ name: "column", description: "Exact name of the target column", required: true },
|
|
1359
|
+
{ name: "title", description: "Card title", required: true },
|
|
1360
|
+
{ name: "content", description: "Card content in markdown", required: false }
|
|
1361
|
+
],
|
|
1362
|
+
buildInput: (p) => ({ boardId: p.boardId, column: p.column, title: p.title, content: p.content })
|
|
1363
|
+
},
|
|
1364
|
+
{
|
|
1365
|
+
name: "kanban_get_card",
|
|
1366
|
+
description: "Read one kanban card by id, including archived ones. Cheaper than fetching the whole board, and the only way to read a card that has been archived.",
|
|
1367
|
+
route: "kanban.getCard",
|
|
1368
|
+
method: "GET",
|
|
1369
|
+
params: [
|
|
1370
|
+
{ name: "boardId", description: "The kanban board ID", required: true },
|
|
1371
|
+
{ name: "cardId", description: "The card ID", required: true }
|
|
1372
|
+
],
|
|
1373
|
+
buildInput: (p) => ({ boardId: p.boardId, cardId: p.cardId })
|
|
1374
|
+
},
|
|
1375
|
+
{
|
|
1376
|
+
name: "kanban_update_card",
|
|
1377
|
+
description: "Update an existing kanban card. Only the fields you pass are changed; passing null to priority, color or deadline clears it. Prefer this over creating a second card when something needs correcting.",
|
|
1378
|
+
route: "kanban.updateCard",
|
|
1379
|
+
method: "POST",
|
|
1380
|
+
params: [
|
|
1381
|
+
{ name: "boardId", description: "The kanban board ID", required: true },
|
|
1382
|
+
{ name: "cardId", description: "The card ID", required: true },
|
|
1383
|
+
{ name: "title", description: "New title", required: false },
|
|
1384
|
+
{ name: "content", description: "New card content, in markdown", required: false },
|
|
1385
|
+
{ name: "priority", description: "Priority from 1 to 10, or null to clear it", required: false },
|
|
1386
|
+
{ name: "color", description: "Card colour, or null to clear it", required: false },
|
|
1387
|
+
{ name: "groups", description: "Labels, as a list of strings. Replaces the current ones.", required: false },
|
|
1388
|
+
{ name: "deadline", description: "Due date as YYYY-MM-DD, or null to clear it", required: false },
|
|
1389
|
+
{ name: "assignees", description: "User ids to assign, as a list. Replaces the current ones; use kanban_list_members to find the ids.", required: false }
|
|
1390
|
+
],
|
|
1391
|
+
buildInput: (p) => ({
|
|
1392
|
+
boardId: p.boardId,
|
|
1393
|
+
cardId: p.cardId,
|
|
1394
|
+
...p.title !== void 0 ? { title: p.title } : {},
|
|
1395
|
+
...p.content !== void 0 ? { content: p.content } : {},
|
|
1396
|
+
// Tout arrive en chaîne : un modèle n'écrit pas des nombres, des listes
|
|
1397
|
+
// ni des `null` typés. `clearable` distingue « efface » de « ne touche
|
|
1398
|
+
// pas » — sans quoi vider une couleur serait impossible à exprimer, et
|
|
1399
|
+
// changer un titre risquerait de vider le reste.
|
|
1400
|
+
...clearable(p.priority, (v) => Number(v), "priority"),
|
|
1401
|
+
...clearable(p.color, (v) => v, "color"),
|
|
1402
|
+
...clearable(p.deadline, (v) => v, "deadline"),
|
|
1403
|
+
...p.groups !== void 0 ? { groups: toList(p.groups) } : {},
|
|
1404
|
+
...p.assignees !== void 0 ? { assignees: toList(p.assignees) } : {}
|
|
1405
|
+
})
|
|
1406
|
+
},
|
|
1407
|
+
{
|
|
1408
|
+
name: "kanban_set_card_archived",
|
|
1409
|
+
description: "Archive a kanban card (it leaves the board but is not deleted) or bring it back. An unarchived card returns to the column it left.",
|
|
1410
|
+
route: "kanban.setCardArchived",
|
|
1411
|
+
method: "POST",
|
|
1412
|
+
params: [
|
|
1413
|
+
{ name: "boardId", description: "The kanban board ID", required: true },
|
|
1414
|
+
{ name: "cardId", description: "The card ID", required: true },
|
|
1415
|
+
{ name: "archived", description: "true to archive, false to bring the card back", required: true }
|
|
1416
|
+
],
|
|
1417
|
+
buildInput: (p) => ({ boardId: p.boardId, cardId: p.cardId, archived: p.archived === "true" })
|
|
1418
|
+
},
|
|
1419
|
+
{
|
|
1420
|
+
name: "kanban_list_members",
|
|
1421
|
+
description: "List the people of the organization who can be assigned to a card, with their ids. Needed before assigning anyone with kanban_update_card.",
|
|
1422
|
+
route: "kanban.listMembers",
|
|
1423
|
+
method: "GET",
|
|
1424
|
+
params: [
|
|
1425
|
+
{ name: "organizationId", description: "Which organization. Optional: needed only when the account belongs to several and the error message asks for it.", required: false }
|
|
1426
|
+
],
|
|
1427
|
+
buildInput: (p) => p.organizationId ? { organizationId: p.organizationId } : {}
|
|
1428
|
+
},
|
|
1429
|
+
// ─── Lecture seule ───────────────────────────────────────────────────────
|
|
1430
|
+
//
|
|
1431
|
+
// Tout ce qui se consulte sans rien changer. La création, la mise à jour et
|
|
1432
|
+
// la suppression restent hors MCP : elles s'ajouteront au cas par cas.
|
|
1433
|
+
//
|
|
1434
|
+
// Volontairement absentes, et à ne pas ajouter sans y regarder à deux fois,
|
|
1435
|
+
// parce qu'elles rendent un secret : `environment.list` / `get` / `resolve` /
|
|
1436
|
+
// `resolveFlat` (un `Environment` porte ses variables, valeurs comprises),
|
|
1437
|
+
// `apiKeys.list` / `reveal`, `setup.getEncryptionKeyHex` et `getOrgKeys`
|
|
1438
|
+
// (clés de chiffrement), `settings.get` et `settings.listAIProviders` (clés
|
|
1439
|
+
// de fournisseurs d'IA — `settings.getPaths` et `getNetwork`, eux, ne
|
|
1440
|
+
// rendent que des chemins et une adresse, d'où leur présence ci-dessous),
|
|
1441
|
+
// `cloudAuth.session`, `agent.getPassthroughEnv`. Un agent n'a pas besoin de
|
|
1442
|
+
// ces valeurs pour travailler, et ce qu'il lit finit dans une transcription.
|
|
1443
|
+
{
|
|
1444
|
+
name: "list_processes",
|
|
1445
|
+
description: "List every process across all agents with its current state (running, stopped, exit code, uptime). Use this to see the whole machine at once, rather than calling get_service_status service by service. An agent only learns about a service when it is first started, so this lists what is deployed, not what is configured: an empty list means nothing has been started, not that you cannot see them \u2014 list_services shows what exists.",
|
|
1446
|
+
route: "process.list",
|
|
1447
|
+
method: "GET",
|
|
1448
|
+
params: [],
|
|
1449
|
+
buildInput: () => void 0
|
|
1450
|
+
},
|
|
1451
|
+
{
|
|
1452
|
+
name: "get_service",
|
|
1453
|
+
description: "Read the full configuration of one service: its commands, ports, groups, runner, log sources and restart policy. list_services gives the ids.",
|
|
1454
|
+
route: "service.get",
|
|
1455
|
+
method: "GET",
|
|
1456
|
+
params: [
|
|
1457
|
+
{ name: "serviceId", description: "The service ID", required: true }
|
|
1458
|
+
],
|
|
1459
|
+
buildInput: (p) => ({ id: p.serviceId })
|
|
1460
|
+
},
|
|
1461
|
+
{
|
|
1462
|
+
name: "get_service_metrics",
|
|
1463
|
+
description: "Read the CPU and memory currently used by a running service.",
|
|
1464
|
+
route: "process.metrics",
|
|
1465
|
+
method: "GET",
|
|
1466
|
+
params: [
|
|
1467
|
+
{ name: "serviceId", description: "The service ID", required: true },
|
|
1468
|
+
{ name: "agentId", description: "The agent ID hosting this service", required: true }
|
|
1469
|
+
],
|
|
1470
|
+
buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId })
|
|
1471
|
+
},
|
|
1472
|
+
{
|
|
1473
|
+
name: "list_agents",
|
|
1474
|
+
description: "List the agents connected to this Runeya, with their status and whether they run on this machine. Passphrases are never returned.",
|
|
1475
|
+
route: "agent.list",
|
|
1476
|
+
method: "GET",
|
|
1477
|
+
params: [],
|
|
1478
|
+
buildInput: () => void 0
|
|
1479
|
+
},
|
|
1480
|
+
{
|
|
1481
|
+
name: "list_projects",
|
|
1482
|
+
description: "List the projects known to this Runeya, with their ids and the services they hold.",
|
|
1483
|
+
route: "project.list",
|
|
1484
|
+
method: "GET",
|
|
1485
|
+
params: [],
|
|
1486
|
+
buildInput: () => void 0
|
|
1487
|
+
},
|
|
1488
|
+
{
|
|
1489
|
+
name: "get_project",
|
|
1490
|
+
description: "Read one project: its services, its active environment, its organization.",
|
|
1491
|
+
route: "project.get",
|
|
1492
|
+
method: "GET",
|
|
1493
|
+
params: [
|
|
1494
|
+
{ name: "projectId", description: "The project ID, from list_projects", required: true },
|
|
1495
|
+
{ name: "orgId", description: "Its organization. Needed only when the same project id exists in several.", required: false }
|
|
1496
|
+
],
|
|
1497
|
+
buildInput: (p) => ({ id: p.projectId, ...p.orgId ? { orgId: p.orgId } : {} })
|
|
1498
|
+
},
|
|
1499
|
+
{
|
|
1500
|
+
name: "list_project_paths",
|
|
1501
|
+
description: "Where each project lives on this machine. Use it to find the directory to work in before reading or editing files.",
|
|
1502
|
+
route: "project.localPaths",
|
|
1503
|
+
method: "GET",
|
|
1504
|
+
params: [],
|
|
1505
|
+
buildInput: () => void 0
|
|
1506
|
+
},
|
|
1507
|
+
{
|
|
1508
|
+
name: "git_status",
|
|
1509
|
+
description: "Read the git working tree of a service or a project: staged, modified and untracked files, current branch, ahead/behind counts.",
|
|
1510
|
+
route: "git.status",
|
|
1511
|
+
method: "GET",
|
|
1512
|
+
params: [
|
|
1513
|
+
{ name: "serviceId", description: "Target the repository of this service", required: false },
|
|
1514
|
+
{ name: "projectId", description: "Target the repository of this project, when no service is given", required: false },
|
|
1515
|
+
{ name: "agentId", description: "The agent hosting the repository", required: false },
|
|
1516
|
+
{ name: "orgId", description: "Its organization, when a project id alone is ambiguous", required: false }
|
|
1517
|
+
],
|
|
1518
|
+
buildInput: (p) => gitTarget(p)
|
|
1519
|
+
},
|
|
1520
|
+
{
|
|
1521
|
+
name: "git_log",
|
|
1522
|
+
description: "Read the recent commits of a service or project repository: hash, author, date, message.",
|
|
1523
|
+
route: "git.log",
|
|
1524
|
+
method: "GET",
|
|
1525
|
+
params: [
|
|
1526
|
+
{ name: "serviceId", description: "Target the repository of this service", required: false },
|
|
1527
|
+
{ name: "projectId", description: "Target the repository of this project, when no service is given", required: false },
|
|
1528
|
+
{ name: "agentId", description: "The agent hosting the repository", required: false },
|
|
1529
|
+
{ name: "orgId", description: "Its organization, when a project id alone is ambiguous", required: false },
|
|
1530
|
+
{ name: "limit", description: "How many commits to return (1-200). Default: 50.", required: false }
|
|
1531
|
+
],
|
|
1532
|
+
buildInput: (p) => ({ ...gitTarget(p), ...p.limit ? { limit: Number(p.limit) } : {} })
|
|
1533
|
+
},
|
|
1534
|
+
{
|
|
1535
|
+
name: "git_branches",
|
|
1536
|
+
description: "List the local and remote branches of a service or project repository.",
|
|
1537
|
+
route: "git.branches",
|
|
1538
|
+
method: "GET",
|
|
1539
|
+
params: [
|
|
1540
|
+
{ name: "serviceId", description: "Target the repository of this service", required: false },
|
|
1541
|
+
{ name: "projectId", description: "Target the repository of this project, when no service is given", required: false },
|
|
1542
|
+
{ name: "agentId", description: "The agent hosting the repository", required: false },
|
|
1543
|
+
{ name: "orgId", description: "Its organization, when a project id alone is ambiguous", required: false }
|
|
1544
|
+
],
|
|
1545
|
+
buildInput: (p) => gitTarget(p)
|
|
1546
|
+
},
|
|
1547
|
+
{
|
|
1548
|
+
name: "git_diff",
|
|
1549
|
+
description: "Read the diff of a service or project repository \u2014 everything, or one file. Use it to see what changed before describing or reviewing it.",
|
|
1550
|
+
route: "git.diff",
|
|
1551
|
+
method: "GET",
|
|
1552
|
+
params: [
|
|
1553
|
+
{ name: "serviceId", description: "Target the repository of this service", required: false },
|
|
1554
|
+
{ name: "projectId", description: "Target the repository of this project, when no service is given", required: false },
|
|
1555
|
+
{ name: "agentId", description: "The agent hosting the repository", required: false },
|
|
1556
|
+
{ name: "orgId", description: "Its organization, when a project id alone is ambiguous", required: false },
|
|
1557
|
+
{ name: "path", description: "Restrict the diff to this file path", required: false },
|
|
1558
|
+
{ name: "staged", description: 'Set to "true" to read the staged diff instead of the working tree', required: false },
|
|
1559
|
+
{ name: "untracked", description: 'Set to "true" to include untracked files', required: false }
|
|
1560
|
+
],
|
|
1561
|
+
buildInput: (p) => ({
|
|
1562
|
+
...gitTarget(p),
|
|
1563
|
+
...p.path ? { path: p.path } : {},
|
|
1564
|
+
...p.staged !== void 0 ? { staged: p.staged === "true" } : {},
|
|
1565
|
+
...p.untracked !== void 0 ? { untracked: p.untracked === "true" } : {}
|
|
1566
|
+
})
|
|
1567
|
+
},
|
|
1568
|
+
{
|
|
1569
|
+
name: "list_docs",
|
|
1570
|
+
description: "List the markdown documentation files of a scope, as a tree. Pair it with read_doc to answer from the project's own docs rather than from guesswork.",
|
|
1571
|
+
route: "wiki.list",
|
|
1572
|
+
method: "GET",
|
|
1573
|
+
params: [
|
|
1574
|
+
{ name: "scope", description: `"global" for this Runeya, or "service:<serviceId>" for one service's repository`, required: true }
|
|
1575
|
+
],
|
|
1576
|
+
buildInput: (p) => ({ scope: p.scope })
|
|
1577
|
+
},
|
|
1578
|
+
{
|
|
1579
|
+
name: "read_doc",
|
|
1580
|
+
description: "Read one markdown documentation file. Paths come from list_docs; only .md and .markdown can be read.",
|
|
1581
|
+
route: "wiki.read",
|
|
1582
|
+
method: "GET",
|
|
1583
|
+
params: [
|
|
1584
|
+
{ name: "scope", description: `"global" for this Runeya, or "service:<serviceId>" for one service's repository`, required: true },
|
|
1585
|
+
{ name: "path", description: "Relative path of the file, as returned by list_docs", required: true }
|
|
1586
|
+
],
|
|
1587
|
+
buildInput: (p) => ({ scope: p.scope, path: p.path })
|
|
1588
|
+
},
|
|
1589
|
+
{
|
|
1590
|
+
name: "get_server_logs",
|
|
1591
|
+
description: "Read Runeya's own recent log entries. Use it to explain why Runeya itself misbehaved \u2014 not to read a service's output, which is get_logs.",
|
|
1592
|
+
route: "diagnostics.recentLogs",
|
|
1593
|
+
method: "GET",
|
|
1594
|
+
params: [
|
|
1595
|
+
{ name: "limit", description: "How many entries to return (1-2000). Default: 500.", required: false }
|
|
1596
|
+
],
|
|
1597
|
+
buildInput: (p) => p.limit ? { limit: Number(p.limit) } : void 0
|
|
1598
|
+
},
|
|
1599
|
+
{
|
|
1600
|
+
name: "get_kanban_queue_state",
|
|
1601
|
+
description: "Read the state of the kanban task queue: what is running, what is waiting. Use it before queuing work, or to explain why a card has not started.",
|
|
1602
|
+
route: "kanbanQueue.getState",
|
|
1603
|
+
method: "GET",
|
|
1604
|
+
params: [],
|
|
1605
|
+
buildInput: () => void 0
|
|
1606
|
+
},
|
|
1607
|
+
{
|
|
1608
|
+
name: "export_project",
|
|
1609
|
+
description: "Read a project and every service it holds in one call, with secrets stripped out. Cheaper and safer than calling get_service for each service \u2014 prefer it whenever you need the whole picture of a project.",
|
|
1610
|
+
route: "project.export",
|
|
1611
|
+
method: "GET",
|
|
1612
|
+
params: [
|
|
1613
|
+
{ name: "projectId", description: "The project ID, from list_projects", required: true },
|
|
1614
|
+
{ name: "orgId", description: "Its organization. Needed only when the same project id exists in several.", required: false }
|
|
1615
|
+
],
|
|
1616
|
+
buildInput: (p) => ({ id: p.projectId, ...p.orgId ? { orgId: p.orgId } : {} })
|
|
1617
|
+
},
|
|
1618
|
+
{
|
|
1619
|
+
name: "git_remotes",
|
|
1620
|
+
description: "List the git remotes of a service or project repository, with their URLs.",
|
|
1621
|
+
route: "git.remotes",
|
|
1622
|
+
method: "GET",
|
|
1623
|
+
params: [
|
|
1624
|
+
{ name: "serviceId", description: "Target the repository of this service", required: false },
|
|
1625
|
+
{ name: "projectId", description: "Target the repository of this project, when no service is given", required: false },
|
|
1626
|
+
{ name: "agentId", description: "The agent hosting the repository", required: false },
|
|
1627
|
+
{ name: "orgId", description: "Its organization, when a project id alone is ambiguous", required: false }
|
|
1628
|
+
],
|
|
1629
|
+
buildInput: (p) => gitTarget(p)
|
|
1630
|
+
},
|
|
1631
|
+
{
|
|
1632
|
+
name: "git_stash_list",
|
|
1633
|
+
description: "List the stashes of a service or project repository. Useful before assuming work was lost: it may simply be stashed.",
|
|
1634
|
+
route: "git.stashList",
|
|
1635
|
+
method: "GET",
|
|
1636
|
+
params: [
|
|
1637
|
+
{ name: "serviceId", description: "Target the repository of this service", required: false },
|
|
1638
|
+
{ name: "projectId", description: "Target the repository of this project, when no service is given", required: false },
|
|
1639
|
+
{ name: "agentId", description: "The agent hosting the repository", required: false },
|
|
1640
|
+
{ name: "orgId", description: "Its organization, when a project id alone is ambiguous", required: false }
|
|
1641
|
+
],
|
|
1642
|
+
buildInput: (p) => gitTarget(p)
|
|
1643
|
+
},
|
|
1644
|
+
{
|
|
1645
|
+
name: "get_runeya_version",
|
|
1646
|
+
description: "Read the version of Runeya running here, the latest published one, and whether this install is up to date. Use it before blaming a bug on the code: the machine may simply be behind.",
|
|
1647
|
+
route: "health.versionInfo",
|
|
1648
|
+
method: "GET",
|
|
1649
|
+
params: [],
|
|
1650
|
+
buildInput: () => void 0
|
|
1651
|
+
},
|
|
1652
|
+
{
|
|
1653
|
+
name: "get_runeya_paths",
|
|
1654
|
+
description: "Read where Runeya keeps its things on this machine: its launch directory, its data directory, and the machine-wide directory holding cloud projects.",
|
|
1655
|
+
route: "settings.getPaths",
|
|
1656
|
+
method: "GET",
|
|
1657
|
+
params: [],
|
|
1658
|
+
buildInput: () => void 0
|
|
1659
|
+
},
|
|
1660
|
+
{
|
|
1661
|
+
name: "get_network_info",
|
|
1662
|
+
description: "Read where this Runeya listens (host and port) and whether it is reachable from the local network, with the URLs to use. Use it to give someone a working link instead of guessing one.",
|
|
1663
|
+
route: "settings.getNetwork",
|
|
1664
|
+
method: "GET",
|
|
1665
|
+
params: [],
|
|
1666
|
+
buildInput: () => void 0
|
|
1667
|
+
},
|
|
1668
|
+
{
|
|
1669
|
+
name: "list_runeya_instances",
|
|
1670
|
+
description: "List every Runeya answering on this machine, this one included, with its port and directory. Use it when a port is taken or when two instances seem to disagree.",
|
|
1671
|
+
route: "diagnostics.instances",
|
|
1672
|
+
method: "GET",
|
|
1673
|
+
params: [],
|
|
1674
|
+
buildInput: () => void 0
|
|
1675
|
+
},
|
|
1676
|
+
{
|
|
1677
|
+
name: "get_cloud_status",
|
|
1678
|
+
description: "Say whether this Runeya is linked to a cloud account, and to which cloud. A kanban tool failing for lack of a cloud link is explained here.",
|
|
1679
|
+
route: "cloudAuth.status",
|
|
1680
|
+
method: "GET",
|
|
1681
|
+
params: [],
|
|
1682
|
+
buildInput: () => void 0
|
|
1683
|
+
}
|
|
1684
|
+
];
|
|
1685
|
+
|
|
1686
|
+
// ../../packages/ai-capabilities/src/adapters/anthropic.ts
|
|
1687
|
+
function buildAnthropicTools(capabilities) {
|
|
1688
|
+
return capabilities.map((cap) => ({
|
|
1689
|
+
name: cap.name,
|
|
1690
|
+
description: cap.description,
|
|
1691
|
+
input_schema: {
|
|
1692
|
+
type: "object",
|
|
1693
|
+
properties: Object.fromEntries(
|
|
1694
|
+
cap.params.map((p) => [p.name, { type: "string", description: p.description }])
|
|
1695
|
+
),
|
|
1696
|
+
required: cap.params.filter((p) => p.required).map((p) => p.name)
|
|
1432
1697
|
}
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1698
|
+
}));
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1701
|
+
// ../../packages/ai-capabilities/src/adapters/openai.ts
|
|
1702
|
+
function buildOpenAITools(capabilities) {
|
|
1703
|
+
return capabilities.map((cap) => ({
|
|
1704
|
+
type: "function",
|
|
1705
|
+
function: {
|
|
1706
|
+
name: cap.name,
|
|
1707
|
+
description: cap.description,
|
|
1708
|
+
parameters: {
|
|
1709
|
+
type: "object",
|
|
1710
|
+
properties: Object.fromEntries(
|
|
1711
|
+
cap.params.map((p) => [p.name, { type: "string", description: p.description }])
|
|
1712
|
+
),
|
|
1713
|
+
required: cap.params.filter((p) => p.required).map((p) => p.name)
|
|
1449
1714
|
}
|
|
1450
1715
|
}
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
overridden: wasInherited
|
|
1469
|
-
};
|
|
1716
|
+
}));
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
// ../../packages/ai-capabilities/src/adapters/prompt.ts
|
|
1720
|
+
function buildToolSafetyInstruction(capabilities) {
|
|
1721
|
+
const destructive = capabilities.filter((c) => c.destructive).map((c) => c.name);
|
|
1722
|
+
const withHints = capabilities.filter((c) => c.usageHint);
|
|
1723
|
+
const lines = ["## Tool use safety rules"];
|
|
1724
|
+
if (destructive.length > 0) {
|
|
1725
|
+
lines.push(`CRITICAL: Never call ${destructive.join(", ")} unless the user has EXPLICITLY and UNAMBIGUOUSLY requested it.`);
|
|
1726
|
+
lines.push(`- Only call destructive tools (${destructive.join(", ")}) when the user explicitly uses action words for a specific service.`);
|
|
1727
|
+
}
|
|
1728
|
+
if (withHints.length > 0) {
|
|
1729
|
+
lines.push("");
|
|
1730
|
+
lines.push("## Tool usage hints");
|
|
1731
|
+
for (const cap of withHints) {
|
|
1732
|
+
lines.push(`- ${cap.usageHint}`);
|
|
1470
1733
|
}
|
|
1471
|
-
return {
|
|
1472
|
-
variables: mergedVariables,
|
|
1473
|
-
sources,
|
|
1474
|
-
parentEnv,
|
|
1475
|
-
parentSecretKeys,
|
|
1476
|
-
parentKeySources
|
|
1477
|
-
};
|
|
1478
1734
|
}
|
|
1479
|
-
|
|
1480
|
-
|
|
1735
|
+
return lines.join("\n");
|
|
1736
|
+
}
|
|
1737
|
+
|
|
1738
|
+
// ../../packages/ai-capabilities/src/trpc-caller.ts
|
|
1739
|
+
async function callTrpc(baseUrl, route, method, input, authToken) {
|
|
1740
|
+
const headers = {
|
|
1741
|
+
"Content-Type": "application/json",
|
|
1742
|
+
"Authorization": `Bearer ${authToken}`
|
|
1743
|
+
};
|
|
1744
|
+
const url = method === "GET" && input ? `${baseUrl}/api/trpc/${route}?input=${encodeURIComponent(JSON.stringify(input))}` : `${baseUrl}/api/trpc/${route}`;
|
|
1745
|
+
const res = await fetch(url, {
|
|
1746
|
+
method,
|
|
1747
|
+
headers,
|
|
1748
|
+
...method === "POST" ? { body: JSON.stringify(input ?? {}) } : {},
|
|
1749
|
+
signal: AbortSignal.timeout(15e3)
|
|
1750
|
+
});
|
|
1751
|
+
const json = await res.json();
|
|
1752
|
+
if (json["error"]) throw new Error(JSON.stringify(json["error"]));
|
|
1753
|
+
const result = json["result"];
|
|
1754
|
+
return result?.["data"] ?? result ?? json;
|
|
1755
|
+
}
|
|
1481
1756
|
|
|
1482
1757
|
// ../server/src/services/llms-txt-generator.ts
|
|
1483
|
-
function generateAdminLlmsTxt(services, jwt) {
|
|
1484
|
-
const baseUrl = `http://localhost:${env.PORT}`;
|
|
1485
|
-
const trpcBase = `${baseUrl}/api/trpc`;
|
|
1758
|
+
function generateAdminLlmsTxt(services, jwt, project) {
|
|
1486
1759
|
const lines = [];
|
|
1487
|
-
lines.push("# Runeya \u2014 Service Management
|
|
1760
|
+
lines.push("# Runeya \u2014 Service Management");
|
|
1488
1761
|
lines.push("");
|
|
1489
1762
|
lines.push("> You are operating as an authenticated admin with full access to all services.");
|
|
1490
|
-
lines.push(
|
|
1491
|
-
if (jwt) {
|
|
1492
|
-
lines.push("> Authentication: pass `Authorization: Bearer $RUNEYA_API_TOKEN` on all tRPC requests.");
|
|
1493
|
-
}
|
|
1763
|
+
lines.push("> Everything below is driven through the Runeya MCP tools.");
|
|
1494
1764
|
lines.push("");
|
|
1765
|
+
if (project) {
|
|
1766
|
+
lines.push(`## Current project`);
|
|
1767
|
+
lines.push("");
|
|
1768
|
+
lines.push(`You are working on **${project.name}** (projectId: \`${project.id}\`${project.orgId ? `, orgId: \`${project.orgId}\`` : ""}).`);
|
|
1769
|
+
lines.push(`The services listed below are its own. Name this project \u2014 \`projectId=${project.id}\` \u2014 on any tool that takes one, and you will stay on what the user actually sees.`);
|
|
1770
|
+
lines.push("A call that names no project may answer for every project of the machine, which is far more than this screen shows: if a result mentions services you do not recognize, that is why.");
|
|
1771
|
+
lines.push("");
|
|
1772
|
+
}
|
|
1495
1773
|
if (services.length === 0) {
|
|
1496
1774
|
lines.push("No services configured.");
|
|
1497
1775
|
return lines.join("\n");
|
|
@@ -1509,47 +1787,24 @@ function generateAdminLlmsTxt(services, jwt) {
|
|
|
1509
1787
|
}
|
|
1510
1788
|
lines.push("## MCP Tools");
|
|
1511
1789
|
lines.push("");
|
|
1512
|
-
lines.push("
|
|
1513
|
-
lines.push("Available tools: `list_services`, `get_service_status`, `start_service`, `stop_service`, `restart_service`, `get_logs`.");
|
|
1790
|
+
lines.push("Runeya is driven exclusively through the MCP tools below. There is no HTTP API to fall back on.");
|
|
1514
1791
|
lines.push("");
|
|
1792
|
+
lines.push(RUNEYA_CAPABILITIES.map((c) => `\`${c.name}\``).join(", ") + ".");
|
|
1793
|
+
lines.push("");
|
|
1794
|
+
const hints = RUNEYA_CAPABILITIES.filter((c) => c.usageHint);
|
|
1795
|
+
if (hints.length > 0) {
|
|
1796
|
+
lines.push("### Usage hints");
|
|
1797
|
+
lines.push("");
|
|
1798
|
+
for (const cap of hints) lines.push(`- ${cap.usageHint}`);
|
|
1799
|
+
lines.push("");
|
|
1800
|
+
}
|
|
1515
1801
|
if (jwt) {
|
|
1516
1802
|
lines.push("**Important**: Pass the `authToken` parameter with value `$RUNEYA_API_TOKEN` (from environment) on every MCP tool call for authentication.");
|
|
1517
1803
|
lines.push("");
|
|
1518
1804
|
}
|
|
1519
1805
|
lines.push("Use the service IDs and agent IDs listed above when calling these tools.");
|
|
1520
1806
|
lines.push("");
|
|
1521
|
-
lines.push("
|
|
1522
|
-
lines.push("");
|
|
1523
|
-
lines.push("Only use raw HTTP calls if MCP tools are unavailable.");
|
|
1524
|
-
lines.push("All endpoints use tRPC v11 over HTTP (`Content-Type: application/json`).");
|
|
1525
|
-
lines.push("");
|
|
1526
|
-
lines.push("**tRPC v11 request format:**");
|
|
1527
|
-
lines.push('- **GET queries**: `?input={"id":"abc"}`');
|
|
1528
|
-
lines.push('- **POST mutations**: JSON body `{"agentId":"<agentId>","processId":"<serviceId>"}`');
|
|
1529
|
-
lines.push("");
|
|
1530
|
-
lines.push(`### List services
|
|
1531
|
-
\`GET ${trpcBase}/service.list\``);
|
|
1532
|
-
lines.push("");
|
|
1533
|
-
lines.push(`### Get service
|
|
1534
|
-
\`GET ${trpcBase}/service.get?input={"agentId":"<agentId>","id":"<serviceId>"}\``);
|
|
1535
|
-
lines.push("");
|
|
1536
|
-
lines.push(`### Read logs
|
|
1537
|
-
\`GET ${trpcBase}/process.logs?input={"agentId":"<agentId>","processId":"<serviceId>"}\``);
|
|
1538
|
-
lines.push("");
|
|
1539
|
-
lines.push(`### Start service
|
|
1540
|
-
\`POST ${trpcBase}/process.start\`
|
|
1541
|
-
Body: \`{"agentId":"<agentId>","processId":"<serviceId>"}\``);
|
|
1542
|
-
lines.push("");
|
|
1543
|
-
lines.push(`### Stop service
|
|
1544
|
-
\`POST ${trpcBase}/process.stop\`
|
|
1545
|
-
Body: \`{"agentId":"<agentId>","processId":"<serviceId>"}\``);
|
|
1546
|
-
lines.push("");
|
|
1547
|
-
lines.push(`### Restart service
|
|
1548
|
-
\`POST ${trpcBase}/process.restart\`
|
|
1549
|
-
Body: \`{"agentId":"<agentId>","processId":"<serviceId>"}\``);
|
|
1550
|
-
lines.push("");
|
|
1551
|
-
lines.push(`### Get service status
|
|
1552
|
-
\`GET ${trpcBase}/process.status?input={"agentId":"<agentId>","processId":"<serviceId>"}\``);
|
|
1807
|
+
lines.push("If a tool you need does not exist, say so instead of improvising another route.");
|
|
1553
1808
|
lines.push("");
|
|
1554
1809
|
return lines.join("\n");
|
|
1555
1810
|
}
|
|
@@ -2075,10 +2330,31 @@ async function resolveServiceVariables(service) {
|
|
|
2075
2330
|
}
|
|
2076
2331
|
var DockerConfigInput = DockerConfigSchema;
|
|
2077
2332
|
var serviceRouter = router({
|
|
2078
|
-
|
|
2333
|
+
/**
|
|
2334
|
+
* Sans `projectId`, la réponse couvre TOUT le poste : `serviceStore.list()`
|
|
2335
|
+
* rend chaque coffre, donc chaque organisation et chaque projet de la
|
|
2336
|
+
* machine. L'interface le supporte — elle n'affiche que le projet ouvert —
|
|
2337
|
+
* mais un appelant sans écran reçoit la liste entière, d'où le filtre.
|
|
2338
|
+
*
|
|
2339
|
+
* Un projet introuvable rend une liste vide, jamais tout le poste : un repli
|
|
2340
|
+
* silencieux ferait croire au filtrage tout en rendant les services des
|
|
2341
|
+
* autres organisations.
|
|
2342
|
+
*/
|
|
2343
|
+
list: protectedProcedure.meta({ openapi: { method: "GET", path: "/services", tags: ["services"], summary: "List services (every project of the machine unless narrowed)", protect: true } }).input(z2.object({
|
|
2344
|
+
projectId: z2.string().max(128).optional(),
|
|
2345
|
+
orgId: z2.string().max(128).nullable().optional()
|
|
2346
|
+
}).optional()).output(z2.any()).query(async ({ input, ctx }) => {
|
|
2079
2347
|
const all = await serviceStore.list();
|
|
2080
2348
|
const allowedIds = getAllowedServiceIds(ctx);
|
|
2081
|
-
|
|
2349
|
+
let filtered = allowedIds ? all.filter((s) => allowedIds.has(s.id)) : all;
|
|
2350
|
+
if (input?.projectId) {
|
|
2351
|
+
const project = await projectStore.get({
|
|
2352
|
+
id: input.projectId,
|
|
2353
|
+
...input.orgId !== void 0 ? { orgId: input.orgId } : {}
|
|
2354
|
+
});
|
|
2355
|
+
const ids = new Set(project?.serviceIds ?? []);
|
|
2356
|
+
filtered = filtered.filter((s) => ids.has(s.id));
|
|
2357
|
+
}
|
|
2082
2358
|
return Promise.all(filtered.map(async (s) => ({
|
|
2083
2359
|
...s,
|
|
2084
2360
|
effectiveAgentId: await resolveEffectiveAgentId(s)
|
|
@@ -3256,7 +3532,7 @@ async function vaultOfProject(projectId) {
|
|
|
3256
3532
|
// ../server/src/services/image-storage.service.ts
|
|
3257
3533
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
3258
3534
|
import { mkdir as mkdir6, writeFile as writeFile4, readFile as readFile6, unlink as unlink2, readdir as readdir3 } from "fs/promises";
|
|
3259
|
-
import { existsSync } from "fs";
|
|
3535
|
+
import { existsSync as existsSync2 } from "fs";
|
|
3260
3536
|
import { join as join6, extname, resolve as resolve2, sep as sep2 } from "path";
|
|
3261
3537
|
var ALLOWED_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
3262
3538
|
"image/png",
|
|
@@ -3322,7 +3598,7 @@ var ImageStorageService = class {
|
|
|
3322
3598
|
if (!metaFile) return null;
|
|
3323
3599
|
const raw = JSON.parse(await readFile6(join6(this.dir, metaFile), "utf-8"));
|
|
3324
3600
|
if (expectedContextId !== void 0 && raw.contextId !== expectedContextId) return null;
|
|
3325
|
-
if (!
|
|
3601
|
+
if (!existsSync2(raw.filePath)) return null;
|
|
3326
3602
|
return { filePath: raw.filePath, mimeType: raw.mimeType, contextId: raw.contextId };
|
|
3327
3603
|
} catch {
|
|
3328
3604
|
return null;
|
|
@@ -4554,13 +4830,9 @@ async function getAgentManager() {
|
|
|
4554
4830
|
return agentManager2;
|
|
4555
4831
|
}
|
|
4556
4832
|
function buildPtyArgs(params, sessionId, opts) {
|
|
4557
|
-
const { isResume, systemContext,
|
|
4833
|
+
const { isResume, systemContext, model, mcpConfig, skipTokenInstructions, prompt } = params;
|
|
4558
4834
|
const sessionArg = isResume ? ["--resume", sessionId] : ["--session-id", sessionId];
|
|
4559
|
-
const
|
|
4560
|
-
const fullSystemContext = apiDocs ? `${systemContext}
|
|
4561
|
-
|
|
4562
|
-
${apiDocs}` : systemContext;
|
|
4563
|
-
const systemPrompt = skipTokenInstructions ? fullSystemContext : `${fullSystemContext}
|
|
4835
|
+
const systemPrompt = skipTokenInstructions ? systemContext : `${systemContext}
|
|
4564
4836
|
|
|
4565
4837
|
${TOKEN_INSTRUCTIONS}`;
|
|
4566
4838
|
const mcpArgs = mcpConfig && !opts.excludeMcp ? ["--mcp-config", mcpConfig] : [];
|
|
@@ -4719,7 +4991,9 @@ async function runClaudeViaPty(params) {
|
|
|
4719
4991
|
// toutes les tools répondent « No auth token available », et `$RUNEYA_API_TOKEN`
|
|
4720
4992
|
// ne résout à rien dans le shell du CLI. Le jeton est déjà là — la file le
|
|
4721
4993
|
// signe elle-même, faute de requête HTTP d'où le tirer.
|
|
4722
|
-
mcpApiToken: params.apiToken || void 0
|
|
4994
|
+
mcpApiToken: params.apiToken || void 0,
|
|
4995
|
+
mcpProjectId: params.projectId || void 0,
|
|
4996
|
+
mcpOrgId: params.orgId || void 0
|
|
4723
4997
|
}).then(({ spawnId: id }) => {
|
|
4724
4998
|
spawnId = id;
|
|
4725
4999
|
if (signal.aborted) {
|
|
@@ -4866,16 +5140,12 @@ var EFFORT_THINKING_BUDGET = {
|
|
|
4866
5140
|
high: 1e4
|
|
4867
5141
|
};
|
|
4868
5142
|
function buildClaudeSpawnConfig(params, opts) {
|
|
4869
|
-
const { sessionId, prompt, isResume, systemContext,
|
|
5143
|
+
const { sessionId, prompt, isResume, systemContext, apiToken, model, effort, images, mcpConfig, skipTokenInstructions, injectedEnv } = params;
|
|
4870
5144
|
const hasImages = images && images.length > 0;
|
|
4871
5145
|
const sessionArg = isResume ? ["--resume", sessionId] : sessionId ? ["--session-id", sessionId] : [];
|
|
4872
5146
|
const thinkingBudget = EFFORT_THINKING_BUDGET[effort] ?? 0;
|
|
4873
5147
|
const thinkingArgs = thinkingBudget > 0 ? ["--thinking", "enabled"] : [];
|
|
4874
|
-
const
|
|
4875
|
-
const fullSystemContext = apiDocs ? `${systemContext}
|
|
4876
|
-
|
|
4877
|
-
${apiDocs}` : systemContext;
|
|
4878
|
-
const systemPrompt = skipTokenInstructions ? fullSystemContext : `${fullSystemContext}
|
|
5148
|
+
const systemPrompt = skipTokenInstructions ? systemContext : `${systemContext}
|
|
4879
5149
|
|
|
4880
5150
|
${TOKEN_INSTRUCTIONS}`;
|
|
4881
5151
|
const inputArgs = hasImages ? ["--input-format", "stream-json"] : ["-p", prompt];
|
|
@@ -5053,56 +5323,6 @@ var ClaudeCodeRunner = class {
|
|
|
5053
5323
|
import { spawn as spawn2 } from "child_process";
|
|
5054
5324
|
import { createInterface } from "readline";
|
|
5055
5325
|
import { EventEmitter } from "events";
|
|
5056
|
-
|
|
5057
|
-
// ../../packages/mcp-server/src/launch.ts
|
|
5058
|
-
import { fileURLToPath } from "url";
|
|
5059
|
-
import { createRequire } from "module";
|
|
5060
|
-
import { existsSync as existsSync2 } from "fs";
|
|
5061
|
-
function resolveMcpServerPath() {
|
|
5062
|
-
try {
|
|
5063
|
-
const req = createRequire(import.meta.url);
|
|
5064
|
-
return req.resolve("@runeya/packages-mcp-server");
|
|
5065
|
-
} catch {
|
|
5066
|
-
}
|
|
5067
|
-
const candidates = [
|
|
5068
|
-
// Build packagé du CLI : dist/agent/index.js et dist/index.js côtoient
|
|
5069
|
-
// dist/mcp-server/, copié là par le post-build.
|
|
5070
|
-
new URL("../mcp-server/index.js", import.meta.url),
|
|
5071
|
-
new URL("./mcp-server/index.js", import.meta.url),
|
|
5072
|
-
// Monorepo, depuis un dist d'app.
|
|
5073
|
-
new URL("../../../packages/mcp-server/dist/index.js", import.meta.url),
|
|
5074
|
-
new URL("../../../../packages/mcp-server/dist/index.js", import.meta.url)
|
|
5075
|
-
];
|
|
5076
|
-
for (const c of candidates) {
|
|
5077
|
-
const p = fileURLToPath(c);
|
|
5078
|
-
if (existsSync2(p)) return p;
|
|
5079
|
-
}
|
|
5080
|
-
throw new Error("Could not locate @runeya/packages-mcp-server (built dist not found)");
|
|
5081
|
-
}
|
|
5082
|
-
function pickEnv(env2) {
|
|
5083
|
-
return {
|
|
5084
|
-
...env2.RUNEYA_BASE_URL ? { RUNEYA_BASE_URL: env2.RUNEYA_BASE_URL } : {},
|
|
5085
|
-
...env2.RUNEYA_API_TOKEN ? { RUNEYA_API_TOKEN: env2.RUNEYA_API_TOKEN } : {}
|
|
5086
|
-
};
|
|
5087
|
-
}
|
|
5088
|
-
function codexMcpArgs(env2) {
|
|
5089
|
-
const fields = [
|
|
5090
|
-
`command=${tomlString("node")}`,
|
|
5091
|
-
`args=[${tomlString(resolveMcpServerPath())}]`
|
|
5092
|
-
];
|
|
5093
|
-
const entries = Object.entries(pickEnv(env2));
|
|
5094
|
-
if (entries.length > 0) {
|
|
5095
|
-
const inline = entries.map(([k, v]) => `${k}=${tomlString(v)}`).join(",");
|
|
5096
|
-
fields.push(`env={${inline}}`);
|
|
5097
|
-
}
|
|
5098
|
-
return ["-c", `mcp_servers.runeya={${fields.join(",")}}`];
|
|
5099
|
-
}
|
|
5100
|
-
function tomlString(value) {
|
|
5101
|
-
const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/[\u0000-\u001f\u007f]/g, (c) => `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`);
|
|
5102
|
-
return `"${escaped}"`;
|
|
5103
|
-
}
|
|
5104
|
-
|
|
5105
|
-
// ../server/src/services/ai-runners/codex-app-server-client.ts
|
|
5106
5326
|
function resolveMcpArgs(env2) {
|
|
5107
5327
|
if (!env2["RUNEYA_API_TOKEN"]) return [];
|
|
5108
5328
|
try {
|
|
@@ -5399,8 +5619,7 @@ var CodexRunner = class {
|
|
|
5399
5619
|
this.lastThreadId = threadId;
|
|
5400
5620
|
params.onThreadId?.(threadId);
|
|
5401
5621
|
}
|
|
5402
|
-
const
|
|
5403
|
-
const systemParts = [systemContext, ...skipTokenInstructions ? [] : [TOKEN_INSTRUCTIONS], apiDocs].filter(Boolean);
|
|
5622
|
+
const systemParts = [systemContext, ...skipTokenInstructions ? [] : [TOKEN_INSTRUCTIONS]].filter(Boolean);
|
|
5404
5623
|
const fullSystemContext = systemParts.join("\n\n");
|
|
5405
5624
|
const fullPrompt = isResume && this.lastThreadId ? prompt : `${fullSystemContext}
|
|
5406
5625
|
|
|
@@ -5592,8 +5811,7 @@ ${prompt}`;
|
|
|
5592
5811
|
this.lastThreadId = threadId;
|
|
5593
5812
|
params.onThreadId?.(threadId);
|
|
5594
5813
|
}
|
|
5595
|
-
const
|
|
5596
|
-
const systemParts = [systemContext, ...skipTokenInstructions ? [] : [TOKEN_INSTRUCTIONS], apiDocs].filter(Boolean);
|
|
5814
|
+
const systemParts = [systemContext, ...skipTokenInstructions ? [] : [TOKEN_INSTRUCTIONS]].filter(Boolean);
|
|
5597
5815
|
const fullSystemContext = systemParts.join("\n\n");
|
|
5598
5816
|
const fullPrompt = isResume && this.lastThreadId ? prompt : `${fullSystemContext}
|
|
5599
5817
|
|
|
@@ -5980,20 +6198,21 @@ async function* drainSession(session, signal, isReconnect) {
|
|
|
5980
6198
|
if (signal?.aborted) return;
|
|
5981
6199
|
}
|
|
5982
6200
|
}
|
|
6201
|
+
async function kanbanContextFor(conv) {
|
|
6202
|
+
if (!conv?.kanbanBoardId) return "";
|
|
6203
|
+
const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);
|
|
6204
|
+
if (!kanbanBoard) return "";
|
|
6205
|
+
return "\n\n" + (conv.kanbanCardId ? await buildKanbanCardPrompt(kanbanBoard, conv.kanbanCardId) : generateKanbanPopulatePrompt(kanbanBoard));
|
|
6206
|
+
}
|
|
5983
6207
|
async function buildCliSystemContext(conv, jwt) {
|
|
5984
6208
|
const allServices = await serviceStore.list();
|
|
5985
6209
|
const ref = conv ? await conversationStore.projectRefOf(conv) : null;
|
|
5986
6210
|
const project = ref ? await projectStore.get(ref) : null;
|
|
5987
6211
|
const ownServices = project ? allServices.filter((svc) => project.serviceIds.includes(svc.id)) : allServices;
|
|
5988
6212
|
const resolvedServices = await Promise.all(ownServices.map(resolveServiceVariables));
|
|
5989
|
-
let systemContext = generateAdminLlmsTxt(resolvedServices, jwt);
|
|
6213
|
+
let systemContext = generateAdminLlmsTxt(resolvedServices, jwt, project);
|
|
5990
6214
|
if (!conv?.isCompanion) systemContext += "\n\n" + companionSystemNote();
|
|
5991
|
-
|
|
5992
|
-
const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);
|
|
5993
|
-
if (kanbanBoard) {
|
|
5994
|
-
systemContext += "\n\n" + (conv.kanbanCardId ? await buildKanbanCardPrompt(kanbanBoard, conv.kanbanCardId) : generateKanbanPopulatePrompt(kanbanBoard));
|
|
5995
|
-
}
|
|
5996
|
-
}
|
|
6215
|
+
systemContext += await kanbanContextFor(conv);
|
|
5997
6216
|
return systemContext;
|
|
5998
6217
|
}
|
|
5999
6218
|
async function resolveInjectedEnv(environmentId) {
|
|
@@ -6020,15 +6239,12 @@ async function startClaudeCodeSession(convId, prompt, opts = {}) {
|
|
|
6020
6239
|
conversationStore.update(conv.id, { messages: conv.messages }, { silent: true }).catch(() => {
|
|
6021
6240
|
});
|
|
6022
6241
|
const systemContext = await buildCliSystemContext(conv, opts.jwt);
|
|
6023
|
-
const
|
|
6024
|
-
const mcpConfig =
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
env: { RUNEYA_BASE_URL: `http://localhost:${env.PORT}`, ...opts.jwt ? { RUNEYA_API_TOKEN: opts.jwt } : {} }
|
|
6030
|
-
}
|
|
6031
|
-
}
|
|
6242
|
+
const mcpRef = conv ? await conversationStore.projectRefOf(conv) : null;
|
|
6243
|
+
const mcpConfig = runeyaMcpConfig({
|
|
6244
|
+
RUNEYA_BASE_URL: `http://localhost:${env.PORT}`,
|
|
6245
|
+
...opts.jwt ? { RUNEYA_API_TOKEN: opts.jwt } : {},
|
|
6246
|
+
...mcpRef?.id ? { RUNEYA_PROJECT_ID: mcpRef.id } : {},
|
|
6247
|
+
...mcpRef?.orgId ? { RUNEYA_ORG_ID: mcpRef.orgId } : {}
|
|
6032
6248
|
});
|
|
6033
6249
|
const ac = new AbortController();
|
|
6034
6250
|
const session = activeSessionRegistry.registerProviderApiSession(convId, ac);
|
|
@@ -6048,6 +6264,8 @@ async function startClaudeCodeSession(convId, prompt, opts = {}) {
|
|
|
6048
6264
|
systemContext,
|
|
6049
6265
|
apiBaseUrl: `http://localhost:${env.PORT}`,
|
|
6050
6266
|
apiToken: opts.jwt ?? "",
|
|
6267
|
+
...mcpRef?.id ? { projectId: mcpRef.id } : {},
|
|
6268
|
+
...mcpRef?.orgId ? { orgId: mcpRef.orgId } : {},
|
|
6051
6269
|
model: opts.model ?? "claude-opus-4-6",
|
|
6052
6270
|
effort: opts.effort ?? "normal",
|
|
6053
6271
|
signal: ac.signal,
|
|
@@ -6549,25 +6767,14 @@ Return ONLY the improved text, no explanation, no preamble.`;
|
|
|
6549
6767
|
const cliPrompt = input.contextNote ? `${input.contextNote}
|
|
6550
6768
|
|
|
6551
6769
|
${input.prompt}` : input.prompt;
|
|
6552
|
-
const allServices = await serviceStore.list();
|
|
6553
|
-
const resolvedServices = await Promise.all(allServices.map(resolveServiceVariables));
|
|
6554
6770
|
const jwt = ctx.authorization?.startsWith("Bearer ") ? ctx.authorization.slice(7) : void 0;
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
}
|
|
6561
|
-
|
|
6562
|
-
const mcpServerPath = fileURLToPath2(new URL("../mcp-server/index.js", import.meta.url));
|
|
6563
|
-
const mcpConfig = JSON.stringify({
|
|
6564
|
-
mcpServers: {
|
|
6565
|
-
runeya: {
|
|
6566
|
-
command: "node",
|
|
6567
|
-
args: [mcpServerPath],
|
|
6568
|
-
env: { RUNEYA_BASE_URL: `http://localhost:${env.PORT}`, ...jwt ? { RUNEYA_API_TOKEN: jwt } : {} }
|
|
6569
|
-
}
|
|
6570
|
-
}
|
|
6771
|
+
const systemContext = await buildCliSystemContext(conv, jwt);
|
|
6772
|
+
const mcpRef = await conversationStore.projectRefOf(conv);
|
|
6773
|
+
const mcpConfig = runeyaMcpConfig({
|
|
6774
|
+
RUNEYA_BASE_URL: `http://localhost:${env.PORT}`,
|
|
6775
|
+
...jwt ? { RUNEYA_API_TOKEN: jwt } : {},
|
|
6776
|
+
...mcpRef?.id ? { RUNEYA_PROJECT_ID: mcpRef.id } : {},
|
|
6777
|
+
...mcpRef?.orgId ? { RUNEYA_ORG_ID: mcpRef.orgId } : {}
|
|
6571
6778
|
});
|
|
6572
6779
|
const imagePaths = [];
|
|
6573
6780
|
if (input.imageIds && input.imageIds.length > 0) {
|
|
@@ -6603,6 +6810,8 @@ ${imagePaths.map((p) => `Image: ${p}`).join("\n")}` : cliPrompt;
|
|
|
6603
6810
|
systemContext,
|
|
6604
6811
|
apiBaseUrl: `http://localhost:${env.PORT}`,
|
|
6605
6812
|
apiToken: jwt ?? "",
|
|
6813
|
+
...mcpRef?.id ? { projectId: mcpRef.id } : {},
|
|
6814
|
+
...mcpRef?.orgId ? { orgId: mcpRef.orgId } : {},
|
|
6606
6815
|
model: input.model ?? "claude-opus-4-6",
|
|
6607
6816
|
effort: input.effort ?? "normal",
|
|
6608
6817
|
signal: ac.signal,
|
|
@@ -6665,16 +6874,8 @@ ${imagePaths.map((p) => `Image: ${p}`).join("\n")}` : cliPrompt;
|
|
|
6665
6874
|
const cliPrompt = input.contextNote ? `${input.contextNote}
|
|
6666
6875
|
|
|
6667
6876
|
${input.prompt}` : input.prompt;
|
|
6668
|
-
const allServices = await serviceStore.list();
|
|
6669
|
-
const resolvedServices = await Promise.all(allServices.map(resolveServiceVariables));
|
|
6670
6877
|
const jwt = ctx.authorization?.startsWith("Bearer ") ? ctx.authorization.slice(7) : void 0;
|
|
6671
|
-
|
|
6672
|
-
if (conv.kanbanBoardId) {
|
|
6673
|
-
const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);
|
|
6674
|
-
if (kanbanBoard) {
|
|
6675
|
-
systemContext += "\n\n" + (conv.kanbanCardId ? await buildKanbanCardPrompt(kanbanBoard, conv.kanbanCardId) : generateKanbanPopulatePrompt(kanbanBoard));
|
|
6676
|
-
}
|
|
6677
|
-
}
|
|
6878
|
+
const systemContext = await buildCliSystemContext(conv, jwt);
|
|
6678
6879
|
const resolvedImages = input.imageIds && input.imageIds.length > 0 ? await resolveImagesToBase64(input.imageIds.map((id) => ({ imageId: id, mimeType: "" })), input.conversationId) : [];
|
|
6679
6880
|
const convId = input.conversationId;
|
|
6680
6881
|
const ac = new AbortController();
|
|
@@ -6764,12 +6965,7 @@ ${input.prompt}` : input.prompt;
|
|
|
6764
6965
|
const authToken = ctx.authorization?.replace(/^Bearer\s+/i, "") ?? "";
|
|
6765
6966
|
let system = await buildSystemPrompt(apiKey);
|
|
6766
6967
|
system += "\n\n" + TOOL_SAFETY_INSTRUCTION;
|
|
6767
|
-
|
|
6768
|
-
const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);
|
|
6769
|
-
if (kanbanBoard) {
|
|
6770
|
-
system += "\n\n" + (conv.kanbanCardId ? await buildKanbanCardPrompt(kanbanBoard, conv.kanbanCardId) : generateKanbanPopulatePrompt(kanbanBoard));
|
|
6771
|
-
}
|
|
6772
|
-
}
|
|
6968
|
+
system += await kanbanContextFor(conv);
|
|
6773
6969
|
const resolvedImages = input.imageIds && input.imageIds.length > 0 ? await resolveImagesToBase64(input.imageIds.map((id) => ({ imageId: id, mimeType: "" })), input.conversationId) : [];
|
|
6774
6970
|
let session;
|
|
6775
6971
|
try {
|
|
@@ -6896,12 +7092,14 @@ ${input.prompt}` : input.prompt;
|
|
|
6896
7092
|
}
|
|
6897
7093
|
}
|
|
6898
7094
|
lap("findPtyBySession (no reattach)");
|
|
7095
|
+
const ptyConv = input.sessionId ? await conversationStore.get(input.sessionId).catch(() => null) : null;
|
|
6899
7096
|
const isCodex = input.runner === "codex";
|
|
6900
7097
|
const cli = isCodex ? "codex" : "claude";
|
|
6901
7098
|
const args = [];
|
|
6902
7099
|
if (isCodex) {
|
|
6903
|
-
|
|
6904
|
-
|
|
7100
|
+
const resumeId = await resolveCodexResumeId(input.sessionId, ptyConv?.codexThreadId);
|
|
7101
|
+
if (resumeId) {
|
|
7102
|
+
args.push("resume", resumeId);
|
|
6905
7103
|
}
|
|
6906
7104
|
if (input.model) args.push("--model", input.model);
|
|
6907
7105
|
args.push("--dangerously-bypass-approvals-and-sandbox");
|
|
@@ -6917,20 +7115,13 @@ ${input.prompt}` : input.prompt;
|
|
|
6917
7115
|
if (input.model) args.push("--model", input.model);
|
|
6918
7116
|
args.push("--dangerously-skip-permissions");
|
|
6919
7117
|
}
|
|
7118
|
+
const ptyRef = (ptyConv ? await conversationStore.projectRefOf(ptyConv) : null) ?? (input.projectId ? { id: input.projectId, orgId: input.orgId ?? null } : null);
|
|
6920
7119
|
const jwt = ctx.authorization?.startsWith("Bearer ") ? ctx.authorization.slice(7) : void 0;
|
|
6921
|
-
if (!isCodex &&
|
|
7120
|
+
if (!isCodex && ptyConv) {
|
|
6922
7121
|
try {
|
|
6923
|
-
const
|
|
6924
|
-
if (
|
|
6925
|
-
|
|
6926
|
-
const apiBase = input.apiBaseUrl ?? `http://localhost:${env.PORT}`;
|
|
6927
|
-
const apiDocs = buildApiDocs(apiBase, jwt ?? "");
|
|
6928
|
-
const fullSystemPrompt = apiDocs ? `${systemContext}
|
|
6929
|
-
|
|
6930
|
-
${apiDocs}` : systemContext;
|
|
6931
|
-
if (fullSystemPrompt.trim().length > 0) {
|
|
6932
|
-
args.push("--append-system-prompt", fullSystemPrompt);
|
|
6933
|
-
}
|
|
7122
|
+
const systemContext = await buildCliSystemContext(ptyConv, jwt);
|
|
7123
|
+
if (systemContext.trim().length > 0) {
|
|
7124
|
+
args.push("--append-system-prompt", systemContext);
|
|
6934
7125
|
}
|
|
6935
7126
|
} catch (err) {
|
|
6936
7127
|
console.warn("[chat.pty.start] buildCliSystemContext failed:", err.message);
|
|
@@ -6962,7 +7153,9 @@ ${apiDocs}` : systemContext;
|
|
|
6962
7153
|
sessionId: input.sessionId,
|
|
6963
7154
|
enableMcp: input.enableMcp,
|
|
6964
7155
|
mcpApiBaseUrl: input.apiBaseUrl ?? `http://localhost:${env.PORT}`,
|
|
6965
|
-
mcpApiToken: jwt
|
|
7156
|
+
mcpApiToken: jwt,
|
|
7157
|
+
...ptyRef?.id ? { mcpProjectId: ptyRef.id } : {},
|
|
7158
|
+
...ptyRef?.orgId ? { mcpOrgId: ptyRef.orgId } : {}
|
|
6966
7159
|
}
|
|
6967
7160
|
);
|
|
6968
7161
|
lap("agent ai.spawnPty");
|
|
@@ -7319,4 +7512,4 @@ export {
|
|
|
7319
7512
|
startCliSession,
|
|
7320
7513
|
chatRouter
|
|
7321
7514
|
};
|
|
7322
|
-
//# sourceMappingURL=chunk-
|
|
7515
|
+
//# sourceMappingURL=chunk-MBHLFZ7C.js.map
|