@xopcai/xopc 0.0.426 → 0.0.428
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/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/src/adapters/security-adapter.js +1 -1
- package/dist/extensions/telegram/src/pairing-config-resolver.js +1 -1
- package/dist/extensions/telegram/src/plugin.js +2 -2
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/api/api.js +1 -1
- package/dist/extensions/weixin/src/auth/accounts.js +2 -2
- package/dist/extensions/weixin/src/auth/pairing.js +1 -1
- package/dist/extensions/weixin/src/cdn/upload.js +1 -1
- package/dist/extensions/weixin/src/cli/gateway-qr-login.js +1 -1
- package/dist/extensions/weixin/src/cli/qr-login.js +1 -1
- package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
- package/dist/extensions/weixin/src/messaging/inbound.js +2 -2
- package/dist/extensions/weixin/src/messaging/process-message.js +3 -3
- package/dist/extensions/weixin/src/messaging/send.js +12 -3
- package/dist/extensions/weixin/src/monitor/monitor.js +1 -1
- package/dist/extensions/weixin/src/outbound-send.js +12 -3
- package/dist/extensions/weixin/src/pairing-config-resolver.js +1 -1
- package/dist/extensions/weixin/src/plugin.js +1 -1
- package/dist/gateway/static/root/assets/{activity-store-D_DXNHba.js → activity-store-WqnVruhY.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CjaQxFQt.js → agent-avatar-dicebear-CSiO9c2F.js} +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-display-6Z4m31Fz.js → agent-avatar-display-D-yds6wG.js} +2 -2
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-_UT9C7bg.js +1 -0
- package/dist/gateway/static/root/assets/agent-plugin-dialog-DVzYXsAy.js +1 -0
- package/dist/gateway/static/root/assets/{agents-admin-api-u5c3GREg.js → agents-admin-api-Bgv4lJ9Y.js} +1 -1
- package/dist/gateway/static/root/assets/agents-yTsbcxRi.js +77 -0
- package/dist/gateway/static/root/assets/{api-C3Tp9MkF.js → api-C-9J9ghT.js} +1 -1
- package/dist/gateway/static/root/assets/{api-CRT9ZyH0.js → api-Dv6Cn-Rs.js} +1 -1
- package/dist/gateway/static/root/assets/app-link-DRy3-k7j.js +1 -0
- package/dist/gateway/static/root/assets/{app-management-settings-panel-C8yc3yHG.js → app-management-settings-panel-BXJrrjH5.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-BELgtR3O.js → appearance-settings-oYjAVulT.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-D95yzj-f.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-BCQnOkV8.js → archive-plugin-DBPu3xCJ.js} +1 -1
- package/dist/gateway/static/root/assets/attachment-load-DrVGNxJm.js +1 -0
- package/dist/gateway/static/root/assets/automation-api-DAou8Kji.js +1 -0
- package/dist/gateway/static/root/assets/{automation-result-state-CMfVTv_i.js → automation-result-state-CA7LV098.js} +1 -1
- package/dist/gateway/static/root/assets/automation-task-card-w6cKxfaP.js +3 -0
- package/dist/gateway/static/root/assets/{automations-page-CdIPdwF0.js → automations-page-D4LyOLzY.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-BGyvZZj5.js +9 -0
- package/dist/gateway/static/root/assets/{binary-plugins-CIB5cbvQ.js → binary-plugins-D25P9ZxQ.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-BQtTLe6Q.js → block-editor-BI105p1U.js} +2 -2
- package/dist/gateway/static/root/assets/{browser-automation-inputs-DeraGZ1y.js → browser-automation-inputs-DhDRvWQE.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-automations-page-SpPzRNqU.js → browser-automations-page-CCPi1Bvy.js} +2 -2
- package/dist/gateway/static/root/assets/{browser-control-api-CbbPvhHR.js → browser-control-api-BN4F-bM1.js} +1 -1
- package/dist/gateway/static/root/assets/browser-settings-page-BZXUZpjp.js +3 -0
- package/dist/gateway/static/root/assets/{button-CnRSIP6m.js → button-Cc4hUNTt.js} +1 -1
- package/dist/gateway/static/root/assets/{capabilities-DLMuj21P.js → capabilities-LC-yEQYo.js} +1 -1
- package/dist/gateway/static/root/assets/capabilities-page-DHJLl4RD.js +2 -0
- package/dist/gateway/static/root/assets/capabilities-settings-panel-FJ3Vo7Wa.js +8 -0
- package/dist/gateway/static/root/assets/capabilities-u2z_KFRt.js +1 -0
- package/dist/gateway/static/root/assets/{capability-header-actions-CTUCuBlW.js → capability-header-actions-BxMYfQ8y.js} +1 -1
- package/dist/gateway/static/root/assets/channels-9Uaa-IN0.js +1 -0
- package/dist/gateway/static/root/assets/{chat-agents-api-D8YS5amE.js → chat-agents-api-Cffxfzi1.js} +1 -1
- package/dist/gateway/static/root/assets/{chat-chart-block-DCzUECct.js → chat-chart-block-Bbk0b3TV.js} +1 -1
- package/dist/gateway/static/root/assets/chat-page--dKUIg5W.js +72 -0
- package/dist/gateway/static/root/assets/{chat-terminal-dock-Dl-OTkJI.js → chat-terminal-dock-CQMuG-Bz.js} +2 -2
- package/dist/gateway/static/root/assets/{command-palette-api-Dijix7V6.js → command-palette-api-BRxfFgGA.js} +1 -1
- package/dist/gateway/static/root/assets/composer-payload-handoff-_9L2A5AZ.js +1 -0
- package/dist/gateway/static/root/assets/{computer-settings-page-B-lGMimW.js → computer-settings-page-Bm70SIjD.js} +1 -1
- package/dist/gateway/static/root/assets/confirm-dialog-D7dQJytv.js +1 -0
- package/dist/gateway/static/root/assets/connected-providers-grid-B7ktDgqt.js +1 -0
- package/dist/gateway/static/root/assets/{connector-service-page-C8InhrMt.js → connector-service-page-BVMEg8n-.js} +1 -1
- package/dist/gateway/static/root/assets/{connectors-api-DEJU8mgn.js → connectors-api-B07yoCzk.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-hPKaJUWY.js +1 -0
- package/dist/gateway/static/root/assets/{copy-text-row-CYIv7RfP.js → copy-text-row-CpiRzq4G.js} +1 -1
- package/dist/gateway/static/root/assets/{date-picker-kqic8j73.js → date-picker-BvEnSGZK.js} +1 -1
- package/dist/gateway/static/root/assets/dependency-picker-XjPB8FJS.js +1 -0
- package/dist/gateway/static/root/assets/{desktop-pet-DFNehTtd.js → desktop-pet-C1z9YDEg.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-BDS7_tQ_.js → desktop-pet-settings-CbbVb8GY.js} +1 -1
- package/dist/gateway/static/root/assets/{dev-view-store-CeZZLOc6.js → dev-view-store-38EmUIEC.js} +1 -1
- package/dist/gateway/static/root/assets/device-pairing-wizard-Wb1EKiXA.js +1 -0
- package/dist/gateway/static/root/assets/{directory-picker-path-field-Di0h3ws4.js → directory-picker-path-field-BvKDrKc4.js} +1 -1
- package/dist/gateway/static/root/assets/{discussion-annotation-sync-ClKEyXmN.js → discussion-annotation-sync-BfVzIwe2.js} +1 -1
- package/dist/gateway/static/root/assets/dist-BGTk37IG.js +1 -0
- package/dist/gateway/static/root/assets/dist-BuHnPloF.js +1 -0
- package/dist/gateway/static/root/assets/dist-GJ8-1PAx.js +1 -0
- package/dist/gateway/static/root/assets/dist-ZrL34Ps4.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-DwB5KMGk.js → extension-debug-page-CB9Lu3Sq.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-iframe-host-Cqg1K70e.js → extension-iframe-host-BzjrVAUR.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-marketplace-api-DRBszrCR.js → extension-marketplace-api-DigziAgd.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-DyrQtG82.js → extension-page-DUa9MeaZ.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-provider-C_uKqJxP.js → extension-provider-301x0rh-.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-BAMQHzkX.js → extension-settings-page-CP9ciZUI.js} +1 -1
- package/dist/gateway/static/root/assets/{file-preview-surface-DfkXvFnc.js → file-preview-surface-BaMGmCbw.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-BOCt_zOo.js → gateway-config-swr-BD4Bf8uu.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-realtime-BL_Cf0OQ.js → gateway-realtime-CSd9VB7Z.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-realtime-store-Bxkv62qs.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-restart-CHf8qY7H.js → gateway-restart-CIUCTKYR.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-settings-uAboiElC.js → gateway-settings-CCqF1uZv.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-startup-retry-CvkJYurV.js → gateway-startup-retry-BsU5k8oi.js} +1 -1
- package/dist/gateway/static/root/assets/{global-defaults-api-BWMbKu72.js → global-defaults-api-asOZQeM8.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-Bb_RC1O9.js +2 -0
- package/dist/gateway/static/root/assets/{image-generation-api-CQxZSTWA.js → image-generation-api-BbEnKsK1.js} +1 -1
- package/dist/gateway/static/root/assets/{imports-page-C90644id.js → imports-page-CVnoGUyp.js} +1 -1
- package/dist/gateway/static/root/assets/index-ClPeYgQk.js +11 -0
- package/dist/gateway/static/root/assets/index-Cz-VjTNd.css +1 -0
- package/dist/gateway/static/root/assets/install-connector-dialog-DXVOHMhS.js +1 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-CbeubKe1.js → keyboard-shortcuts-settings-BCl90SrD.js} +1 -1
- package/dist/gateway/static/root/assets/link-2-D_ZKYUW7.js +1 -0
- package/dist/gateway/static/root/assets/local-app-workbench-page-CcJc9xLJ.js +1 -0
- package/dist/gateway/static/root/assets/{local-apps-page-C6zFgwkr.js → local-apps-page-CdAKoWfg.js} +1 -1
- package/dist/gateway/static/root/assets/{local-session-drafts-BJ1B1dQ7.js → local-session-drafts-nRGeybku.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-Br7IfbXK.js → locale-store-B7y-RVe8.js} +1 -1
- package/dist/gateway/static/root/assets/{logs-page-CpVCvAWE.js → logs-page-McbSQwJI.js} +2 -2
- package/dist/gateway/static/root/assets/management-settings-BIR0BwNV.js +1 -0
- package/dist/gateway/static/root/assets/{markdown-view-DrVAMlwc.js → markdown-view-DFHa8rUg.js} +2 -2
- package/dist/gateway/static/root/assets/mcp-conversation-setup-page-Dwx4TuIr.js +1 -0
- package/dist/gateway/static/root/assets/{media-plugins-Ba6vUE4J.js → media-plugins-BzzLV7wW.js} +1 -1
- package/dist/gateway/static/root/assets/messages-DYDkJvXj.js +3 -0
- package/dist/gateway/static/root/assets/model-selector-DJSVr3LM.js +1 -0
- package/dist/gateway/static/root/assets/{models-hub-cache-Bd-fYUrV.js → models-hub-cache-BUapaPTN.js} +1 -1
- package/dist/gateway/static/root/assets/new-chat-navigation-B6NPQ4h4.js +1 -0
- package/dist/gateway/static/root/assets/note-detail-panel-CJ-dPovd.js +5 -0
- package/dist/gateway/static/root/assets/note-image-lightbox-ClPkeHe5.js +1 -0
- package/dist/gateway/static/root/assets/{notes-api-CUlhTRv0.js → notes-api-ulup1oFS.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-page-eoKX85K5.js → notes-page-BaFNplIr.js} +1 -1
- package/dist/gateway/static/root/assets/{oauth-api-DMMdeaNd.js → oauth-api-DINa08-z.js} +1 -1
- package/dist/gateway/static/root/assets/{oauth-provider-connect-C8BXow79.js → oauth-provider-connect-C0PVEHC2.js} +1 -1
- package/dist/gateway/static/root/assets/{page-context-capture-button-CBFK41OS.js → page-context-capture-button-CGfR0dsc.js} +1 -1
- package/dist/gateway/static/root/assets/{page-context-draft-LF33STHC.js → page-context-draft-DhRNxc0v.js} +1 -1
- package/dist/gateway/static/root/assets/page-header-store-CoKMiYoi.js +1 -0
- package/dist/gateway/static/root/assets/{personal-avatar-D6CzIIfo.js → personal-avatar-DiVFO2Aw.js} +1 -1
- package/dist/gateway/static/root/assets/personal-page-CiKdXLeR.js +1 -0
- package/dist/gateway/static/root/assets/{personal-settings-panel-DnYapLo7.js → personal-settings-panel-Ds4ntiqu.js} +1 -1
- package/dist/gateway/static/root/assets/{phone-dependencies-card-DBiKtzwz.js → phone-dependencies-card-B3R6L5Qu.js} +1 -1
- package/dist/gateway/static/root/assets/phone-model-connection-ucX3Tvl8.js +1 -0
- package/dist/gateway/static/root/assets/{phone-model-picker-BmSxEr7M.js → phone-model-picker-CU37sziM.js} +1 -1
- package/dist/gateway/static/root/assets/phone-settings-page-BSdB2pnW.js +1 -0
- package/dist/gateway/static/root/assets/{phone-workspace-store-SN7hfddU.js → phone-workspace-store-Cmes9gQ4.js} +1 -1
- package/dist/gateway/static/root/assets/plugin-details-dialog-DblFhnuC.js +1 -0
- package/dist/gateway/static/root/assets/{popover-select-DD8fmrxH.js → popover-select-CEMWIrtY.js} +1 -1
- package/dist/gateway/static/root/assets/{preference-select-fields-Cu_ZC9Up.js → preference-select-fields-D2-QfMN5.js} +1 -1
- package/dist/gateway/static/root/assets/{product-automation-feedback-Tn2dUJWM.js → product-automation-feedback-BzY3z8zu.js} +2 -2
- package/dist/gateway/static/root/assets/{product-open-page-Nf-Oqf1h.js → product-open-page-BKw6H0Mn.js} +1 -1
- package/dist/gateway/static/root/assets/{product-preview-content-D6NwUm3A.js → product-preview-content-CNaJb6Bj.js} +1 -1
- package/dist/gateway/static/root/assets/{product-preview-modal-BfNcGgXA.js → product-preview-modal-DgwrrpqJ.js} +2 -2
- package/dist/gateway/static/root/assets/project-detail-page-FReFYUv0.js +7 -0
- package/dist/gateway/static/root/assets/{project-understanding-B1BK7Ixi.js → project-understanding-CrSkrJnM.js} +1 -1
- package/dist/gateway/static/root/assets/projects-page-Cp91_KzA.js +1 -0
- package/dist/gateway/static/root/assets/{providers-api-DOnNfkwQ.js → providers-api-CBSC3jdu.js} +1 -1
- package/dist/gateway/static/root/assets/{recording-upload-RAhaLUcQ.js → recording-upload-DBHAGKZj.js} +1 -1
- package/dist/gateway/static/root/assets/{refresh-button-bU_0NarN.js → refresh-button-DiWdGAaX.js} +1 -1
- package/dist/gateway/static/root/assets/{registry-api-DFDvOTg4.js → registry-api-QZEjziDq.js} +1 -1
- package/dist/gateway/static/root/assets/{remote-access-hub-DWsOWetc.js → remote-access-hub-BdXxFQfH.js} +1 -1
- package/dist/gateway/static/root/assets/{resource-unavailable-TQcRCpAg.js → resource-unavailable-BTNhcOHF.js} +1 -1
- package/dist/gateway/static/root/assets/route-preload-DS4fVFbc.js +2 -0
- package/dist/gateway/static/root/assets/{runtime-tools-api-9o3Wfji1.js → runtime-tools-api-BDTUD8Rj.js} +1 -1
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-BGiXeHF5.js → runtime-tools-settings-panel-CYEzIrDf.js} +1 -1
- package/dist/gateway/static/root/assets/{schema-form-BKeP5G7b.js → schema-form-C-jw6Hid.js} +1 -1
- package/dist/gateway/static/root/assets/{secret-input-BQvFXqzz.js → secret-input-Dryrns2s.js} +1 -1
- package/dist/gateway/static/root/assets/{service-recommendation-list-BEnNx0u7.js → service-recommendation-list-CfeYH6lK.js} +1 -1
- package/dist/gateway/static/root/assets/{session-api-Bs3r_d2_.js → session-api-DVXLCZX2.js} +1 -1
- package/dist/gateway/static/root/assets/session-manager-DjRWxXJG.js +23 -0
- package/dist/gateway/static/root/assets/sessions-page-C8gwrFHR.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BMHe9uwy.js +1 -0
- package/dist/gateway/static/root/assets/{settings-advanced-section-CURRjsLK.js → settings-advanced-section-BmrbHgQa.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-mode-store-CiRpsdTJ.js → settings-mode-store-Bk_hzwPK.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-GtsbT6as.js → settings-page-DCQnHCNN.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-header-DBL0_u0Z.js → settings-page-header-BLKI3_9N.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-layout-IAvpbz4A.js → settings-page-layout-BqBVrkC9.js} +1 -1
- package/dist/gateway/static/root/assets/setup-interaction-page-B9ACeAvO.js +1 -0
- package/dist/gateway/static/root/assets/setup-status-panel-DEefuWo3.js +1 -0
- package/dist/gateway/static/root/assets/share-link-dialog-C2LyeNzj.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-L9KYu8M7.js → share-preview-page-BFwEr7Ws.js} +1 -1
- package/dist/gateway/static/root/assets/{shares-api-D8Q-m46d.js → shares-api-CTFkLQxq.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-CpK3yhtc.js +1 -0
- package/dist/gateway/static/root/assets/{skill-api-uKU4sRiv.js → skill-api-DpicfA6o.js} +1 -1
- package/dist/gateway/static/root/assets/{skill-list-api-BzKzG-xG.js → skill-list-api-B8fegRLZ.js} +1 -1
- package/dist/gateway/static/root/assets/{skill-reload-api-DkUXekcd.js → skill-reload-api-VmC8ySUy.js} +1 -1
- package/dist/gateway/static/root/assets/skills-page-BIWXS6Ki.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-CsvcFoaJ.js → system-settings-panel-BmoA92oX.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-L5RIelv0.js +3 -0
- package/dist/gateway/static/root/assets/{task-result-evidence-B8xUiwW3.js → task-result-evidence-BV-6hBVU.js} +1 -1
- package/dist/gateway/static/root/assets/{terminal-panel-store-DJVC7HqA.js → terminal-panel-store-BGdKE9hU.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-Dlnmgryi.js → theme-store-Dvv79Wb2.js} +1 -1
- package/dist/gateway/static/root/assets/tracing-settings-page-B4uA4Pnz.js +1 -0
- package/dist/gateway/static/root/assets/{tunnel-api-BB7u79ID.js → tunnel-api-BurZtvqx.js} +1 -1
- package/dist/gateway/static/root/assets/{understanding-activity-store-C4bblRnQ.js → understanding-activity-store-C1cLL8zq.js} +1 -1
- package/dist/gateway/static/root/assets/{understanding-refresh-store-BvCj9-Ue.js → understanding-refresh-store-C3Lr_pjY.js} +1 -1
- package/dist/gateway/static/root/assets/{usage-page-Cv4Je5XJ.js → usage-page-C91ZzLm9.js} +1 -1
- package/dist/gateway/static/root/assets/{use-autosave-YHxQ-UZg.js → use-autosave-zkzRuUtx.js} +1 -1
- package/dist/gateway/static/root/assets/use-composer-attachments-CoiQAgjo.js +2 -0
- package/dist/gateway/static/root/assets/use-file-preview-expanded-DFzy6iVy.js +2 -0
- package/dist/gateway/static/root/assets/{use-personal-profile-D2Un8G1L.js → use-personal-profile-BB10h9ED.js} +1 -1
- package/dist/gateway/static/root/assets/{use-workspace-tree-BQEiJzK7.js → use-workspace-tree-sF5DcONt.js} +1 -1
- package/dist/gateway/static/root/assets/user-model-page-WFnD5utO.js +2 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-DCM69u8Y.js → voice-api-key-field-Bqa4PeZx.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-config-api-CrULrSKC.js → voice-config-api-LNO2xXHk.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-input-shortcut-events-DFMNIyy4.js → voice-input-shortcut-events-AzfhxBX7.js} +1 -1
- package/dist/gateway/static/root/assets/voice-transcribe-api-Cb8i6dLb.js +1 -0
- package/dist/gateway/static/root/assets/{work-discovery-overlay-CVe9UmFl.js → work-discovery-overlay-CdQUiV-a.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-page-CtqkRMN5.js → work-discovery-page-HcUloXxf.js} +1 -1
- package/dist/gateway/static/root/assets/working-directory-picker-modal-Dv1HUipe.js +1 -0
- package/dist/gateway/static/root/assets/{workspace-api-tbifz2zY.js → workspace-api-Am2ee4R6.js} +2 -2
- package/dist/gateway/static/root/assets/workspace-editor-agent-store-CqHcVFhS.js +1 -0
- package/dist/gateway/static/root/assets/{workspace-file-preview-dialog-BubQwQwU.js → workspace-file-preview-dialog-z5Q00v92.js} +1 -1
- package/dist/gateway/static/root/assets/{workspace-open-location-menu-DZk3MBSa.js → workspace-open-location-menu-4ONYaGy0.js} +1 -1
- package/dist/gateway/static/root/assets/xopc-cloud-account-card-DimGN59n.js +1 -0
- package/dist/gateway/static/root/index.html +99 -97
- package/dist/package.js +1 -1
- package/dist/packages/gateway-contract/src/automations.js +8 -0
- package/dist/packages/gateway-contract/src/capabilities.js +7 -3
- package/dist/packages/gateway-contract/src/home.js +12 -2
- package/dist/src/agent/agent-manager.d.ts +1 -0
- package/dist/src/agent/agent-manager.js +1 -0
- package/dist/src/agent/background-review/prompts.js +11 -6
- package/dist/src/agent/background-review/run-background-review.js +12 -3
- package/dist/src/agent/child-agent-factory.js +1 -1
- package/dist/src/agent/context/execution-context.js +3 -1
- package/dist/src/agent/data-acquisition/service.js +1 -1
- package/dist/src/agent/embedded/configuration-capability-correction.d.ts +3 -0
- package/dist/src/agent/embedded/configuration-capability-correction.js +14 -0
- package/dist/src/agent/embedded/run-for-session.js +20 -5
- package/dist/src/agent/embedded/run-turn.js +25 -2
- package/dist/src/agent/embedded/session-runner.js +10 -3
- package/dist/src/agent/image/generation/openai-images-provider.js +1 -1
- package/dist/src/agent/image/load-image-media.js +1 -1
- package/dist/src/agent/inbound/inbound-loop.js +4 -1
- package/dist/src/agent/independent-execution.js +1 -1
- package/dist/src/agent/mcp/config.js +1 -1
- package/dist/src/agent/mcp/connection-drafts.d.ts +5 -2
- package/dist/src/agent/mcp/connection-drafts.js +6 -4
- package/dist/src/agent/mcp/connection-setup.d.ts +15 -1
- package/dist/src/agent/mcp/connection-setup.js +223 -78
- package/dist/src/agent/mcp/continuation-guard.d.ts +3 -0
- package/dist/src/agent/mcp/continuation-guard.js +54 -0
- package/dist/src/agent/mcp/continuation-input.d.ts +4 -0
- package/dist/src/agent/mcp/continuation-input.js +13 -0
- package/dist/src/agent/mcp/conversation-setup.d.ts +282 -0
- package/dist/src/agent/mcp/conversation-setup.js +856 -0
- package/dist/src/agent/mcp/discovery.d.ts +102 -0
- package/dist/src/agent/mcp/discovery.js +219 -0
- package/dist/src/agent/mcp/native-mcp.d.ts +1 -0
- package/dist/src/agent/mcp/native-mcp.js +8 -1
- package/dist/src/agent/mcp/setup-plan.d.ts +76 -0
- package/dist/src/agent/mcp/setup-plan.js +93 -0
- package/dist/src/agent/mcp/tool-catalog.d.ts +7 -0
- package/dist/src/agent/mcp/tool-catalog.js +26 -3
- package/dist/src/agent/mcp/transport.d.ts +20 -0
- package/dist/src/agent/mcp/transport.js +188 -0
- package/dist/src/agent/mcp/weixin-setup-scope.d.ts +12 -0
- package/dist/src/agent/mcp/weixin-setup-scope.js +43 -0
- package/dist/src/agent/orchestration/delegation-scope.d.ts +2 -1
- package/dist/src/agent/prompt/conversational-configuration-guide.js +2 -1
- package/dist/src/agent/prompt/sections/tooling.js +3 -2
- package/dist/src/agent/prompt/service-prompt-builder.js +1 -1
- package/dist/src/agent/service/direct-turn-helpers.js +3 -2
- package/dist/src/agent/service/process-direct-streaming.js +4 -3
- package/dist/src/agent/service.d.ts +2 -0
- package/dist/src/agent/service.js +15 -1
- package/dist/src/agent/service.types.d.ts +1 -0
- package/dist/src/agent/tasks/task-judge-service.js +2 -2
- package/dist/src/agent/tool-manuals/xopc-configuration.d.ts +6 -4
- package/dist/src/agent/tool-manuals/xopc-configuration.js +125 -8
- package/dist/src/agent/tools/automation-tool.d.ts +9 -1
- package/dist/src/agent/tools/automation-tool.js +34 -5
- package/dist/src/agent/tools/create-share-tool.js +1 -1
- package/dist/src/agent/tools/factory.d.ts +3 -0
- package/dist/src/agent/tools/factory.js +35 -24
- package/dist/src/agent/tools/image-generate-tool.js +3 -3
- package/dist/src/agent/tools/index.d.ts +1 -0
- package/dist/src/agent/tools/index.js +5 -4
- package/dist/src/agent/tools/mcp-setup-tool.d.ts +9 -0
- package/dist/src/agent/tools/mcp-setup-tool.js +36 -0
- package/dist/src/agent/tools/personal-task-tool.js +2 -2
- package/dist/src/agent/tools/publish-artifacts.js +1 -1
- package/dist/src/agent/tools/read.js +1 -1
- package/dist/src/agent/tools/skill-install-tool.js +56 -1
- package/dist/src/agent/tools/skill-manage-tool.d.ts +4 -0
- package/dist/src/agent/tools/skill-manage-tool.js +74 -2
- package/dist/src/agent/tools/skills-tools.js +1 -1
- package/dist/src/agent/tools/task-collaboration-tool.js +1 -1
- package/dist/src/agent/tools/tool-manual-tool.d.ts +1 -1
- package/dist/src/agent/tools/tool-manual-tool.js +3 -1
- package/dist/src/agent/tools/toolExposure.js +2 -0
- package/dist/src/agent/tools/write.js +1 -1
- package/dist/src/agent/tools/xopc-use-tool.d.ts +5 -2
- package/dist/src/agent/tools/xopc-use-tool.js +81 -10
- package/dist/src/agent-catalog/service.d.ts +1 -1
- package/dist/src/agent-catalog/service.js +2 -1
- package/dist/src/automations/api/routes.js +13 -5
- package/dist/src/automations/capabilities/drafts.js +5 -2
- package/dist/src/automations/capabilities/read.js +49 -10
- package/dist/src/automations/capabilities/write.d.ts +111 -52
- package/dist/src/automations/capabilities/write.js +44 -10
- package/dist/src/automations/delivery/delivery-router.d.ts +1 -0
- package/dist/src/automations/delivery/delivery-router.js +7 -1
- package/dist/src/automations/domain/types.d.ts +10 -0
- package/dist/src/automations/domain/validation.d.ts +24 -0
- package/dist/src/automations/domain/validation.js +7 -0
- package/dist/src/automations/draft/automation-draft-validator.d.ts +6 -0
- package/dist/src/automations/index.js +2 -2
- package/dist/src/automations/mcp-source.d.ts +60 -0
- package/dist/src/automations/mcp-source.js +173 -0
- package/dist/src/automations/service/action-executor.js +15 -1
- package/dist/src/automations/service/automation-service.d.ts +12 -0
- package/dist/src/automations/service/automation-service.js +61 -4
- package/dist/src/automations/service/index.js +2 -2
- package/dist/src/automations/storage/automation-run-repository.d.ts +11 -2
- package/dist/src/automations/storage/automation-run-repository.js +28 -24
- package/dist/src/automations/storage/index.js +2 -2
- package/dist/src/browser/setup/repository.d.ts +1 -0
- package/dist/src/browser/setup/repository.js +7 -1
- package/dist/src/browser/setup/service.d.ts +3 -0
- package/dist/src/browser/setup/service.js +41 -18
- package/dist/src/browser/setup/types.d.ts +1 -0
- package/dist/src/channels/attachments/voice-stt-webchat.js +1 -1
- package/dist/src/channels/index.js +1 -1
- package/dist/src/channels/manager.d.ts +1 -0
- package/dist/src/channels/outbound-sender.d.ts +1 -0
- package/dist/src/channels/outbound-sender.js +3 -0
- package/dist/src/channels/pairing/pairing-service.js +1 -1
- package/dist/src/channels/weixin/account-identity.d.ts +2 -0
- package/dist/src/channels/weixin/account-identity.js +15 -0
- package/dist/src/chat-commands/builtins/config.js +1 -1
- package/dist/src/cli/commands/channels.js +2 -2
- package/dist/src/cli/commands/doctor/checks/channel-pairing-pending.js +1 -1
- package/dist/src/cli/commands/mcp.js +1 -1
- package/dist/src/config/schema.d.ts +3 -0
- package/dist/src/config/schema.js +3 -2
- package/dist/src/extensions/agent-plugins/credentials.js +1 -1
- package/dist/src/extensions/agent-plugins/setup.d.ts +2 -1
- package/dist/src/extensions/agent-plugins/setup.js +4 -3
- package/dist/src/extensions/api.js +1 -1
- package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/device-routes.js +1 -1
- package/dist/src/gateway/hono/app.js +1 -1
- package/dist/src/gateway/hono/lib/config-payload.js +1 -1
- package/dist/src/gateway/hono/oauth-async.js +1 -1
- package/dist/src/gateway/hono/routes/channels.js +1 -1
- package/dist/src/gateway/hono/routes/config.js +1 -1
- package/dist/src/gateway/hono/routes/lazy-bundles.js +1 -1
- package/dist/src/gateway/hono/routes/mcp.js +39 -2
- package/dist/src/gateway/hono/routes/notes.js +2 -2
- package/dist/src/gateway/hono/routes/phone-setup.js +33 -9
- package/dist/src/gateway/hono/routes/projects.js +1 -1
- package/dist/src/gateway/hono/routes/provider-setup.js +1 -1
- package/dist/src/gateway/hono/routes/public-gateway.js +22 -0
- package/dist/src/gateway/hono/routes/session-input-handler.js +1 -1
- package/dist/src/gateway/hono/routes/shares.js +1 -1
- package/dist/src/gateway/hono/routes/site-shares.js +1 -1
- package/dist/src/gateway/hono/routes/tasks.js +1 -5
- package/dist/src/gateway/media-access.js +1 -1
- package/dist/src/gateway/service/agent-runner.d.ts +1 -0
- package/dist/src/gateway/service/agent-runner.js +3 -1
- package/dist/src/gateway/service/config-coordinator.d.ts +2 -2
- package/dist/src/gateway/service/config-coordinator.js +2 -1
- package/dist/src/gateway/service/run-gateway-agent.js +1 -1
- package/dist/src/gateway/service/sessions-api.js +2 -1
- package/dist/src/gateway/service.d.ts +5 -1
- package/dist/src/gateway/service.js +97 -22
- package/dist/src/gateway/session-context-summary.js +1 -1
- package/dist/src/gateway/session-reset-service.d.ts +1 -0
- package/dist/src/gateway/session-reset-service.js +15 -2
- package/dist/src/home-intelligence/evidence-presentation.d.ts +3 -0
- package/dist/src/home-intelligence/evidence-presentation.js +30 -0
- package/dist/src/home-intelligence/generator.d.ts +8 -0
- package/dist/src/home-intelligence/generator.js +15 -4
- package/dist/src/home-intelligence/host.js +2 -2
- package/dist/src/home-intelligence/policy.js +3 -0
- package/dist/src/memory-learning/repository.d.ts +6 -1
- package/dist/src/memory-learning/repository.js +10 -5
- package/dist/src/memory-learning/service.js +23 -1
- package/dist/src/notes/service.js +1 -1
- package/dist/src/personal-agent/prompts.js +1 -1
- package/dist/src/personal-agent/reply-composer.js +2 -2
- package/dist/src/personal-agent/request-service.js +3 -3
- package/dist/src/personal-agent/service.js +1 -1
- package/dist/src/personal-agent/task-cancel.js +1 -1
- package/dist/src/phone/setup/service.d.ts +14 -4
- package/dist/src/phone/setup/service.js +106 -28
- package/dist/src/process/mcp-stdio-supervisor.d.ts +1 -0
- package/dist/src/process/mcp-stdio-supervisor.js +14 -0
- package/dist/src/projects/index.js +1 -1
- package/dist/src/projects/project-service.js +1 -1
- package/dist/src/runtime-tools/phone-dependencies.d.ts +2 -0
- package/dist/src/runtime-tools/phone-dependencies.js +10 -0
- package/dist/src/share/note-share-service.js +1 -1
- package/dist/src/share/site-proxy.js +1 -1
- package/dist/src/tasks/capabilities/write.js +1 -1
- package/dist/src/tasks/index.js +1 -1
- package/dist/src/tasks/task-allocation-service.js +3 -3
- package/dist/src/tasks/task-application-service.js +2 -2
- package/dist/src/tasks/task-context-assembler.js +1 -1
- package/dist/src/tasks/task-contract-planner.js +1 -1
- package/dist/src/tasks/task-criterion-review-repository.js +1 -1
- package/dist/src/tasks/task-handoff.js +1 -1
- package/dist/src/tasks/task-research-result.js +1 -1
- package/dist/src/tasks/task-run-coordinator.js +2 -2
- package/dist/src/tui/backends/embedded-backend.js +1 -1
- package/dist/src/tui/tui.js +1 -1
- package/dist/src/user-context/extraction/registry.js +2 -2
- package/dist/src/user-model/capture/executor.d.ts +1 -0
- package/dist/src/user-model/capture/executor.js +6 -6
- package/dist/src/user-model/capture/semantic.d.ts +3 -0
- package/dist/src/user-model/capture/semantic.js +14 -4
- package/package.json +3 -1
- package/skills/tools/configure-xopc/SKILL.md +10 -3
- package/skills/tools/configure-xopc/references/browser/chrome-extension.md +4 -1
- package/skills/tools/configure-xopc/references/browser/overview.md +2 -2
- package/skills/tools/configure-xopc/references/phone/aliyun.md +3 -2
- package/skills/tools/configure-xopc/references/phone/overview.md +2 -2
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-Dne9A10p.js +0 -1
- package/dist/gateway/static/root/assets/agent-plugin-dialog-BoHL-b1o.js +0 -1
- package/dist/gateway/static/root/assets/agents-CIiIlVBp.js +0 -77
- package/dist/gateway/static/root/assets/app-link-1j40sJ-z.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-vgS1CHDj.js +0 -1
- package/dist/gateway/static/root/assets/attachment-load-qjPpQzYY.js +0 -1
- package/dist/gateway/static/root/assets/automation-api-hRsGx-qe.js +0 -1
- package/dist/gateway/static/root/assets/automation-task-card-MnzgyTVA.js +0 -3
- package/dist/gateway/static/root/assets/automations-workspace-C3xZLafX.js +0 -9
- package/dist/gateway/static/root/assets/browser-settings-page-BD1uF_Nb.js +0 -3
- package/dist/gateway/static/root/assets/capabilities-BGE6hiUE.js +0 -1
- package/dist/gateway/static/root/assets/capabilities-page-Bda4mSdf.js +0 -2
- package/dist/gateway/static/root/assets/capabilities-settings-panel-B2B7no22.js +0 -8
- package/dist/gateway/static/root/assets/channels-NtsjZThx.js +0 -1
- package/dist/gateway/static/root/assets/chat-page-BnOCCAXG.js +0 -72
- package/dist/gateway/static/root/assets/composer-payload-handoff-CQc-VTaL.js +0 -1
- package/dist/gateway/static/root/assets/confirm-dialog-XGclfBqe.js +0 -1
- package/dist/gateway/static/root/assets/connected-providers-grid-CcXe9kz5.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-Ci0L2How.js +0 -1
- package/dist/gateway/static/root/assets/dependency-picker-cbC6-2Ya.js +0 -1
- package/dist/gateway/static/root/assets/device-pairing-wizard-_3BJFWVQ.js +0 -1
- package/dist/gateway/static/root/assets/dist-CaUuvp8-.js +0 -1
- package/dist/gateway/static/root/assets/dist-D3lWNSe7.js +0 -1
- package/dist/gateway/static/root/assets/dist-DfWfZ9iu.js +0 -1
- package/dist/gateway/static/root/assets/dist-DusecO_p.js +0 -1
- package/dist/gateway/static/root/assets/gateway-realtime-store-BHBOPF_q.js +0 -1
- package/dist/gateway/static/root/assets/home-page-D6pCBY1V.js +0 -2
- package/dist/gateway/static/root/assets/index-Cc41XQid.css +0 -1
- package/dist/gateway/static/root/assets/index-CnOYR6jq.js +0 -11
- package/dist/gateway/static/root/assets/install-connector-dialog-BuNXON0P.js +0 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-CP-BkbB6.js +0 -1
- package/dist/gateway/static/root/assets/management-settings-I-pXv4ML.js +0 -1
- package/dist/gateway/static/root/assets/messages-ByFlEbsu.js +0 -3
- package/dist/gateway/static/root/assets/model-selector-CXcxc30J.js +0 -1
- package/dist/gateway/static/root/assets/note-detail-panel-CbpLXAVh.js +0 -5
- package/dist/gateway/static/root/assets/note-image-lightbox-cLGiF8oU.js +0 -1
- package/dist/gateway/static/root/assets/page-header-store-Du44NIEJ.js +0 -1
- package/dist/gateway/static/root/assets/personal-page-CXR1Gy0x.js +0 -1
- package/dist/gateway/static/root/assets/phone-settings-page-vg65qilc.js +0 -1
- package/dist/gateway/static/root/assets/plugin-details-dialog-B3Hn2cbx.js +0 -1
- package/dist/gateway/static/root/assets/project-detail-page-Ch-ZMyTu.js +0 -7
- package/dist/gateway/static/root/assets/projects-page-B7cetxao.js +0 -1
- package/dist/gateway/static/root/assets/route-preload-Zc5Z3fNv.js +0 -2
- package/dist/gateway/static/root/assets/send-1f1Ntw6E.js +0 -1
- package/dist/gateway/static/root/assets/session-manager-ChUtTAoG.js +0 -23
- package/dist/gateway/static/root/assets/sessions-page-Bt52kBvJ.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-BI4DMz4_.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-A6uMpGRy.js +0 -1
- package/dist/gateway/static/root/assets/share-link-dialog-D1otGSXD.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-Bmfadz8A.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-BZklXTX9.js +0 -2
- package/dist/gateway/static/root/assets/task-detail-page-SjZGW1Dx.js +0 -2
- package/dist/gateway/static/root/assets/tracing-settings-page-MvG4SH64.js +0 -1
- package/dist/gateway/static/root/assets/use-composer-attachments-vDdxHtUb.js +0 -2
- package/dist/gateway/static/root/assets/use-file-preview-expanded-Ce2mgYme.js +0 -2
- package/dist/gateway/static/root/assets/user-model-page-DRSsn4EV.js +0 -2
- package/dist/gateway/static/root/assets/voice-transcribe-api-Bbyj0yGR.js +0 -1
- package/dist/gateway/static/root/assets/working-directory-picker-modal-CDZ1xh3o.js +0 -1
- package/dist/gateway/static/root/assets/workspace-editor-agent-store-4cZ26iaD.js +0 -1
- package/dist/gateway/static/root/assets/xopc-cloud-account-card-CIavPUr3.js +0 -1
|
@@ -0,0 +1,856 @@
|
|
|
1
|
+
import { createLogger } from "../../utils/logger/index.js";
|
|
2
|
+
import { init_logger } from "../../utils/logger.js";
|
|
3
|
+
import { getActiveConnectionWait, init_connection_wait_repository } from "../../storage/sqlite/connection-wait-repository.js";
|
|
4
|
+
import { getSessionMetadata } from "../../storage/sqlite/session-read-repository.js";
|
|
5
|
+
import { init_session_repository } from "../../storage/sqlite/session-repository.js";
|
|
6
|
+
import { CredentialResolver, init_credentials } from "../../auth/credentials.js";
|
|
7
|
+
import { connectorPrincipalForSession } from "../../connectors/principal.js";
|
|
8
|
+
import { DurableState } from "../../storage/sqlite/durable-state.js";
|
|
9
|
+
import { connectorSecretProviderId } from "../../connectors/secret-store.js";
|
|
10
|
+
import { isManagedConnectorServer } from "../../connectors/materialize.js";
|
|
11
|
+
import { classifyMcpConnectionError } from "./connection-errors.js";
|
|
12
|
+
import { McpConnectionDrafts, McpDraftError, mcpConfigRevision } from "./connection-drafts.js";
|
|
13
|
+
import { weixinSetupScope } from "./weixin-setup-scope.js";
|
|
14
|
+
import { localExecutionSchema, secretFieldsSchema } from "./setup-plan.js";
|
|
15
|
+
import { McpDiscovery, createMcpResearch } from "./discovery.js";
|
|
16
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
17
|
+
import { z } from "zod";
|
|
18
|
+
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
19
|
+
//#region src/agent/mcp/conversation-setup.ts
|
|
20
|
+
init_credentials();
|
|
21
|
+
init_session_repository();
|
|
22
|
+
init_connection_wait_repository();
|
|
23
|
+
init_logger();
|
|
24
|
+
const identity = z.string().min(1).max(200);
|
|
25
|
+
const log = createLogger("McpConversationSetup");
|
|
26
|
+
const targetSchema = z.object({
|
|
27
|
+
serverId: z.string().regex(/^[a-zA-Z0-9_-]{1,64}$/),
|
|
28
|
+
displayName: z.string().min(1).max(100).optional(),
|
|
29
|
+
url: z.string().url().max(2048).optional(),
|
|
30
|
+
purpose: z.string().min(1).max(1e3),
|
|
31
|
+
authentication: z.enum([
|
|
32
|
+
"auto",
|
|
33
|
+
"bearer",
|
|
34
|
+
"header",
|
|
35
|
+
"none"
|
|
36
|
+
]).optional(),
|
|
37
|
+
expectedRevision: z.string().optional(),
|
|
38
|
+
planId: z.string().uuid().optional(),
|
|
39
|
+
expectedPlanVersion: z.number().int().positive().optional(),
|
|
40
|
+
transport: z.enum([
|
|
41
|
+
"streamable-http",
|
|
42
|
+
"sse",
|
|
43
|
+
"stdio"
|
|
44
|
+
]).optional(),
|
|
45
|
+
secretFields: secretFieldsSchema.optional(),
|
|
46
|
+
execution: localExecutionSchema.optional(),
|
|
47
|
+
helpUrl: z.string().url().optional(),
|
|
48
|
+
objective: z.enum(["connect_only", "complete_task"]).optional()
|
|
49
|
+
}).strict();
|
|
50
|
+
const setupSchema = z.object({
|
|
51
|
+
setupId: identity,
|
|
52
|
+
expectedVersion: z.number().int().positive().optional()
|
|
53
|
+
}).strict();
|
|
54
|
+
const serverSchema = z.object({
|
|
55
|
+
serverId: identity,
|
|
56
|
+
expectedRevision: z.string(),
|
|
57
|
+
enabled: z.boolean().optional()
|
|
58
|
+
}).strict();
|
|
59
|
+
function configuredServer(config, id) {
|
|
60
|
+
const servers = config.mcp?.servers;
|
|
61
|
+
return servers && Object.hasOwn(servers, id) ? servers[id] : void 0;
|
|
62
|
+
}
|
|
63
|
+
/** Coordinates HTTP MCP setup; pi remains the sole MCP and OAuth implementation. */
|
|
64
|
+
var McpConversationSetup = class {
|
|
65
|
+
goals = new DurableState("mcp.conversation-setup");
|
|
66
|
+
drafts;
|
|
67
|
+
draftIds = /* @__PURE__ */ new Map();
|
|
68
|
+
busy = /* @__PURE__ */ new Set();
|
|
69
|
+
authorizations = /* @__PURE__ */ new Set();
|
|
70
|
+
disposed = false;
|
|
71
|
+
retryTimers = /* @__PURE__ */ new Map();
|
|
72
|
+
discovery;
|
|
73
|
+
constructor(options) {
|
|
74
|
+
this.options = options;
|
|
75
|
+
this.drafts = new McpConnectionDrafts({
|
|
76
|
+
readConfig: options.readConfig,
|
|
77
|
+
saveConfig: options.saveConfig
|
|
78
|
+
});
|
|
79
|
+
this.discovery = new McpDiscovery(options.research ?? createMcpResearch(options.readConfig));
|
|
80
|
+
}
|
|
81
|
+
notify(goal) {
|
|
82
|
+
try {
|
|
83
|
+
this.options.changed?.(goal.conversationId);
|
|
84
|
+
} catch (err) {
|
|
85
|
+
log.warn({
|
|
86
|
+
err,
|
|
87
|
+
conversationId: goal.conversationId
|
|
88
|
+
}, "MCP setup state saved; notification failed");
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
save(goal) {
|
|
92
|
+
goal.version++;
|
|
93
|
+
this.goals.set(goal.id, goal);
|
|
94
|
+
this.notify(goal);
|
|
95
|
+
}
|
|
96
|
+
current(goal) {
|
|
97
|
+
if (this.disposed) throw new McpDraftError(409, "Gateway is stopping. Recheck after restart.");
|
|
98
|
+
const stored = this.goals.get(goal.id);
|
|
99
|
+
const session = getSessionMetadata(goal.conversationId);
|
|
100
|
+
const channel = goal.channel ? weixinSetupScope(goal.conversationId, this.options.readConfig()) : void 0;
|
|
101
|
+
if (goal.channel && JSON.stringify(channel) !== JSON.stringify(goal.channel)) {
|
|
102
|
+
if (stored && stored.phase !== "cancelled") this.cancelGoal(stored);
|
|
103
|
+
throw new McpDraftError(409, "The Weixin identity, pairing or secure Gateway origin changed. Start a new request.");
|
|
104
|
+
}
|
|
105
|
+
if (!stored || stored.version !== goal.version || stored.phase === "cancelled" || session?.transcriptId !== goal.transcriptId || session.agentId !== goal.agentId) throw new McpDraftError(409, "The setup objective changed or was cancelled. Inspect the current conversation before continuing.");
|
|
106
|
+
}
|
|
107
|
+
get(id, conversationId) {
|
|
108
|
+
const goal = this.goals.get(id);
|
|
109
|
+
if (!goal || conversationId && goal.conversationId !== conversationId) throw new McpDraftError(404, "MCP setup not found.");
|
|
110
|
+
return goal;
|
|
111
|
+
}
|
|
112
|
+
canProvideToken(goal) {
|
|
113
|
+
const url = new URL(goal.url);
|
|
114
|
+
return (goal.phase === "auth_unknown" || goal.phase === "blocked" && goal.errorCode === "access_denied") && !goal.tokenProvider && !goal.secretProviders && (url.protocol === "https:" || [
|
|
115
|
+
"127.0.0.1",
|
|
116
|
+
"localhost",
|
|
117
|
+
"[::1]"
|
|
118
|
+
].includes(url.hostname));
|
|
119
|
+
}
|
|
120
|
+
view(goal) {
|
|
121
|
+
const expired = goal.expiresAt < Date.now() && goal.phase !== "ready";
|
|
122
|
+
const interactionPath = goal.channel ? `${goal.channel.origin}/#/mcp-setup/${goal.id}` : `/mcp-setup/${goal.id}`;
|
|
123
|
+
const interactionLink = `[Complete connection](${interactionPath})`;
|
|
124
|
+
return {
|
|
125
|
+
setupId: goal.id,
|
|
126
|
+
serverId: goal.serverId,
|
|
127
|
+
displayName: goal.displayName,
|
|
128
|
+
version: goal.version,
|
|
129
|
+
phase: goal.phase,
|
|
130
|
+
expired,
|
|
131
|
+
reloadRequired: goal.reloadRequired === true,
|
|
132
|
+
canProvideToken: this.canProvideToken(goal),
|
|
133
|
+
secretFields: goal.secretFields,
|
|
134
|
+
helpUrl: goal.helpUrl,
|
|
135
|
+
objective: goal.objective,
|
|
136
|
+
planApproval: goal.reviewRequired ? {
|
|
137
|
+
sources: goal.sources ?? [],
|
|
138
|
+
execution: goal.execution,
|
|
139
|
+
endpoint: goal.transport === "stdio" ? goal.execution?.command : goal.url,
|
|
140
|
+
purpose: goal.purpose
|
|
141
|
+
} : void 0,
|
|
142
|
+
diagnosis: goal.diagnosis,
|
|
143
|
+
nextRetryAt: goal.nextRetryAt,
|
|
144
|
+
attempts: goal.attempts ?? 0,
|
|
145
|
+
errorCode: goal.errorCode,
|
|
146
|
+
conversationId: goal.conversationId,
|
|
147
|
+
expiresAt: goal.expiresAt,
|
|
148
|
+
interactionPath,
|
|
149
|
+
returnChannel: goal.channel ? "weixin" : void 0,
|
|
150
|
+
managementPath: goal.channel ? `${goal.channel.origin}/#/capabilities/connectors?tab=connected` : "/capabilities/connectors?tab=connected",
|
|
151
|
+
continuationQueued: goal.resumed === true,
|
|
152
|
+
replyDelivery: goal.reply?.status,
|
|
153
|
+
instruction: goal.phase === "cancelled" ? "This setup is cancelled. Do not continue or revive it. Cancellation does not undo configuration already saved." : expired ? "This request expired. Start a new objective instead of reusing authorization." : goal.phase === "approval_required" ? goal.channel ? "Send the exact trusted interactionPath to the user. The paired Weixin user has requested this service; an authenticated Gateway owner must approve this exact request on that page before any probe, credential submission or configuration change. Never ask for keys, callback URLs or a continue reply in chat. The result returns to this original Weixin conversation automatically." : `Copy ${interactionLink} verbatim. The owner must review this exact publisher source or local execution plan before any probe, credential submission or execution. Do not ask for secrets or an additional continue reply in chat.` : this.canProvideToken(goal) ? `The service refused access. Copy this Markdown link verbatim for secure first-time Token input: ${interactionLink} . Never rewrite its destination as xopc://workspace or add an origin. A refusal alone does not prove a missing Token; service or account permissions may also block access. Do not request secrets in chat or repeatedly retry.` : goal.phase === "blocked" ? "The connection check failed. Report the safe error code and the remaining blocker. Do not repeatedly retry without resolving the cause." : goal.reloadRequired ? "Configuration is saved but runtime reload failed. Report the partial result and require a Gateway restart; do not claim the tools are active or tested." : goal.phase === "ready" ? "Configuration is saved. The host queues the original objective once in a fresh turn. If this is that continuation, discover native tools by the exact server namespace and finish the original objective; otherwise stop and let the queued continuation run. Do not repeat installation or invent a successful read." : goal.phase === "planned" ? "Continue automatic steps with advance and the returned version." : `Copy this Markdown link verbatim for authorization or Token input: ${interactionLink} . Never rewrite its destination as xopc://workspace or add an origin. Then stop this turn. The host resumes automatically; never ask for credentials, callback URLs or a continue reply in chat.`
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
cancelGoal(goal) {
|
|
157
|
+
clearTimeout(this.retryTimers.get(goal.id));
|
|
158
|
+
this.retryTimers.delete(goal.id);
|
|
159
|
+
goal.phase = "cancelled";
|
|
160
|
+
this.save(goal);
|
|
161
|
+
const draftId = this.draftIds.get(goal.id);
|
|
162
|
+
if (draftId) try {
|
|
163
|
+
this.drafts.remove("local-owner", draftId);
|
|
164
|
+
} catch {}
|
|
165
|
+
this.draftIds.delete(goal.id);
|
|
166
|
+
return this.view(goal);
|
|
167
|
+
}
|
|
168
|
+
async cancelConversation(conversationId) {
|
|
169
|
+
this.discovery.cancelConversation(conversationId);
|
|
170
|
+
for (const goal of this.goals.values().filter((g) => g.conversationId === conversationId && g.phase !== "cancelled")) this.cancelGoal(goal);
|
|
171
|
+
}
|
|
172
|
+
revokeWeixinRequests(accountId, peerId) {
|
|
173
|
+
for (const goal of this.goals.values()) if (goal.channel?.accountId === accountId && goal.channel.peerId.toLowerCase() === peerId.toLowerCase() && goal.phase !== "cancelled") this.cancelGoal(goal);
|
|
174
|
+
}
|
|
175
|
+
reconcileWeixinScopes() {
|
|
176
|
+
for (const goal of this.goals.values().filter((item) => item.channel && item.phase !== "cancelled")) try {
|
|
177
|
+
this.current(goal);
|
|
178
|
+
} catch {}
|
|
179
|
+
}
|
|
180
|
+
inspect() {
|
|
181
|
+
return {
|
|
182
|
+
servers: Object.entries(this.options.readConfig().mcp?.servers ?? {}).map(([serverId, server]) => ({
|
|
183
|
+
serverId,
|
|
184
|
+
displayName: server.displayName,
|
|
185
|
+
enabled: server.enabled !== false,
|
|
186
|
+
transport: server.command ? "stdio" : "http",
|
|
187
|
+
managed: isManagedConnectorServer(server) || Boolean(server.xopcPlugin),
|
|
188
|
+
revision: mcpConfigRevision(server),
|
|
189
|
+
hasCredentialReference: Boolean(server.auth || server.headers || server.xopcOAuthCredentialId)
|
|
190
|
+
})),
|
|
191
|
+
managementPath: "/capabilities/connectors?tab=connected"
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
currentForConversation(conversationId) {
|
|
195
|
+
const session = getSessionMetadata(conversationId);
|
|
196
|
+
if (!session) return { setup: null };
|
|
197
|
+
const goal = this.goals.values(void 0, true).find((item) => item.conversationId === conversationId && item.transcriptId === session.transcriptId && item.agentId === session.agentId && item.phase !== "cancelled" && (item.phase !== "ready" || !item.resumed || item.reloadRequired));
|
|
198
|
+
return { setup: goal ? this.view(goal) : null };
|
|
199
|
+
}
|
|
200
|
+
async command(command, input, context, dryRun = false) {
|
|
201
|
+
const activeSession = getSessionMetadata(context.conversationId);
|
|
202
|
+
if (!activeSession || activeSession.agentId !== context.agentId) throw new McpDraftError(404, "Owner conversation required.");
|
|
203
|
+
const localOwner = connectorPrincipalForSession(context.conversationId).isLocalOwner;
|
|
204
|
+
const channel = context.canRequestWeixinSetup ? weixinSetupScope(context.conversationId, this.options.readConfig()) : void 0;
|
|
205
|
+
if (!localOwner && !channel) throw new McpDraftError(404, "A paired, account-isolated Weixin direct conversation and a secure Gateway public URL are required. Shared/merged routing is not eligible.");
|
|
206
|
+
if (channel && ![
|
|
207
|
+
"discover",
|
|
208
|
+
"propose",
|
|
209
|
+
"select",
|
|
210
|
+
"repair",
|
|
211
|
+
"start",
|
|
212
|
+
"get",
|
|
213
|
+
"cancel",
|
|
214
|
+
"advance"
|
|
215
|
+
].includes(command)) throw new McpDraftError(409, "Weixin configuration requires approval for a specific new connection on the secure page.");
|
|
216
|
+
if ([
|
|
217
|
+
"discover",
|
|
218
|
+
"propose",
|
|
219
|
+
"select"
|
|
220
|
+
].includes(command)) {
|
|
221
|
+
if (!context.canConfigure && !channel) throw new McpDraftError(409, "An active owner turn is required.");
|
|
222
|
+
if (dryRun) return {
|
|
223
|
+
dryRun: true,
|
|
224
|
+
instruction: "Discovery and candidate state were not changed."
|
|
225
|
+
};
|
|
226
|
+
return this.discovery.command(command, input, context);
|
|
227
|
+
}
|
|
228
|
+
if (command === "inspect") {
|
|
229
|
+
z.object({}).strict().parse(input);
|
|
230
|
+
return this.inspect();
|
|
231
|
+
}
|
|
232
|
+
if (command === "get") {
|
|
233
|
+
const args = setupSchema.parse(input);
|
|
234
|
+
return this.view(this.get(args.setupId, context.conversationId));
|
|
235
|
+
}
|
|
236
|
+
if (!context.canConfigure && !channel) throw new McpDraftError(409, "An active owner App or local CLI turn is required for MCP configuration.");
|
|
237
|
+
if (command === "repair") {
|
|
238
|
+
const args = setupSchema.extend({
|
|
239
|
+
planId: z.string().uuid(),
|
|
240
|
+
expectedPlanVersion: z.number().int().positive()
|
|
241
|
+
}).strict().parse(input);
|
|
242
|
+
const goal = this.get(args.setupId, context.conversationId);
|
|
243
|
+
this.current(goal);
|
|
244
|
+
if (goal.version !== args.expectedVersion || goal.expiresAt < Date.now() || goal.phase !== "blocked" || goal.diagnosis?.recovery?.kind !== "verify_documented_endpoint") throw new McpDraftError(409, "This objective does not permit endpoint repair.");
|
|
245
|
+
const selected = this.discovery.selected(args.planId, args.expectedPlanVersion, context);
|
|
246
|
+
if (selected.purpose !== goal.purpose || selected.plan.url === goal.url && (selected.plan.transport ?? "streamable-http") === (goal.transport ?? "streamable-http")) throw new McpDraftError(409, "Repair needs the original objective and a documented different endpoint or transport.");
|
|
247
|
+
if (dryRun) return {
|
|
248
|
+
dryRun: true,
|
|
249
|
+
instruction: "The original objective and all existing credentials remain unchanged."
|
|
250
|
+
};
|
|
251
|
+
const revision = mcpConfigRevision(configuredServer(this.options.readConfig(), goal.serverId));
|
|
252
|
+
if (revision !== goal.expectedRevision) throw new McpDraftError(409, "The saved connection changed. Inspect before repairing.");
|
|
253
|
+
this.cancelGoal(goal);
|
|
254
|
+
return this.command("start", {
|
|
255
|
+
planId: args.planId,
|
|
256
|
+
expectedPlanVersion: args.expectedPlanVersion,
|
|
257
|
+
serverId: goal.serverId,
|
|
258
|
+
purpose: goal.purpose,
|
|
259
|
+
...!channel ? { expectedRevision: revision } : {}
|
|
260
|
+
}, context);
|
|
261
|
+
}
|
|
262
|
+
if (command === "start") {
|
|
263
|
+
if (getActiveConnectionWait(context.conversationId)) throw new McpDraftError(409, "Another connection objective is waiting. Finish or cancel it before starting a separate MCP setup.");
|
|
264
|
+
const args = targetSchema.parse(input);
|
|
265
|
+
let selected;
|
|
266
|
+
if (args.planId) {
|
|
267
|
+
if (!args.expectedPlanVersion || args.url || args.execution || args.authentication || args.secretFields || args.transport || args.helpUrl || args.objective) throw new McpDraftError(400, "Use the selected plan without overriding its configuration.");
|
|
268
|
+
selected = this.discovery.selected(args.planId, args.expectedPlanVersion, context);
|
|
269
|
+
Object.assign(args, selected.plan);
|
|
270
|
+
args.purpose = selected.purpose;
|
|
271
|
+
}
|
|
272
|
+
const stdio = args.transport === "stdio";
|
|
273
|
+
for (const reference of [args.helpUrl, args.execution?.sourceUrl].filter((v) => Boolean(v))) {
|
|
274
|
+
const parsed = new URL(reference);
|
|
275
|
+
if (!["https:", "http:"].includes(parsed.protocol) || parsed.username || parsed.password || [...parsed.searchParams.keys()].some((key) => /token|secret|password|api.?key|authorization/i.test(key))) throw new McpDraftError(400, "Use a public integration guide without embedded credentials.");
|
|
276
|
+
}
|
|
277
|
+
if (stdio ? !args.execution || args.url : !args.url || args.execution) throw new McpDraftError(400, "Provide one HTTP URL or stdio execution plan.");
|
|
278
|
+
const url = new URL(stdio ? `stdio://localhost/${args.serverId}` : args.url);
|
|
279
|
+
if ([
|
|
280
|
+
"__proto__",
|
|
281
|
+
"constructor",
|
|
282
|
+
"prototype"
|
|
283
|
+
].includes(args.serverId.toLowerCase())) throw new McpDraftError(400, "Use a non-reserved server name.");
|
|
284
|
+
if (!stdio && (!["http:", "https:"].includes(url.protocol) || url.username || url.password || [...url.searchParams.keys()].some((key) => /token|secret|password|api.?key|authorization/i.test(key)))) throw new McpDraftError(400, "Use an HTTP MCP address without embedded credentials. Enter secrets only in the secure page.");
|
|
285
|
+
if (args.secretFields?.some((field) => field.location !== (stdio ? "env" : "header"))) throw new McpDraftError(400, "Credential fields do not match the selected transport.");
|
|
286
|
+
if (args.authentication === "bearer" && args.secretFields?.length) {
|
|
287
|
+
if (args.secretFields.length !== 1 || args.secretFields[0].location !== "header" || args.secretFields[0].name.toLowerCase() !== "authorization") throw new McpDraftError(400, "Bearer authentication uses one Authorization credential field.");
|
|
288
|
+
args.secretFields[0].prefix = "Bearer ";
|
|
289
|
+
}
|
|
290
|
+
if (args.authentication === "header" && !args.secretFields?.length) throw new McpDraftError(400, "Describe the documented header fields.");
|
|
291
|
+
if (!stdio && (args.authentication === "bearer" || args.secretFields?.length) && url.protocol !== "https:" && ![
|
|
292
|
+
"127.0.0.1",
|
|
293
|
+
"localhost",
|
|
294
|
+
"[::1]"
|
|
295
|
+
].includes(url.hostname)) throw new McpDraftError(400, "Token authentication requires HTTPS or a loopback server.");
|
|
296
|
+
const session = getSessionMetadata(context.conversationId);
|
|
297
|
+
if (!session?.transcriptId || session.agentId !== context.agentId) throw new McpDraftError(409, "Conversation identity changed.");
|
|
298
|
+
if (channel) {
|
|
299
|
+
if (args.expectedRevision !== void 0) throw new McpDraftError(409, "Existing connection changes require owner management.");
|
|
300
|
+
args.displayName ??= args.serverId;
|
|
301
|
+
args.serverId = `weixin-${createHash("sha256").update(`${channel.principalId}\0${url.href}`).digest("hex").slice(0, 16)}`;
|
|
302
|
+
}
|
|
303
|
+
const server = configuredServer(this.options.readConfig(), args.serverId);
|
|
304
|
+
if (channel && server?.enabled !== false && server?.url === url.href && !isManagedConnectorServer(server) && !server.xopcPlugin) return {
|
|
305
|
+
alreadyConfigured: true,
|
|
306
|
+
serverId: args.serverId,
|
|
307
|
+
displayName: server.displayName,
|
|
308
|
+
instruction: "This exact service is already saved. Discover its actual native tools and complete the current read without another configuration. Runtime readiness and the business result still need an actual tool call."
|
|
309
|
+
};
|
|
310
|
+
if (channel && server) throw new McpDraftError(409, "Replacing an existing connection requires its owner management page.");
|
|
311
|
+
if (server && args.expectedRevision !== mcpConfigRevision(server)) throw new McpDraftError(409, "Read inspect and provide the current server revision before replacing it.");
|
|
312
|
+
if (server && (isManagedConnectorServer(server) || server.xopcPlugin)) throw new McpDraftError(409, "Manage this service through its owning connector or plugin.");
|
|
313
|
+
if (dryRun) return {
|
|
314
|
+
dryRun: true,
|
|
315
|
+
serverId: args.serverId,
|
|
316
|
+
authentication: args.authentication === "bearer" ? "token_required" : "probe_required"
|
|
317
|
+
};
|
|
318
|
+
const existing = this.goals.values().find((goal) => goal.conversationId === context.conversationId && goal.transcriptId === session.transcriptId && JSON.stringify([
|
|
319
|
+
goal.transport ?? "streamable-http",
|
|
320
|
+
goal.execution,
|
|
321
|
+
goal.secretFields,
|
|
322
|
+
goal.helpUrl,
|
|
323
|
+
goal.objective
|
|
324
|
+
]) === JSON.stringify([
|
|
325
|
+
args.transport ?? "streamable-http",
|
|
326
|
+
args.execution,
|
|
327
|
+
args.secretFields,
|
|
328
|
+
args.helpUrl,
|
|
329
|
+
args.objective
|
|
330
|
+
]) && JSON.stringify(goal.sources) === JSON.stringify(selected?.sources) && goal.serverId === args.serverId && goal.url === url.href && goal.purpose === args.purpose && goal.displayName === args.displayName && (goal.authentication ?? "auto") === (args.authentication ?? "auto") && goal.phase !== "cancelled" && goal.phase !== "ready" && goal.expiresAt > Date.now());
|
|
331
|
+
if (existing) return this.view(existing);
|
|
332
|
+
for (const previous of this.goals.values().filter((item) => item.conversationId === context.conversationId && (item.phase !== "ready" || !item.resumed) && item.phase !== "cancelled")) this.cancelGoal(previous);
|
|
333
|
+
const goal = {
|
|
334
|
+
id: randomUUID(),
|
|
335
|
+
conversationId: context.conversationId,
|
|
336
|
+
transcriptId: session.transcriptId,
|
|
337
|
+
agentId: context.agentId,
|
|
338
|
+
serverId: args.serverId,
|
|
339
|
+
displayName: args.displayName,
|
|
340
|
+
url: url.href,
|
|
341
|
+
purpose: args.purpose,
|
|
342
|
+
authentication: args.authentication,
|
|
343
|
+
transport: args.transport,
|
|
344
|
+
execution: args.execution,
|
|
345
|
+
secretFields: args.secretFields,
|
|
346
|
+
helpUrl: args.helpUrl,
|
|
347
|
+
objective: args.objective,
|
|
348
|
+
reviewRequired: stdio || Boolean(selected),
|
|
349
|
+
publicOnly: Boolean(selected && !stdio),
|
|
350
|
+
sources: selected?.sources,
|
|
351
|
+
expectedRevision: mcpConfigRevision(server),
|
|
352
|
+
version: 1,
|
|
353
|
+
phase: channel || stdio || selected ? "approval_required" : "planned",
|
|
354
|
+
...channel ? { channel } : {},
|
|
355
|
+
expiresAt: Date.now() + 15 * 6e4
|
|
356
|
+
};
|
|
357
|
+
this.goals.set(goal.id, goal);
|
|
358
|
+
this.notify(goal);
|
|
359
|
+
return this.view(goal);
|
|
360
|
+
}
|
|
361
|
+
if (command === "remove" || command === "set_enabled") {
|
|
362
|
+
const args = serverSchema.parse(input);
|
|
363
|
+
if (command === "set_enabled" && args.enabled === void 0) throw new McpDraftError(400, "enabled is required.");
|
|
364
|
+
if (dryRun) return {
|
|
365
|
+
dryRun: true,
|
|
366
|
+
serverId: args.serverId
|
|
367
|
+
};
|
|
368
|
+
return this.options.withConfigLock(async () => {
|
|
369
|
+
const config = this.options.readConfig(), server = configuredServer(config, args.serverId);
|
|
370
|
+
if (!server || isManagedConnectorServer(server) || server.xopcPlugin || mcpConfigRevision(server) !== args.expectedRevision) throw new McpDraftError(409, "The custom server changed or belongs to another owner. Inspect again.");
|
|
371
|
+
for (const goal of this.goals.values().filter((item) => item.serverId === args.serverId && item.phase !== "ready" && item.phase !== "cancelled")) this.cancelGoal(goal);
|
|
372
|
+
const next = structuredClone(config);
|
|
373
|
+
if (command === "remove") delete next.mcp.servers[args.serverId];
|
|
374
|
+
else next.mcp.servers[args.serverId].enabled = args.enabled;
|
|
375
|
+
const result = await this.options.saveConfig(next, structuredClone(config));
|
|
376
|
+
if (result.conflict || !result.saved && !result.persisted) throw new McpDraftError(409, "Configuration could not be applied. Inspect before retrying.");
|
|
377
|
+
return {
|
|
378
|
+
saved: true,
|
|
379
|
+
removed: command === "remove",
|
|
380
|
+
enabled: command === "set_enabled" ? args.enabled : void 0,
|
|
381
|
+
reloadRequired: !result.saved,
|
|
382
|
+
remoteAuthorizationRevoked: false,
|
|
383
|
+
instruction: "This changes local configuration only. Remote authorization and installed packages are not removed."
|
|
384
|
+
};
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
const args = setupSchema.parse(input), goal = this.get(args.setupId, context.conversationId);
|
|
388
|
+
if (!["advance", "cancel"].includes(command)) throw new McpDraftError(400, "Supported MCP setup commands: inspect, start, get, advance, cancel, set_enabled, remove.");
|
|
389
|
+
if (args.expectedVersion !== goal.version) throw new McpDraftError(409, "Setup changed. Read get before retrying.");
|
|
390
|
+
if (dryRun) return {
|
|
391
|
+
dryRun: true,
|
|
392
|
+
...this.view(goal)
|
|
393
|
+
};
|
|
394
|
+
if (command === "cancel") return this.cancelGoal(goal);
|
|
395
|
+
return this.advance(goal);
|
|
396
|
+
}
|
|
397
|
+
async advance(goal) {
|
|
398
|
+
this.current(goal);
|
|
399
|
+
if (goal.phase === "approval_required") return this.view(goal);
|
|
400
|
+
if (goal.channel && !goal.approvedBy) throw new McpDraftError(409, "Owner approval is required.");
|
|
401
|
+
if (goal.phase === "ready") {
|
|
402
|
+
await this.resume(goal);
|
|
403
|
+
return this.view(goal);
|
|
404
|
+
}
|
|
405
|
+
if (goal.expiresAt < Date.now()) throw new McpDraftError(409, "Setup expired. Start a new goal; do not reuse an old authorization.");
|
|
406
|
+
if (goal.nextRetryAt && Date.now() < goal.nextRetryAt) {
|
|
407
|
+
this.scheduleRetry(goal);
|
|
408
|
+
return this.view(goal);
|
|
409
|
+
}
|
|
410
|
+
if (this.busy.has(goal.id)) return {
|
|
411
|
+
...this.view(goal),
|
|
412
|
+
inProgress: true
|
|
413
|
+
};
|
|
414
|
+
this.busy.add(goal.id);
|
|
415
|
+
try {
|
|
416
|
+
const published = configuredServer(this.options.readConfig(), goal.serverId);
|
|
417
|
+
if (published?.xopcSetupId === goal.id) {
|
|
418
|
+
goal.phase = "ready";
|
|
419
|
+
goal.committedRevision = mcpConfigRevision(published);
|
|
420
|
+
this.save(goal);
|
|
421
|
+
await this.resume(goal);
|
|
422
|
+
return this.view(goal);
|
|
423
|
+
}
|
|
424
|
+
if (mcpConfigRevision(published) !== goal.expectedRevision) throw new McpDraftError(409, "Server changed. Start again from the current configuration.");
|
|
425
|
+
let draftId = this.draftIds.get(goal.id);
|
|
426
|
+
if (!draftId) {
|
|
427
|
+
const fields = goal.secretFields?.length ? goal.secretFields : [{
|
|
428
|
+
id: "token",
|
|
429
|
+
name: "Authorization",
|
|
430
|
+
location: "header",
|
|
431
|
+
prefix: "Bearer ",
|
|
432
|
+
label: "Token"
|
|
433
|
+
}];
|
|
434
|
+
const secretConfig = {};
|
|
435
|
+
for (const field of fields) {
|
|
436
|
+
const provider = goal.secretProviders?.[field.id] ?? (field.id === "token" ? goal.tokenProvider : void 0);
|
|
437
|
+
if (provider) (secretConfig[field.location === "env" ? "env" : "headers"] ??= {})[field.name] = { xopcSecretRef: {
|
|
438
|
+
provider,
|
|
439
|
+
fieldKey: field.id,
|
|
440
|
+
prefix: field.prefix
|
|
441
|
+
} };
|
|
442
|
+
}
|
|
443
|
+
const draft = await this.drafts.create("local-owner", {
|
|
444
|
+
serverId: goal.serverId,
|
|
445
|
+
...published ? {
|
|
446
|
+
sourceServerId: goal.serverId,
|
|
447
|
+
expectedServer: published
|
|
448
|
+
} : {},
|
|
449
|
+
server: {
|
|
450
|
+
...goal.transport === "stdio" ? {
|
|
451
|
+
...goal.execution,
|
|
452
|
+
sourceUrl: void 0,
|
|
453
|
+
type: "stdio",
|
|
454
|
+
xopcManagedStdio: true
|
|
455
|
+
} : {
|
|
456
|
+
url: goal.url,
|
|
457
|
+
type: goal.transport ?? "streamable-http"
|
|
458
|
+
},
|
|
459
|
+
displayName: goal.displayName,
|
|
460
|
+
enabled: true,
|
|
461
|
+
xopcSetupId: goal.id,
|
|
462
|
+
xopcPublicOnly: goal.publicOnly,
|
|
463
|
+
...secretConfig
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
this.current(goal);
|
|
467
|
+
draftId = draft.id;
|
|
468
|
+
this.draftIds.set(goal.id, draftId);
|
|
469
|
+
if (goal.phase === "authorizing") {
|
|
470
|
+
goal.phase = "planned";
|
|
471
|
+
this.save(goal);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
if (goal.authentication === "bearer" && !goal.secretFields?.length && !goal.tokenProvider && !goal.secretProviders?.token || goal.secretFields?.some((field) => !goal.secretProviders?.[field.id])) {
|
|
475
|
+
goal.phase = "token_required";
|
|
476
|
+
goal.errorCode = void 0;
|
|
477
|
+
this.save(goal);
|
|
478
|
+
return this.view(goal);
|
|
479
|
+
}
|
|
480
|
+
if (goal.phase === "authorizing") {
|
|
481
|
+
const auth = this.drafts.authorization("local-owner", draftId);
|
|
482
|
+
if (auth.state === "error" || auth.state === "cancelled") {
|
|
483
|
+
goal.phase = "blocked";
|
|
484
|
+
goal.errorCode = "authorization_failed";
|
|
485
|
+
this.save(goal);
|
|
486
|
+
return this.view(goal);
|
|
487
|
+
}
|
|
488
|
+
if (auth.state !== "connected") return this.view(goal);
|
|
489
|
+
} else {
|
|
490
|
+
if ((goal.attempts ?? 0) >= 3) {
|
|
491
|
+
goal.phase = "blocked";
|
|
492
|
+
goal.nextRetryAt = void 0;
|
|
493
|
+
goal.diagnosis = {
|
|
494
|
+
...goal.diagnosis,
|
|
495
|
+
recovery: {
|
|
496
|
+
kind: "report_blocker",
|
|
497
|
+
reason: "retry_budget_exhausted"
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
this.save(goal);
|
|
501
|
+
return this.view(goal);
|
|
502
|
+
}
|
|
503
|
+
goal.attempts = (goal.attempts ?? 0) + 1;
|
|
504
|
+
goal.nextRetryAt = void 0;
|
|
505
|
+
this.save(goal);
|
|
506
|
+
const probe = await this.drafts.probe("local-owner", draftId, { beforeRequest: (request) => {
|
|
507
|
+
this.current(goal);
|
|
508
|
+
const key = `${request?.method ?? "GET"}:${request?.stage ?? "metadata"}`;
|
|
509
|
+
goal.requestCounts ??= {};
|
|
510
|
+
if ((goal.requestCounts[key] ?? 0) >= 3) throw new Error("MCP retry budget exhausted for this protocol stage");
|
|
511
|
+
goal.requestCounts[key] = (goal.requestCounts[key] ?? 0) + 1;
|
|
512
|
+
this.goals.set(goal.id, goal);
|
|
513
|
+
} });
|
|
514
|
+
this.current(goal);
|
|
515
|
+
goal.diagnosis = {
|
|
516
|
+
auth: probe.auth,
|
|
517
|
+
observation: probe.observation,
|
|
518
|
+
recovery: probe.recovery
|
|
519
|
+
};
|
|
520
|
+
if (probe.state !== "connected") {
|
|
521
|
+
goal.phase = probe.state === "error" ? "blocked" : probe.state;
|
|
522
|
+
goal.errorCode = probe.state === "token_required" && (goal.tokenProvider || goal.secretProviders) ? "credential_rejected" : probe.errorCode;
|
|
523
|
+
if ((probe.recovery?.kind === "wait" || [
|
|
524
|
+
"network",
|
|
525
|
+
"timeout",
|
|
526
|
+
"connection_refused"
|
|
527
|
+
].includes(probe.errorCode ?? "")) && (goal.attempts ?? 0) < 3) goal.nextRetryAt = probe.recovery?.retryAt ?? Date.now() + (goal.attempts === 1 ? 2e3 : 5e3);
|
|
528
|
+
this.save(goal);
|
|
529
|
+
this.scheduleRetry(goal);
|
|
530
|
+
return this.view(goal);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
const result = await this.options.withConfigLock(async () => {
|
|
534
|
+
this.current(goal);
|
|
535
|
+
return this.drafts.commit("local-owner", draftId, true);
|
|
536
|
+
});
|
|
537
|
+
goal.phase = "ready";
|
|
538
|
+
goal.errorCode = void 0;
|
|
539
|
+
goal.reloadRequired = result.reloadRequired === true;
|
|
540
|
+
goal.committedRevision = mcpConfigRevision(configuredServer(this.options.readConfig(), goal.serverId));
|
|
541
|
+
this.current(goal);
|
|
542
|
+
this.save(goal);
|
|
543
|
+
this.draftIds.delete(goal.id);
|
|
544
|
+
await this.resume(goal);
|
|
545
|
+
return this.view(goal);
|
|
546
|
+
} catch (error) {
|
|
547
|
+
this.current(goal);
|
|
548
|
+
if (error instanceof McpDraftError) {
|
|
549
|
+
if (error.status === 404) {
|
|
550
|
+
this.draftIds.delete(goal.id);
|
|
551
|
+
goal.phase = "planned";
|
|
552
|
+
this.save(goal);
|
|
553
|
+
return {
|
|
554
|
+
...this.view(goal),
|
|
555
|
+
requiresRecheck: true
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
throw error;
|
|
559
|
+
}
|
|
560
|
+
goal.phase = "blocked";
|
|
561
|
+
goal.errorCode = classifyMcpConnectionError(error);
|
|
562
|
+
this.save(goal);
|
|
563
|
+
return this.view(goal);
|
|
564
|
+
} finally {
|
|
565
|
+
this.busy.delete(goal.id);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
scheduleRetry(goal) {
|
|
569
|
+
if (this.retryTimers.has(goal.id) || !goal.nextRetryAt || goal.nextRetryAt >= goal.expiresAt || this.disposed) return;
|
|
570
|
+
const version = goal.version;
|
|
571
|
+
const timer = setTimeout(() => {
|
|
572
|
+
this.retryTimers.delete(goal.id);
|
|
573
|
+
if (this.disposed) return;
|
|
574
|
+
try {
|
|
575
|
+
const current = this.goals.get(goal.id);
|
|
576
|
+
if (!current || current.version !== version) return;
|
|
577
|
+
this.advance(current).catch(() => {});
|
|
578
|
+
} catch {}
|
|
579
|
+
}, Math.max(1, goal.nextRetryAt - Date.now()));
|
|
580
|
+
timer.unref();
|
|
581
|
+
this.retryTimers.set(goal.id, timer);
|
|
582
|
+
}
|
|
583
|
+
/** Owner-only UI; secret values and OAuth URLs never pass through the model API. */
|
|
584
|
+
async interact(id, action, value, expectedVersion, ownerPrincipalId = "local-owner") {
|
|
585
|
+
const goal = this.get(id);
|
|
586
|
+
if (!goal.channel && !connectorPrincipalForSession(goal.conversationId).isLocalOwner) throw new McpDraftError(404, "Owner conversation required.");
|
|
587
|
+
if (action === "get") {
|
|
588
|
+
let authorizationUrl, authState;
|
|
589
|
+
const session = getSessionMetadata(goal.conversationId);
|
|
590
|
+
try {
|
|
591
|
+
this.current(goal);
|
|
592
|
+
} catch {
|
|
593
|
+
return {
|
|
594
|
+
...this.view(goal),
|
|
595
|
+
phase: "cancelled",
|
|
596
|
+
endpointOrigin: new URL(goal.url).origin
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
if (session?.transcriptId !== goal.transcriptId || session.agentId !== goal.agentId) return {
|
|
600
|
+
...this.view(goal),
|
|
601
|
+
phase: "cancelled",
|
|
602
|
+
endpointOrigin: new URL(goal.url).origin
|
|
603
|
+
};
|
|
604
|
+
const draftId = this.draftIds.get(id);
|
|
605
|
+
if (draftId && goal.phase === "authorizing" && goal.expiresAt > Date.now()) {
|
|
606
|
+
const auth = this.drafts.authorization("local-owner", draftId);
|
|
607
|
+
authorizationUrl = auth.authorizationUrl;
|
|
608
|
+
authState = auth.state;
|
|
609
|
+
}
|
|
610
|
+
return {
|
|
611
|
+
...this.view(goal),
|
|
612
|
+
endpointOrigin: goal.transport === "stdio" ? "Gateway local process" : new URL(goal.url).origin,
|
|
613
|
+
approval: goal.channel ? {
|
|
614
|
+
...goal.channel,
|
|
615
|
+
endpoint: goal.url,
|
|
616
|
+
purpose: goal.purpose
|
|
617
|
+
} : void 0,
|
|
618
|
+
canReplaceToken: Boolean(goal.tokenProvider || goal.secretProviders),
|
|
619
|
+
authorizationUrl,
|
|
620
|
+
authState,
|
|
621
|
+
requiresRecheck: !draftId && goal.phase !== "ready" && goal.phase !== "cancelled" && goal.phase !== "approval_required"
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
this.current(goal);
|
|
625
|
+
if (action === "retry_delivery" && goal.channel && goal.phase === "ready" && goal.reply?.status === "delivered") return this.view(goal);
|
|
626
|
+
if (expectedVersion !== goal.version) throw new McpDraftError(409, "The secure form changed. Refresh before submitting.");
|
|
627
|
+
if (action === "cancel") return this.cancelGoal(goal);
|
|
628
|
+
if (action === "retry_delivery") {
|
|
629
|
+
if (!goal.channel || goal.phase !== "ready" || goal.reply?.status !== "failed" || goal.expiresAt < Date.now()) throw new McpDraftError(409, "This result cannot be resent.");
|
|
630
|
+
await this.deliverReply(goal);
|
|
631
|
+
return this.view(this.get(id));
|
|
632
|
+
}
|
|
633
|
+
if (goal.expiresAt < Date.now() || goal.phase === "ready") throw new McpDraftError(409, "This setup no longer accepts input.");
|
|
634
|
+
if (action === "approve") {
|
|
635
|
+
if (!(goal.channel || goal.reviewRequired) || goal.phase !== "approval_required" || !ownerPrincipalId) throw new McpDraftError(409, "This request cannot be approved.");
|
|
636
|
+
goal.approvedBy = ownerPrincipalId;
|
|
637
|
+
goal.phase = "planned";
|
|
638
|
+
this.save(goal);
|
|
639
|
+
return this.advance(goal);
|
|
640
|
+
}
|
|
641
|
+
if (goal.phase === "approval_required") throw new McpDraftError(409, "Approve the exact Weixin request before continuing.");
|
|
642
|
+
if (action === "token") {
|
|
643
|
+
if (!(goal.phase === "token_required" || goal.phase === "blocked" && (goal.tokenProvider || goal.secretProviders) || this.canProvideToken(goal))) throw new McpDraftError(400, "A token is required for this setup.");
|
|
644
|
+
if (goal.nextRetryAt && Date.now() < goal.nextRetryAt) throw new McpDraftError(409, "The service cooldown has not expired. Wait before submitting credentials.");
|
|
645
|
+
const fields = goal.secretFields?.length ? goal.secretFields : [{
|
|
646
|
+
id: "token",
|
|
647
|
+
name: "Authorization",
|
|
648
|
+
location: "header",
|
|
649
|
+
prefix: "Bearer ",
|
|
650
|
+
label: "Token"
|
|
651
|
+
}];
|
|
652
|
+
const values = typeof value === "string" && fields.length === 1 ? { [fields[0].id]: value } : value;
|
|
653
|
+
if (!values || typeof values !== "object" || Object.keys(values).length !== fields.length || fields.some((field) => !Object.hasOwn(values, field.id) || typeof values[field.id] !== "string" || !values[field.id].trim() || values[field.id].length > 16384 || /[\r\n\0]/.test(values[field.id]))) throw new McpDraftError(400, "Provide every requested secret field without control characters.");
|
|
654
|
+
if (this.busy.has(id)) throw new McpDraftError(409, "A check is in progress.");
|
|
655
|
+
const url = new URL(goal.url);
|
|
656
|
+
if (goal.transport !== "stdio" && url.protocol !== "https:" && ![
|
|
657
|
+
"127.0.0.1",
|
|
658
|
+
"localhost",
|
|
659
|
+
"[::1]"
|
|
660
|
+
].includes(url.hostname)) throw new McpDraftError(400, "Token authentication requires HTTPS or a loopback server.");
|
|
661
|
+
this.busy.add(id);
|
|
662
|
+
this.save(goal);
|
|
663
|
+
const providers = {};
|
|
664
|
+
const credentials = new CredentialResolver();
|
|
665
|
+
try {
|
|
666
|
+
for (const field of fields) {
|
|
667
|
+
const provider = connectorSecretProviderId(`mcp-setup-${id}-${goal.version}`, field.id);
|
|
668
|
+
providers[field.id] = provider;
|
|
669
|
+
await credentials.saveApiKey(provider, values[field.id].trim());
|
|
670
|
+
this.current(goal);
|
|
671
|
+
}
|
|
672
|
+
const old = this.draftIds.get(id);
|
|
673
|
+
if (old) try {
|
|
674
|
+
this.drafts.remove("local-owner", old);
|
|
675
|
+
} catch (error) {
|
|
676
|
+
if (!(error instanceof McpDraftError) || error.status !== 404) throw error;
|
|
677
|
+
}
|
|
678
|
+
this.draftIds.delete(id);
|
|
679
|
+
goal.secretProviders = providers;
|
|
680
|
+
goal.tokenProvider = providers.token;
|
|
681
|
+
goal.phase = "planned";
|
|
682
|
+
goal.errorCode = void 0;
|
|
683
|
+
goal.attempts = 0;
|
|
684
|
+
goal.requestCounts = {};
|
|
685
|
+
goal.nextRetryAt = void 0;
|
|
686
|
+
this.save(goal);
|
|
687
|
+
} catch (error) {
|
|
688
|
+
await Promise.all(Object.values(providers).map((provider) => credentials.deleteProfile(`${provider}:default`)));
|
|
689
|
+
throw error;
|
|
690
|
+
} finally {
|
|
691
|
+
this.busy.delete(id);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
if (action === "authorize") {
|
|
695
|
+
if (goal.phase !== "oauth_required") throw new McpDraftError(409, "Recheck the server before authorization.");
|
|
696
|
+
const draftId = this.draftIds.get(id);
|
|
697
|
+
if (!draftId) {
|
|
698
|
+
goal.phase = "planned";
|
|
699
|
+
this.save(goal);
|
|
700
|
+
return this.advance(goal);
|
|
701
|
+
}
|
|
702
|
+
this.drafts.authorize("local-owner", draftId, goal.channel ? { callbackRelayUrl: `${goal.channel.origin}/mcp-setup/callback/${goal.id}` } : void 0);
|
|
703
|
+
goal.phase = "authorizing";
|
|
704
|
+
this.save(goal);
|
|
705
|
+
this.settleAuthorization(goal.id);
|
|
706
|
+
return this.view(goal);
|
|
707
|
+
}
|
|
708
|
+
return this.advance(goal);
|
|
709
|
+
}
|
|
710
|
+
settleAuthorization(id) {
|
|
711
|
+
if (this.authorizations.has(id)) return;
|
|
712
|
+
this.authorizations.add(id);
|
|
713
|
+
(async () => {
|
|
714
|
+
for (;;) {
|
|
715
|
+
await setTimeout$1(250, void 0, { ref: false });
|
|
716
|
+
if (this.disposed) return;
|
|
717
|
+
const goal = this.goals.get(id);
|
|
718
|
+
if (!goal || goal.phase !== "authorizing" || goal.expiresAt < Date.now()) return;
|
|
719
|
+
this.current(goal);
|
|
720
|
+
const draftId = this.draftIds.get(id);
|
|
721
|
+
if (!draftId) return;
|
|
722
|
+
const auth = this.drafts.authorization("local-owner", draftId);
|
|
723
|
+
if (auth.state === "connected") await this.advance(goal);
|
|
724
|
+
else if (auth.state === "error" || auth.state === "cancelled") {
|
|
725
|
+
goal.phase = "blocked";
|
|
726
|
+
goal.errorCode = "authorization_failed";
|
|
727
|
+
this.save(goal);
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
})().catch((error) => {
|
|
732
|
+
try {
|
|
733
|
+
if (this.disposed) return;
|
|
734
|
+
const goal = this.goals.get(id);
|
|
735
|
+
if (!goal || goal.phase !== "authorizing") return;
|
|
736
|
+
this.current(goal);
|
|
737
|
+
goal.phase = "blocked";
|
|
738
|
+
goal.errorCode = error instanceof McpDraftError ? "configuration_changed" : classifyMcpConnectionError(error);
|
|
739
|
+
this.save(goal);
|
|
740
|
+
} catch {}
|
|
741
|
+
}).finally(() => this.authorizations.delete(id));
|
|
742
|
+
}
|
|
743
|
+
dispose() {
|
|
744
|
+
this.disposed = true;
|
|
745
|
+
for (const timer of this.retryTimers.values()) clearTimeout(timer);
|
|
746
|
+
this.retryTimers.clear();
|
|
747
|
+
for (const draftId of this.draftIds.values()) try {
|
|
748
|
+
this.drafts.remove("local-owner", draftId);
|
|
749
|
+
} catch {}
|
|
750
|
+
this.draftIds.clear();
|
|
751
|
+
}
|
|
752
|
+
relayCallback(id, callbackUrl) {
|
|
753
|
+
const goal = this.get(id);
|
|
754
|
+
this.current(goal);
|
|
755
|
+
if (!goal.channel || !goal.approvedBy || goal.phase !== "authorizing" || goal.expiresAt < Date.now()) throw new McpDraftError(409, "Authorization is no longer active.");
|
|
756
|
+
const draftId = this.draftIds.get(id);
|
|
757
|
+
if (!draftId) throw new McpDraftError(409, "Sign in again after the Gateway restart.");
|
|
758
|
+
const auth = this.drafts.authorization("local-owner", draftId);
|
|
759
|
+
if (goal.callbackConsumedForAttempt === auth.id) throw new McpDraftError(409, "Authorization response already received.");
|
|
760
|
+
const actual = new URL(callbackUrl);
|
|
761
|
+
if (actual.origin !== goal.channel.origin || actual.pathname !== `/mcp-setup/callback/${id}`) throw new McpDraftError(400, "Invalid authorization callback.");
|
|
762
|
+
this.drafts.redirect("local-owner", draftId, actual.href);
|
|
763
|
+
goal.callbackConsumedForAttempt = auth.id;
|
|
764
|
+
this.save(goal);
|
|
765
|
+
return `/#/mcp-setup/${goal.id}`;
|
|
766
|
+
}
|
|
767
|
+
async completeContinuation(input, text) {
|
|
768
|
+
if (!input.runId || !this.permitsContinuation(input)) return;
|
|
769
|
+
const goal = this.get(input.clientMessageId.slice(10));
|
|
770
|
+
if (!goal.channel || goal.reply || !text.trim()) return;
|
|
771
|
+
goal.reply = {
|
|
772
|
+
runId: input.runId,
|
|
773
|
+
text,
|
|
774
|
+
status: "pending"
|
|
775
|
+
};
|
|
776
|
+
this.save(goal);
|
|
777
|
+
await this.deliverReply(goal);
|
|
778
|
+
}
|
|
779
|
+
async deliverReply(goal) {
|
|
780
|
+
if (!goal.channel || !goal.reply || goal.reply.status === "delivered" || !this.options.deliver || this.busy.has(`reply:${goal.id}`)) return;
|
|
781
|
+
this.current(goal);
|
|
782
|
+
if (goal.phase !== "ready" || goal.expiresAt < Date.now()) return;
|
|
783
|
+
this.busy.add(`reply:${goal.id}`);
|
|
784
|
+
try {
|
|
785
|
+
await this.options.deliver(goal.channel, goal.reply.text, goal.id);
|
|
786
|
+
const latest = this.get(goal.id);
|
|
787
|
+
this.current(latest);
|
|
788
|
+
if (latest.reply?.runId === goal.reply.runId) {
|
|
789
|
+
latest.reply.status = "delivered";
|
|
790
|
+
this.save(latest);
|
|
791
|
+
}
|
|
792
|
+
} catch {
|
|
793
|
+
const latest = this.get(goal.id);
|
|
794
|
+
if (latest.reply?.runId === goal.reply.runId && latest.phase === "ready") {
|
|
795
|
+
latest.reply.status = "failed";
|
|
796
|
+
this.save(latest);
|
|
797
|
+
}
|
|
798
|
+
} finally {
|
|
799
|
+
this.busy.delete(`reply:${goal.id}`);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
async resume(goal) {
|
|
803
|
+
this.current(goal);
|
|
804
|
+
if (!goal.resumed && goal.expiresAt < Date.now()) {
|
|
805
|
+
goal.phase = "blocked";
|
|
806
|
+
goal.errorCode = "scope_expired";
|
|
807
|
+
this.save(goal);
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
if (goal.resumed || goal.reloadRequired || mcpConfigRevision(configuredServer(this.options.readConfig(), goal.serverId)) !== goal.committedRevision) return;
|
|
811
|
+
const queued = await this.options.resume(goal);
|
|
812
|
+
const latest = this.goals.get(goal.id);
|
|
813
|
+
if (latest && latest.committedRevision === goal.committedRevision && latest.phase === "ready") {
|
|
814
|
+
this.current(latest);
|
|
815
|
+
Object.assign(goal, latest);
|
|
816
|
+
if (latest.resumed) return;
|
|
817
|
+
}
|
|
818
|
+
this.current(goal);
|
|
819
|
+
if (queued) {
|
|
820
|
+
goal.resumed = true;
|
|
821
|
+
this.save(goal);
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
permitsContinuation(input) {
|
|
825
|
+
if (!input.clientMessageId.startsWith("mcp-setup:")) return true;
|
|
826
|
+
const goal = this.goals.get(input.clientMessageId.slice(10));
|
|
827
|
+
if (!goal || goal.phase !== "ready" || goal.reloadRequired || goal.expiresAt < Date.now() || goal.conversationId !== input.conversationId || goal.transcriptId !== input.expectedTranscriptId || input.origin.type !== "system" || input.origin.source !== "internal") return false;
|
|
828
|
+
try {
|
|
829
|
+
this.current(goal);
|
|
830
|
+
return mcpConfigRevision(configuredServer(this.options.readConfig(), goal.serverId)) === goal.committedRevision;
|
|
831
|
+
} catch {
|
|
832
|
+
return false;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
async resumePending(runtimeReloaded = false) {
|
|
836
|
+
for (const goal of this.goals.values().filter((item) => item.phase === "blocked" && item.nextRetryAt)) try {
|
|
837
|
+
this.current(goal);
|
|
838
|
+
this.scheduleRetry(goal);
|
|
839
|
+
} catch {}
|
|
840
|
+
for (const goal of this.goals.values().filter((item) => item.phase === "ready" && item.reply && item.reply.status !== "delivered")) try {
|
|
841
|
+
await this.deliverReply(goal);
|
|
842
|
+
} catch {}
|
|
843
|
+
for (const goal of this.goals.values().filter((item) => item.phase === "ready" && !item.resumed)) {
|
|
844
|
+
if (goal.reloadRequired && runtimeReloaded && mcpConfigRevision(configuredServer(this.options.readConfig(), goal.serverId)) === goal.committedRevision) {
|
|
845
|
+
goal.reloadRequired = false;
|
|
846
|
+
this.save(goal);
|
|
847
|
+
}
|
|
848
|
+
if (goal.reloadRequired) continue;
|
|
849
|
+
try {
|
|
850
|
+
await this.resume(goal);
|
|
851
|
+
} catch {}
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
};
|
|
855
|
+
//#endregion
|
|
856
|
+
export { McpConversationSetup };
|