@xopcai/xopc 0.0.321 → 0.0.323

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/dist/browser-ext/dist/assets/{auth-DKo-NMUY.js → auth-DocRzRlS.js} +95 -21
  2. package/dist/browser-ext/dist/background.js +1 -1
  3. package/dist/browser-ext/dist/sidepanel.html +1 -1
  4. package/dist/browser-ext/dist/sidepanel.js +18 -2
  5. package/dist/browser-ext/manifest.json +1 -1
  6. package/dist/extensions/telegram/xopc.extension.json +1 -1
  7. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-C69p1Gbr.js → agent-avatar-dicebear-DFzmThVi.js} +1 -1
  8. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CAFHadiy.js +1 -0
  9. package/dist/gateway/static/root/assets/agent-plugin-dialog-DYFYiuig.js +1 -0
  10. package/dist/gateway/static/root/assets/{agents-CWR3p3t3.js → agents-BqIlB5Co.js} +1 -1
  11. package/dist/gateway/static/root/assets/{app-link-nL8iPwEr.js → app-link-C6gA5Nck.js} +1 -1
  12. package/dist/gateway/static/root/assets/{app-management-settings-panel-D98bt40S.js → app-management-settings-panel-BgvMRGWe.js} +1 -1
  13. package/dist/gateway/static/root/assets/{appearance-settings-ChMUELAZ.js → appearance-settings-CliHU03A.js} +1 -1
  14. package/dist/gateway/static/root/assets/apps-page-Drt3Foi9.js +1 -0
  15. package/dist/gateway/static/root/assets/{archive-plugin-BIIiu6uP.js → archive-plugin-DnuPpm0u.js} +1 -1
  16. package/dist/gateway/static/root/assets/{attachment-load-CDJpcsCp.js → attachment-load-BiwaK0ie.js} +1 -1
  17. package/dist/gateway/static/root/assets/{automations-page-Cb5a_WOk.js → automations-page-CJSISGQH.js} +1 -1
  18. package/dist/gateway/static/root/assets/automations-workspace-B-Eduqwz.js +7 -0
  19. package/dist/gateway/static/root/assets/{binary-plugins-zp55zQPu.js → binary-plugins-KDjduQZO.js} +1 -1
  20. package/dist/gateway/static/root/assets/{block-editor-B0CTIZb-.js → block-editor-bclvgove.js} +3 -3
  21. package/dist/gateway/static/root/assets/{browser-automation-inputs-Bx3W4J4H.js → browser-automation-inputs-CfQ2T9t6.js} +1 -1
  22. package/dist/gateway/static/root/assets/{browser-automations-page-D5Lr9b8a.js → browser-automations-page-Cxq38Nnp.js} +2 -2
  23. package/dist/gateway/static/root/assets/browser-settings-page-Dwgir6mu.js +3 -0
  24. package/dist/gateway/static/root/assets/capabilities-settings-panel-H5L5vynP.js +8 -0
  25. package/dist/gateway/static/root/assets/capabilities-uFKh3Hd0.js +1 -0
  26. package/dist/gateway/static/root/assets/channels-settings-RFBRYe5S.js +1 -0
  27. package/dist/gateway/static/root/assets/{chat-terminal-dock-1I1PdIq0.js → chat-terminal-dock-DKQC62nQ.js} +2 -2
  28. package/dist/gateway/static/root/assets/{computer-settings-page-BT-EfoI6.js → computer-settings-page-D1whpIqL.js} +1 -1
  29. package/dist/gateway/static/root/assets/{connector-service-page-mhQ-19tj.js → connector-service-page-BAuYTgf5.js} +1 -1
  30. package/dist/gateway/static/root/assets/connectors-page-Px-v3Q6Q.js +2 -0
  31. package/dist/gateway/static/root/assets/{date-picker-BqcldZoN.js → date-picker-CfCo3lqh.js} +1 -1
  32. package/dist/gateway/static/root/assets/{dependency-picker-DLDLJx3D.js → dependency-picker-DOuVO2M1.js} +1 -1
  33. package/dist/gateway/static/root/assets/{desktop-pet-kSFeHyrt.js → desktop-pet-D9tu6Bhu.js} +1 -1
  34. package/dist/gateway/static/root/assets/{desktop-pet-settings-BjY7DqD7.js → desktop-pet-settings-CQPXub2f.js} +1 -1
  35. package/dist/gateway/static/root/assets/device-pairing-wizard-DxkOYSut.js +1 -0
  36. package/dist/gateway/static/root/assets/{extension-debug-page-DbWJDT4X.js → extension-debug-page-CtWClPz-.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-page-lAC_2xWA.js → extension-page-BHh9HLCz.js} +1 -1
  38. package/dist/gateway/static/root/assets/{extension-settings-page-jFy1NJg9.js → extension-settings-page-BdT3v5Uh.js} +1 -1
  39. package/dist/gateway/static/root/assets/{gateway-config-swr-B7WpH3VW.js → gateway-config-swr-1eqyz9vZ.js} +1 -1
  40. package/dist/gateway/static/root/assets/gateway-settings-CZas_Ekx.js +1 -0
  41. package/dist/gateway/static/root/assets/{gateway-startup-retry-C8F_z865.js → gateway-startup-retry-C4rsW6vJ.js} +1 -1
  42. package/dist/gateway/static/root/assets/home-page-w3_aWeNt.js +1 -0
  43. package/dist/gateway/static/root/assets/{image-generation-api-Dc7d0_7q.js → image-generation-api-B5DXMylk.js} +1 -1
  44. package/dist/gateway/static/root/assets/{imports-page-_fMvJvzM.js → imports-page-B1JH0G5j.js} +1 -1
  45. package/dist/gateway/static/root/assets/index--3c0awkr.js +121 -0
  46. package/dist/gateway/static/root/assets/index-CNc4N4TX.css +1 -0
  47. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-CHnZYx1U.js → keyboard-shortcuts-settings-DGrLJ8Yh.js} +1 -1
  48. package/dist/gateway/static/root/assets/local-app-workbench-page-BYKrJpFF.js +1 -0
  49. package/dist/gateway/static/root/assets/local-apps-Bpja8nC6.js +1 -0
  50. package/dist/gateway/static/root/assets/local-apps-page-DqjStqbL.js +1 -0
  51. package/dist/gateway/static/root/assets/{locale-store-D9krC43K.js → locale-store-BIkcRr3t.js} +1 -1
  52. package/dist/gateway/static/root/assets/{logs-page-COxOJsgX.js → logs-page-Dl4kM4Na.js} +2 -2
  53. package/dist/gateway/static/root/assets/management-settings-gCfH4cwH.js +1 -0
  54. package/dist/gateway/static/root/assets/{markdown-view-CurpvCbB.js → markdown-view-Ck_5MADq.js} +1 -1
  55. package/dist/gateway/static/root/assets/{media-plugins-CYldyH6K.js → media-plugins-DTsZqgo6.js} +1 -1
  56. package/dist/gateway/static/root/assets/messages-7VAhscYe.js +3 -0
  57. package/dist/gateway/static/root/assets/note-detail-panel-j6sioeL1.js +5 -0
  58. package/dist/gateway/static/root/assets/notes-page-CMvvHv0f.js +8 -0
  59. package/dist/gateway/static/root/assets/{page-context-capture-button-DZOiI84c.js → page-context-capture-button-DTI_g4tz.js} +1 -1
  60. package/dist/gateway/static/root/assets/{page-tabs-C-XCf9cR.js → page-tabs-CfW_Q-K5.js} +1 -1
  61. package/dist/gateway/static/root/assets/{preview-open-alternatives-CvgeoEU8.js → preview-open-alternatives-CuPN-vAn.js} +1 -1
  62. package/dist/gateway/static/root/assets/product-delivery-bv3z8Xkh.js +1 -0
  63. package/dist/gateway/static/root/assets/product-open-page-BHjxRz1E.js +1 -0
  64. package/dist/gateway/static/root/assets/project-detail-page-C9K_e-EV.js +1 -0
  65. package/dist/gateway/static/root/assets/projects-page-Bk-es4i9.js +1 -0
  66. package/dist/gateway/static/root/assets/{registry-api-cK-g8BDq.js → registry-api-BAAZUGnU.js} +1 -1
  67. package/dist/gateway/static/root/assets/remote-access-hub-CLGJNA42.js +1 -0
  68. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DlUodTo-.js → runtime-tools-settings-panel-CHJBJKL1.js} +2 -2
  69. package/dist/gateway/static/root/assets/{scenes-page-DO8vGorm.js → scenes-page-ClLAD1pz.js} +2 -2
  70. package/dist/gateway/static/root/assets/{schema-form-BfboLCeN.js → schema-form-FQAit5HL.js} +1 -1
  71. package/dist/gateway/static/root/assets/sessions-page-Xj8MkXN1.js +1 -0
  72. package/dist/gateway/static/root/assets/settings-advanced-gate-DwALV8mi.js +1 -0
  73. package/dist/gateway/static/root/assets/{settings-form-section-BytEfCGo.js → settings-form-section-BDc6bw1q.js} +1 -1
  74. package/dist/gateway/static/root/assets/{settings-page-Da2ql9KX.js → settings-page-DnhxBJjV.js} +1 -1
  75. package/dist/gateway/static/root/assets/{settings-page-layout-CBfB_7yz.js → settings-page-layout-D3KNSQ5g.js} +1 -1
  76. package/dist/gateway/static/root/assets/{setup-status-panel-DElF2sgq.js → setup-status-panel-F0rCQ-2a.js} +1 -1
  77. package/dist/gateway/static/root/assets/{share-preview-page-B8J0Saj5.js → share-preview-page-DVQCRxwK.js} +1 -1
  78. package/dist/gateway/static/root/assets/shares-settings-C7hf6Cov.js +1 -0
  79. package/dist/gateway/static/root/assets/skill-reload-api-xPrFejRE.js +1 -0
  80. package/dist/gateway/static/root/assets/{skills-page-CNQHhsiv.js → skills-page-RdDYu7Yj.js} +1 -1
  81. package/dist/gateway/static/root/assets/{skills-page.utils-B53tyGx5.js → skills-page.utils-mDwC9UJ-.js} +1 -1
  82. package/dist/gateway/static/root/assets/{system-settings-panel-0HAvlVtR.js → system-settings-panel-Bk7GrMij.js} +1 -1
  83. package/dist/gateway/static/root/assets/task-detail-page-2A966jFY.js +1 -0
  84. package/dist/gateway/static/root/assets/{tunnel-api-DJsxU6q_.js → tunnel-api-D3Aquraj.js} +1 -1
  85. package/dist/gateway/static/root/assets/{use-autosave-eIELzAOD.js → use-autosave-C1xQ-sHn.js} +1 -1
  86. package/dist/gateway/static/root/assets/user-model-page-CnBxPBVe.js +2 -0
  87. package/dist/gateway/static/root/assets/{voice-api-key-field-BJ59ZCAn.js → voice-api-key-field-DCNECvcp.js} +1 -1
  88. package/dist/gateway/static/root/assets/{voice-config-api-DBXZJWLS.js → voice-config-api-B-_niUTU.js} +1 -1
  89. package/dist/gateway/static/root/assets/{work-discovery-overlay-BpSxdIgB.js → work-discovery-overlay-BrGx_JS_.js} +1 -1
  90. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-Bhlv3VUX.js → workflow-run-setup-panel-CmmC2Pdr.js} +2 -2
  91. package/dist/gateway/static/root/assets/workflows-page-BZVpqw4T.js +6 -0
  92. package/dist/gateway/static/root/index.html +12 -11
  93. package/dist/package.js +1 -1
  94. package/dist/packages/gateway-contract/src/capabilities.js +4 -110
  95. package/dist/packages/gateway-contract/src/chat-previews.js +73 -0
  96. package/dist/packages/gateway-contract/src/index.js +6 -0
  97. package/dist/packages/gateway-contract/src/local-apps.js +215 -0
  98. package/dist/packages/gateway-contract/src/product-delivery.js +62 -17
  99. package/dist/packages/gateway-contract/src/user-turn-document.js +60 -0
  100. package/dist/src/agent/agent-manager.d.ts +1 -0
  101. package/dist/src/agent/agent-manager.js +1 -0
  102. package/dist/src/agent/embedded/transcript-runtime.d.ts +3 -0
  103. package/dist/src/agent/embedded/transcript-runtime.js +6 -0
  104. package/dist/src/agent/external-tools/cliProvider.js +4 -1
  105. package/dist/src/agent/external-tools/composio-provider.js +9 -3
  106. package/dist/src/agent/external-tools/gateway-tools.js +17 -10
  107. package/dist/src/agent/external-tools/mcp-provider.d.ts +3 -1
  108. package/dist/src/agent/external-tools/mcp-provider.js +91 -6
  109. package/dist/src/agent/external-tools/service.d.ts +2 -1
  110. package/dist/src/agent/external-tools/service.js +8 -3
  111. package/dist/src/agent/external-tools/types.d.ts +9 -0
  112. package/dist/src/agent/mcp/bundle-mcp-config.js +37 -5
  113. package/dist/src/agent/mcp/bundle-mcp-gateway.d.ts +1 -0
  114. package/dist/src/agent/mcp/bundle-mcp-gateway.js +1 -0
  115. package/dist/src/agent/mcp/bundle-mcp-names.js +2 -1
  116. package/dist/src/agent/mcp/bundle-mcp-runtime.js +33 -1
  117. package/dist/src/agent/mcp/bundle-mcp-types.d.ts +4 -0
  118. package/dist/src/agent/mcp/index.js +1 -1
  119. package/dist/src/agent/mcp/mcp-stdio-transport.d.ts +1 -0
  120. package/dist/src/agent/mcp/mcp-stdio-transport.js +10 -0
  121. package/dist/src/agent/mcp/mcp-transport.js +12 -8
  122. package/dist/src/agent/mcp/oauth/index.js +1 -1
  123. package/dist/src/agent/mcp/oauth/mcp-oauth-manager.d.ts +6 -1
  124. package/dist/src/agent/mcp/oauth/mcp-oauth-manager.js +70 -14
  125. package/dist/src/agent/mcp/oauth/mcp-oauth-provider.js +1 -1
  126. package/dist/src/agent/mcp/oauth/mcp-oauth-session.d.ts +2 -0
  127. package/dist/src/agent/mcp/oauth/mcp-oauth-session.js +12 -0
  128. package/dist/src/agent/mcp/oauth/mcp-oauth-store.d.ts +3 -0
  129. package/dist/src/agent/mcp/oauth/mcp-oauth-store.js +13 -1
  130. package/dist/src/agent/mcp/plugin-http-fetch.d.ts +2 -0
  131. package/dist/src/agent/mcp/plugin-http-fetch.js +56 -0
  132. package/dist/src/agent/service/process-direct-streaming.js +27 -12
  133. package/dist/src/agent/service.js +1 -0
  134. package/dist/src/agent/service.types.d.ts +2 -0
  135. package/dist/src/agent/skills/hub-pull.js +1 -1
  136. package/dist/src/agent/skills/index.js +8 -1
  137. package/dist/src/agent/skills/skill-manager.d.ts +2 -0
  138. package/dist/src/agent/skills/skill-manager.js +8 -0
  139. package/dist/src/agent/skills/skill-sources.js +17 -0
  140. package/dist/src/agent/skills/types.d.ts +3 -1
  141. package/dist/src/agent/source-context/injector.js +10 -5
  142. package/dist/src/agent/source-context/types.d.ts +3 -0
  143. package/dist/src/agent/source-context/types.js +8 -2
  144. package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -1
  145. package/dist/src/agent/tool-manuals/xopc-use.js +12 -2
  146. package/dist/src/agent/tools/automation-tool.js +1 -1
  147. package/dist/src/agent/tools/factory.d.ts +1 -0
  148. package/dist/src/agent/tools/factory.js +2 -1
  149. package/dist/src/agent/tools/workflow-tool.js +1 -1
  150. package/dist/src/agent/tools/write.js +1 -1
  151. package/dist/src/agent/tools/xopc-use-tool.d.ts +4 -2
  152. package/dist/src/agent/tools/xopc-use-tool.js +120 -12
  153. package/dist/src/chat-previews/index.d.ts +2 -0
  154. package/dist/src/chat-previews/index.js +3 -0
  155. package/dist/src/chat-previews/service.d.ts +27 -0
  156. package/dist/src/chat-previews/service.js +106 -0
  157. package/dist/src/chat-previews/store.d.ts +28 -0
  158. package/dist/src/chat-previews/store.js +77 -0
  159. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  160. package/dist/src/cli/commands/extension-agent-plugin.d.ts +8 -0
  161. package/dist/src/cli/commands/extension-agent-plugin.js +82 -0
  162. package/dist/src/cli/commands/extension-marketplace.js +44 -4
  163. package/dist/src/cli/commands/extension.js +35 -3
  164. package/dist/src/connectors/account-selection.js +1 -1
  165. package/dist/src/connectors/connection-candidates.d.ts +4 -1
  166. package/dist/src/connectors/connection-candidates.js +8 -2
  167. package/dist/src/connectors/connection-capabilities.d.ts +2 -2
  168. package/dist/src/connectors/connection-capabilities.js +3 -1
  169. package/dist/src/connectors/connection-recovery-service.d.ts +6 -1
  170. package/dist/src/connectors/connection-recovery-service.js +138 -26
  171. package/dist/src/connectors/plugin-mcp-recovery.d.ts +28 -0
  172. package/dist/src/connectors/plugin-mcp-recovery.js +90 -0
  173. package/dist/src/extensions/agent-plugins/auth.d.ts +39 -0
  174. package/dist/src/extensions/agent-plugins/auth.js +156 -0
  175. package/dist/src/extensions/agent-plugins/connection.d.ts +8 -0
  176. package/dist/src/extensions/agent-plugins/connection.js +41 -0
  177. package/dist/src/extensions/agent-plugins/health.d.ts +4 -0
  178. package/dist/src/extensions/agent-plugins/health.js +48 -0
  179. package/dist/src/extensions/agent-plugins/inventory.d.ts +53 -0
  180. package/dist/src/extensions/agent-plugins/inventory.js +34 -0
  181. package/dist/src/extensions/agent-plugins/mcp-adapter.d.ts +3 -0
  182. package/dist/src/extensions/agent-plugins/mcp-adapter.js +47 -0
  183. package/dist/src/extensions/agent-plugins/sources.d.ts +5 -0
  184. package/dist/src/extensions/agent-plugins/sources.js +72 -0
  185. package/dist/src/extensions/agent-plugins/store.d.ts +61 -0
  186. package/dist/src/extensions/agent-plugins/store.js +305 -0
  187. package/dist/src/extensions/agent-plugins/validation.d.ts +59 -0
  188. package/dist/src/extensions/agent-plugins/validation.js +211 -0
  189. package/dist/src/extensions/update.js +1 -1
  190. package/dist/src/gateway/chat-stream/mapper.js +10 -3
  191. package/dist/src/gateway/hono/routes/agent-plugins.d.ts +3 -0
  192. package/dist/src/gateway/hono/routes/agent-plugins.js +166 -0
  193. package/dist/src/gateway/hono/routes/agent-stream.js +14 -0
  194. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +4 -2
  195. package/dist/src/gateway/hono/routes/chat-previews.d.ts +3 -0
  196. package/dist/src/gateway/hono/routes/chat-previews.js +41 -0
  197. package/dist/src/gateway/hono/routes/connection-waits.js +4 -2
  198. package/dist/src/gateway/hono/routes/index.js +2 -0
  199. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  200. package/dist/src/gateway/hono/routes/local-apps.js +71 -39
  201. package/dist/src/gateway/hono/routes/mcp.js +48 -21
  202. package/dist/src/gateway/hono/routes/session-input-handler.d.ts +4 -0
  203. package/dist/src/gateway/hono/routes/session-input-handler.js +22 -0
  204. package/dist/src/gateway/hono/routes/side-chats.js +11 -0
  205. package/dist/src/gateway/service/agent-runner.js +7 -1
  206. package/dist/src/gateway/service/marketplace-service.d.ts +1 -0
  207. package/dist/src/gateway/service/marketplace-service.js +15 -1
  208. package/dist/src/gateway/service/session-input-coordinator.js +3 -3
  209. package/dist/src/gateway/service.d.ts +5 -1
  210. package/dist/src/gateway/service.js +14 -0
  211. package/dist/src/gateway/side-chat/index.d.ts +3 -1
  212. package/dist/src/gateway/side-chat/index.js +2 -1
  213. package/dist/src/gateway/side-chat/manager.d.ts +16 -0
  214. package/dist/src/gateway/side-chat/manager.js +40 -6
  215. package/dist/src/gateway/side-chat/promotion-service.d.ts +19 -0
  216. package/dist/src/gateway/side-chat/promotion-service.js +111 -0
  217. package/dist/src/gateway/side-chat/run-service.js +1 -0
  218. package/dist/src/gateway/side-chat/types.d.ts +1 -1
  219. package/dist/src/local-apps/artifact-files.d.ts +3 -0
  220. package/dist/src/local-apps/artifact-files.js +45 -0
  221. package/dist/src/local-apps/capabilities/write.js +1 -1
  222. package/dist/src/local-apps/fix-guidance.d.ts +3 -0
  223. package/dist/src/local-apps/fix-guidance.js +75 -0
  224. package/dist/src/local-apps/index.d.ts +2 -1
  225. package/dist/src/local-apps/scaffold.d.ts +5 -0
  226. package/dist/src/local-apps/scaffold.js +18 -5
  227. package/dist/src/local-apps/service.d.ts +18 -3
  228. package/dist/src/local-apps/service.js +106 -64
  229. package/dist/src/local-apps/snapshot-store.d.ts +8 -0
  230. package/dist/src/local-apps/snapshot-store.js +68 -0
  231. package/dist/src/local-apps/types.d.ts +4 -87
  232. package/dist/src/session/client-history.d.ts +3 -1
  233. package/dist/src/session/client-history.js +10 -3
  234. package/dist/src/session/index.d.ts +1 -1
  235. package/dist/src/session/manager.d.ts +4 -0
  236. package/dist/src/session/manager.js +6 -0
  237. package/dist/src/session/session-context-for-llm.d.ts +12 -1
  238. package/dist/src/session/session-context-for-llm.js +16 -2
  239. package/dist/src/session/store.d.ts +14 -0
  240. package/dist/src/session/store.js +17 -0
  241. package/dist/src/session/stored-rows-to-file-entries.js +10 -1
  242. package/dist/src/session/transcript-outline.js +10 -3
  243. package/dist/src/storage/sqlite/connection-wait-repository.js +9 -3
  244. package/dist/src/storage/sqlite/migrations/202_chat_previews.sql +26 -0
  245. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  246. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  247. package/dist/src/storage/sqlite/row-mappers.js +6 -1
  248. package/dist/src/storage/sqlite/schema.js +1 -1
  249. package/package.json +3 -3
  250. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-DWLXHWXg.js +0 -1
  251. package/dist/gateway/static/root/assets/api-Df2D6d3C.js +0 -1
  252. package/dist/gateway/static/root/assets/apps-page-BzytHIn1.js +0 -1
  253. package/dist/gateway/static/root/assets/automations-workspace-CtSV8tp-.js +0 -7
  254. package/dist/gateway/static/root/assets/browser-settings-page-DrvNA-G2.js +0 -3
  255. package/dist/gateway/static/root/assets/capabilities-D0S3DuAD.js +0 -1
  256. package/dist/gateway/static/root/assets/capabilities-settings-panel-c0k2virA.js +0 -8
  257. package/dist/gateway/static/root/assets/channels-settings-Bkl9fDHc.js +0 -1
  258. package/dist/gateway/static/root/assets/connectors-page-Dw_h-5Qh.js +0 -2
  259. package/dist/gateway/static/root/assets/device-pairing-wizard-C5f4FRpE.js +0 -1
  260. package/dist/gateway/static/root/assets/gateway-settings-D7XbH6Hk.js +0 -1
  261. package/dist/gateway/static/root/assets/home-page-CFJypY6Y.js +0 -1
  262. package/dist/gateway/static/root/assets/index-B4Vwh0H-.css +0 -1
  263. package/dist/gateway/static/root/assets/index-BNubE2Zi.js +0 -89
  264. package/dist/gateway/static/root/assets/local-app-workbench-page-BLKCFXvr.js +0 -2
  265. package/dist/gateway/static/root/assets/local-apps-page-BNFmOkxs.js +0 -1
  266. package/dist/gateway/static/root/assets/management-settings-BX5NtnQ2.js +0 -1
  267. package/dist/gateway/static/root/assets/messages-B1sTgIrE.js +0 -3
  268. package/dist/gateway/static/root/assets/note-detail-panel-DZ0IWx1R.js +0 -5
  269. package/dist/gateway/static/root/assets/notes-page-B9F1uue_.js +0 -8
  270. package/dist/gateway/static/root/assets/product-delivery-chCjIpvu.js +0 -1
  271. package/dist/gateway/static/root/assets/product-open-page-DEYWx__w.js +0 -1
  272. package/dist/gateway/static/root/assets/project-detail-page-9qMDEKVd.js +0 -1
  273. package/dist/gateway/static/root/assets/projects-page-D4UTOpEm.js +0 -1
  274. package/dist/gateway/static/root/assets/remote-access-hub-CPmOucUB.js +0 -1
  275. package/dist/gateway/static/root/assets/sessions-page-zu5P0dk5.js +0 -1
  276. package/dist/gateway/static/root/assets/settings-advanced-gate-ClEw-i1l.js +0 -1
  277. package/dist/gateway/static/root/assets/shares-settings-MLolJfoV.js +0 -1
  278. package/dist/gateway/static/root/assets/skill-reload-api-DTPsW9TY.js +0 -1
  279. package/dist/gateway/static/root/assets/task-detail-page-Dc30oS9J.js +0 -1
  280. package/dist/gateway/static/root/assets/user-model-page-Bq6ab5WJ.js +0 -2
  281. package/dist/gateway/static/root/assets/workflows-page-Ci-4HAYm.js +0 -6
@@ -19,6 +19,7 @@ import { capabilityActions, isToolInputSchema, missingConnectionCapabilities } f
19
19
  import { resolveConnectionCandidate } from "./connection-candidates.js";
20
20
  import { installConnector } from "./install.js";
21
21
  import { persistConfigMutation } from "../config/config-mutation.js";
22
+ import { HostPluginMcpRecovery } from "./plugin-mcp-recovery.js";
22
23
  import { randomUUID } from "node:crypto";
23
24
  //#region src/connectors/connection-recovery-service.ts
24
25
  init_transaction();
@@ -36,6 +37,9 @@ const SCOPE_ORDER = {
36
37
  };
37
38
  const INTENT_TTL = 30 * 6e4;
38
39
  const ATTEMPT_TTL = 10 * 6e4;
40
+ function isConnectorNeed(need) {
41
+ return need.target.type === "connector";
42
+ }
39
43
  /** Authorization lives at click time. Chat history contains only immutable explanations. */
40
44
  var ConnectionRecoveryService = class {
41
45
  busy = /* @__PURE__ */ new Set();
@@ -77,6 +81,9 @@ var ConnectionRecoveryService = class {
77
81
  get adapter() {
78
82
  return this.deps.adapter ?? new ComposioSessionsAdapter();
79
83
  }
84
+ get pluginMcp() {
85
+ return this.deps.pluginMcp ?? new HostPluginMcpRecovery(this.deps.getConfig);
86
+ }
80
87
  snapshot(conversationId) {
81
88
  if (!connectorPrincipalForSession(conversationId).isLocalOwner) throw new Error("This connection belongs to another principal.");
82
89
  const transcriptId = readCurrentTranscriptId(getSqliteDatabase(), conversationId);
@@ -90,13 +97,25 @@ var ConnectionRecoveryService = class {
90
97
  }
91
98
  view(wait, verifiedIds) {
92
99
  const needs = wait.needs.map((need) => {
93
- const instance = listConnectorInstances(this.deps.getConfig()).find((instance) => instance.connectorId === need.connectorId);
94
- const installation = getConnectorInstallation(`${need.connectorId}-${wait.principalId}`);
100
+ if (need.target.type === "plugin-mcp") {
101
+ const availability = this.pluginMcp.availability(need.target);
102
+ const phase = !availability.available || need.connectionId && need.capabilityError ? "blocked" : need.connectionId === need.target.serverId ? "ready" : need.attempt && need.attempt.expiresAt > Date.now() ? "authorizing" : need.unavailable ? "reconnect" : "connect";
103
+ return {
104
+ ...need,
105
+ phase,
106
+ accounts: [],
107
+ alternatives: [],
108
+ ...availability.reason || need.capabilityError ? { reason: availability.reason ?? need.capabilityError } : {}
109
+ };
110
+ }
111
+ const id = need.target.connectorId;
112
+ const instance = listConnectorInstances(this.deps.getConfig()).find((instance) => instance.connectorId === id);
113
+ const installation = getConnectorInstallation(`${id}-${wait.principalId}`);
95
114
  const cli = instance?.materialized.type === "cli" ? getCliAdapter(instance.materialized.adapterId) : void 0;
96
115
  const scopeBlocked = Math.max(1, ...need.capabilities.filter((capability) => cli || /^[A-Z]+_/.test(capability)).map((capability) => SCOPE_ORDER[cli ? cli.curatedActions[capability] ?? "read" : scopeForComposioAction(capability).scope])) > SCOPE_ORDER[installation?.maxScope ?? "read"];
97
116
  const all = listConnectorConnections({
98
117
  principalId: wait.principalId,
99
- connectorId: need.connectorId
118
+ connectorId: id
100
119
  });
101
120
  const requested = need.accountId ? all.find((connection) => connection.accountId === need.accountId) : void 0;
102
121
  const blocked = scopeBlocked || instance?.enabled === false || installation?.enabled === false || installation?.selectedAccountIds?.length === 0 || Boolean(installation && requested && !canAccessConnectorAccount(requested, installation, wait.agentId)) || Boolean(installation?.allowedAgentIds.length && !installation.allowedAgentIds.includes(wait.agentId));
@@ -115,9 +134,9 @@ var ConnectionRecoveryService = class {
115
134
  "revoked",
116
135
  "failed"
117
136
  ].includes(connection.status)) ? "reconnect" : "connect";
118
- const alternatives = ["composio-gmail", "composio-outlook"].includes(need.connectorId) ? ["composio-gmail", "composio-outlook"].filter((id) => id !== need.connectorId).map((id) => ({
119
- candidateRef: id,
120
- label: getConnectorDefinition(id)?.displayName ?? id
137
+ const alternatives = ["composio-gmail", "composio-outlook"].includes(id) ? ["composio-gmail", "composio-outlook"].filter((candidate) => candidate !== id).map((candidate) => ({
138
+ candidateRef: candidate,
139
+ label: getConnectorDefinition(candidate)?.displayName ?? candidate
121
140
  })) : [];
122
141
  return {
123
142
  ...need,
@@ -174,14 +193,16 @@ var ConnectionRecoveryService = class {
174
193
  }))
175
194
  }, verified).needs;
176
195
  return Promise.all(wait.needs.map(async (need) => {
196
+ if (need.target.type === "plugin-mcp") return need;
177
197
  if (views.find((view) => view.key === need.key)?.phase !== "ready") return {
178
198
  ...need,
179
199
  capabilityError: void 0
180
200
  };
181
201
  try {
182
- const instance = listConnectorInstances(this.deps.getConfig()).find((instance) => instance.connectorId === need.connectorId && instance.enabled);
202
+ const id = need.target.connectorId;
203
+ const instance = listConnectorInstances(this.deps.getConfig()).find((instance) => instance.connectorId === id && instance.enabled);
183
204
  if (!instance) throw new Error("Connector setup is unavailable");
184
- const definition = getInstalledConnectorDefinition(this.deps.getConfig(), instance.instanceId) ?? getConnectorDefinition(need.connectorId);
205
+ const definition = getInstalledConnectorDefinition(this.deps.getConfig(), instance.instanceId) ?? getConnectorDefinition(id);
185
206
  if (definition?.runtime.type === "cli") {
186
207
  const selected = views.find((view) => view.key === need.key);
187
208
  const connection = selected?.connectionId ? getConnectorConnection(selected.connectionId) : void 0;
@@ -211,7 +232,7 @@ var ConnectionRecoveryService = class {
211
232
  const missing = missingConnectionCapabilities(need, new Set(Object.entries(schemas && typeof schemas === "object" ? schemas : {}).filter(([action, value]) => value && typeof value === "object" && isToolInputSchema(value.inputSchema) && isComposioActionAllowedByCatalog(action)).map(([action]) => action)));
212
233
  if (missing.length) log.warn({
213
234
  conversationId: wait.conversationId,
214
- connectorId: need.connectorId,
235
+ connectorId: id,
215
236
  missingCapabilities: missing
216
237
  }, "Connected app lacks required tool contracts");
217
238
  return {
@@ -222,7 +243,7 @@ var ConnectionRecoveryService = class {
222
243
  log.warn({
223
244
  err,
224
245
  conversationId: wait.conversationId,
225
- connectorId: need.connectorId
246
+ connectorId: need.target.connectorId
226
247
  }, "Connected app capability check failed");
227
248
  return {
228
249
  ...need,
@@ -235,9 +256,10 @@ var ConnectionRecoveryService = class {
235
256
  const config = this.deps.getConfig();
236
257
  const instances = listConnectorInstances(config);
237
258
  const cliIds = new Set(instances.filter((item) => item.materialized.type === "cli").map((item) => item.connectorId));
238
- const fresh = wait.needs.some((need) => !cliIds.has(need.connectorId)) ? await this.adapter.syncConnections({ principalId: wait.principalId }) : [];
259
+ const connectorNeeds = wait.needs.filter(isConnectorNeed);
260
+ const fresh = connectorNeeds.some((need) => !cliIds.has(need.target.connectorId)) ? await this.adapter.syncConnections({ principalId: wait.principalId }) : [];
239
261
  for (const connection of currentAccountConnections(listConnectorConnections({ principalId: wait.principalId }))) {
240
- if (connection.provider !== "cli" || !wait.needs.some((need) => need.connectorId === connection.connectorId)) continue;
262
+ if (connection.provider !== "cli" || !connectorNeeds.some((need) => need.target.connectorId === connection.connectorId)) continue;
241
263
  const policy = getConnectorInstallation(`${connection.connectorId}-${wait.principalId}`);
242
264
  if (!policy || !canAccessConnectorAccount(connection, policy, wait.agentId)) continue;
243
265
  const instanceId = connection.metadata.runtimeInstanceId;
@@ -247,6 +269,38 @@ var ConnectionRecoveryService = class {
247
269
  }
248
270
  return fresh;
249
271
  }
272
+ async syncPluginMcpNeeds(wait) {
273
+ return Promise.all(wait.needs.map(async (need) => {
274
+ if (need.target.type !== "plugin-mcp") return need;
275
+ const status = await this.pluginMcp.status(need.target);
276
+ if (status.status === "connected") {
277
+ const verified = await this.pluginMcp.verify(need.target);
278
+ return {
279
+ ...need,
280
+ connectionId: need.target.serverId,
281
+ unavailable: false,
282
+ attempt: void 0,
283
+ capabilityError: verified.ready ? void 0 : verified.error ?? "The connected MCP tools are unavailable."
284
+ };
285
+ }
286
+ if (status.status === "authorizing") return {
287
+ ...need,
288
+ connectionId: void 0,
289
+ unavailable: false,
290
+ attempt: {
291
+ id: status.session?.id ?? need.attempt?.id ?? randomUUID(),
292
+ expiresAt: status.session?.expiresAt ?? Date.now() + ATTEMPT_TTL
293
+ }
294
+ };
295
+ return {
296
+ ...need,
297
+ connectionId: void 0,
298
+ unavailable: true,
299
+ attempt: void 0,
300
+ capabilityError: status.status === "error" ? status.session?.error : void 0
301
+ };
302
+ }));
303
+ }
250
304
  async preflight(input) {
251
305
  if (input.kind !== "connection_resume") return true;
252
306
  const wait = input.payload ? getConnectionWait(input.payload.waitId) : void 0;
@@ -255,12 +309,13 @@ var ConnectionRecoveryService = class {
255
309
  try {
256
310
  const fresh = await this.syncConnections(wait);
257
311
  const verified = new Set(fresh.filter((item) => item.status === "active").map((item) => item.id));
258
- wait.needs = await this.checkCapabilities(wait, verified);
259
- const ready = this.view(wait, verified).needs.every((need) => need.phase === "ready");
260
- wait.needs = wait.needs.map((need) => ({
312
+ wait.needs = await this.syncPluginMcpNeeds(wait);
313
+ wait.needs = wait.needs.map((need) => need.target.type === "plugin-mcp" ? need : {
261
314
  ...need,
262
315
  unavailable: !fresh.some((item) => item.id === need.connectionId && item.status === "active")
263
- }));
316
+ });
317
+ wait.needs = await this.checkCapabilities(wait, verified);
318
+ const ready = this.view(wait, verified).needs.every((need) => need.phase === "ready");
264
319
  if (getConnectionWait(wait.id)?.version !== wait.version) return false;
265
320
  if (ready && wait.intent && wait.intent.validUntil > Date.now() && wait.intent.objectiveRevision === wait.objectiveRevision) return true;
266
321
  } catch {}
@@ -319,8 +374,51 @@ var ConnectionRecoveryService = class {
319
374
  const need = wait.needs.find((need) => need.key === action.needKey);
320
375
  if (!need) throw new Error("Unknown connection requirement.");
321
376
  if (this.view(wait).needs.find((item) => item.key === need.key)?.phase === "blocked") throw new Error("Connector policy blocks this connection.");
322
- const instance = listConnectorInstances(this.deps.getConfig()).find((item) => item.connectorId === need.connectorId);
323
- const definition = (instance ? getInstalledConnectorDefinition(this.deps.getConfig(), instance.instanceId) : void 0) ?? getConnectorDefinition(need.connectorId);
377
+ if (need.target.type === "plugin-mcp") {
378
+ const serverId = need.target.serverId;
379
+ const attemptId = randomUUID();
380
+ wait = updateConnectionWait({
381
+ ...wait,
382
+ intent: {
383
+ objectiveRevision: wait.objectiveRevision,
384
+ validUntil: Date.now() + INTENT_TTL
385
+ },
386
+ needs: wait.needs.map((item) => item.key === need.key ? {
387
+ ...item,
388
+ unavailable: false,
389
+ capabilityError: void 0,
390
+ attempt: {
391
+ id: attemptId,
392
+ expiresAt: Date.now() + ATTEMPT_TTL
393
+ }
394
+ } : item)
395
+ }, wait.version);
396
+ publishConnectionWait(conversationId);
397
+ const auth = await this.pluginMcp.start(need.target);
398
+ const latest = getConnectionWait(wait.id);
399
+ if (!latest || latest.version !== wait.version || latest.status !== "open") throw new Error("WAIT_CHANGED");
400
+ wait = updateConnectionWait({
401
+ ...wait,
402
+ needs: wait.needs.map((item) => item.key === need.key ? {
403
+ ...item,
404
+ attempt: auth.status === "authorizing" ? {
405
+ id: auth.session?.id ?? attemptId,
406
+ expiresAt: auth.session?.expiresAt ?? Date.now() + ATTEMPT_TTL
407
+ } : void 0,
408
+ connectionId: auth.status === "connected" ? serverId : void 0,
409
+ unavailable: auth.status === "error",
410
+ capabilityError: auth.status === "error" ? auth.session?.error : void 0
411
+ } : item)
412
+ }, wait.version);
413
+ publishConnectionWait(conversationId);
414
+ return {
415
+ snapshot: this.snapshot(conversationId),
416
+ authorizationUrl: auth.session?.authorizationUrl
417
+ };
418
+ }
419
+ const id = need.target.connectorId;
420
+ const instance = listConnectorInstances(this.deps.getConfig()).find((item) => item.connectorId === id);
421
+ const definition = (instance ? getInstalledConnectorDefinition(this.deps.getConfig(), instance.instanceId) : void 0) ?? getConnectorDefinition(id);
324
422
  if (definition?.runtime.type === "cli") {
325
423
  updateConnectionWait({
326
424
  ...wait,
@@ -332,7 +430,7 @@ var ConnectionRecoveryService = class {
332
430
  publishConnectionWait(conversationId);
333
431
  return {
334
432
  snapshot: this.snapshot(conversationId),
335
- authorizationUrl: `/#/connectors?connector=${encodeURIComponent(need.connectorId)}`
433
+ authorizationUrl: `/#/connectors?connector=${encodeURIComponent(id)}`
336
434
  };
337
435
  }
338
436
  if (definition?.runtime.type !== "composio" || definition.runtime.role !== "toolkit") throw new Error("Unsupported connector.");
@@ -353,8 +451,8 @@ var ConnectionRecoveryService = class {
353
451
  }, wait.version);
354
452
  publishConnectionWait(conversationId);
355
453
  const config = this.deps.getConfig();
356
- await this.ensureInstallation(wait, need.connectorId);
357
- const installationId = `${need.connectorId}-${wait.principalId}`;
454
+ await this.ensureInstallation(wait, id);
455
+ const installationId = `${id}-${wait.principalId}`;
358
456
  const auth = await this.adapter.authorize({
359
457
  principalId: wait.principalId,
360
458
  toolkit: definition.runtime.toolkit,
@@ -388,12 +486,20 @@ var ConnectionRecoveryService = class {
388
486
  authorizationUrl: auth.connectUrl
389
487
  };
390
488
  } else {
489
+ if (action.action === "submit_callback") {
490
+ const need = wait.needs.find((need) => need.key === action.needKey);
491
+ if (!need || need.target.type !== "plugin-mcp") throw new Error("OAuth callback is unavailable.");
492
+ if (!action.callbackUrl || action.callbackUrl.length > 16384) throw new Error("Expected the complete OAuth callback URL.");
493
+ await this.pluginMcp.submitCallback(need.target, action.callbackUrl);
494
+ }
391
495
  const fresh = await this.syncConnections(wait);
392
496
  const verified = new Set(fresh.filter((item) => item.status === "active").map((item) => item.id));
393
497
  const latest = getConnectionWait(wait.id);
394
498
  if (!latest || latest.version !== wait.version || latest.status !== "open") throw new Error("WAIT_CHANGED");
395
499
  let needs = wait.needs.map((need) => {
396
- const authorized = fresh.find((item) => item.providerConnectionId === need.attempt?.connectionId && item.status === "active" && item.connectorId === need.connectorId && (!need.accountId || item.accountId === need.accountId));
500
+ if (need.target.type === "plugin-mcp") return need;
501
+ const id = need.target.connectorId;
502
+ const authorized = fresh.find((item) => item.providerConnectionId === need.attempt?.connectionId && item.status === "active" && item.connectorId === id && (!need.accountId || item.accountId === need.accountId));
397
503
  return authorized ? {
398
504
  ...need,
399
505
  unavailable: false,
@@ -404,13 +510,19 @@ var ConnectionRecoveryService = class {
404
510
  attempt: void 0
405
511
  } : {
406
512
  ...need,
407
- unavailable: !fresh.some((item) => item.connectorId === need.connectorId && item.status === "active" && (!need.connectionId || item.id === need.connectionId) && (!need.accountId || item.accountId === need.accountId))
513
+ unavailable: !fresh.some((item) => item.connectorId === id && item.status === "active" && (!need.connectionId || item.id === need.connectionId) && (!need.accountId || item.accountId === need.accountId))
408
514
  };
409
515
  });
516
+ needs = await this.syncPluginMcpNeeds({
517
+ ...wait,
518
+ needs
519
+ });
410
520
  if (action.action === "select_account") {
411
521
  const need = needs.find((item) => item.key === action.needKey);
412
- const connection = currentAccountConnections(fresh).find((item) => item.accountId === action.accountId && item.connectorId === need?.connectorId);
413
- if (!need || !connection || !this.view(wait, verified).needs.find((item) => item.key === need.key)?.accounts.some((item) => item.id === connection.accountId)) throw new Error("Account is unavailable.");
522
+ if (!need || need.target.type !== "connector") throw new Error("Account selection is unavailable.");
523
+ const id = need.target.connectorId;
524
+ const connection = currentAccountConnections(fresh).find((item) => item.accountId === action.accountId && item.connectorId === id);
525
+ if (!connection || !this.view(wait, verified).needs.find((item) => item.key === need.key)?.accounts.some((item) => item.id === connection.accountId)) throw new Error("Account is unavailable.");
414
526
  needs = needs.map((item) => item.key === need.key ? {
415
527
  ...item,
416
528
  connectionId: connection.id,
@@ -422,7 +534,7 @@ var ConnectionRecoveryService = class {
422
534
  for (const selected of this.view({
423
535
  ...wait,
424
536
  needs
425
- }, verified).needs) if (selected.phase === "ready" || selected.capabilityError && selected.connectionId) await this.ensureInstallation(wait, selected.connectorId);
537
+ }, verified).needs) if (selected.target.type === "connector" && (selected.phase === "ready" || selected.capabilityError && selected.connectionId)) await this.ensureInstallation(wait, selected.target.connectorId);
426
538
  needs = await this.checkCapabilities({
427
539
  ...wait,
428
540
  needs
@@ -0,0 +1,28 @@
1
+ import type { PluginMcpConnectionTarget } from '@xopcai/gateway-contract';
2
+ import { type McpOAuthStatus } from '../agent/mcp/oauth/mcp-oauth-manager.js';
3
+ import type { Config } from '../config/schema.js';
4
+ export type PluginMcpAvailability = {
5
+ available: boolean;
6
+ reason?: string;
7
+ };
8
+ export type PluginMcpVerification = {
9
+ ready: boolean;
10
+ error?: string;
11
+ };
12
+ export interface PluginMcpRecovery {
13
+ availability(target: PluginMcpConnectionTarget): PluginMcpAvailability;
14
+ status(target: PluginMcpConnectionTarget): Promise<McpOAuthStatus>;
15
+ start(target: PluginMcpConnectionTarget): Promise<McpOAuthStatus>;
16
+ verify(target: PluginMcpConnectionTarget): Promise<PluginMcpVerification>;
17
+ submitCallback(target: PluginMcpConnectionTarget, callbackUrl: string): Promise<McpOAuthStatus>;
18
+ }
19
+ export declare class HostPluginMcpRecovery implements PluginMcpRecovery {
20
+ private readonly getConfig;
21
+ constructor(getConfig: () => Config);
22
+ availability(target: PluginMcpConnectionTarget): PluginMcpAvailability;
23
+ status(target: PluginMcpConnectionTarget): Promise<McpOAuthStatus>;
24
+ start(target: PluginMcpConnectionTarget): Promise<McpOAuthStatus>;
25
+ verify(target: PluginMcpConnectionTarget): Promise<PluginMcpVerification>;
26
+ submitCallback(target: PluginMcpConnectionTarget, callbackUrl: string): Promise<McpOAuthStatus>;
27
+ private resolveServer;
28
+ }
@@ -0,0 +1,90 @@
1
+ import { AgentPluginStore } from "../extensions/agent-plugins/store.js";
2
+ import { savePluginAuthBinding } from "../extensions/agent-plugins/auth.js";
3
+ import { loadMergedBundleMcpConfig } from "../agent/mcp/bundle-mcp-config.js";
4
+ import { getWorkspacePath } from "../config/workspace-path-helpers.js";
5
+ import { getMcpOAuthManager } from "../agent/mcp/oauth/mcp-oauth-manager.js";
6
+ import { listBundleMcpServerCapabilitiesForGateway } from "../agent/mcp/bundle-mcp-gateway.js";
7
+ //#region src/connectors/plugin-mcp-recovery.ts
8
+ var HostPluginMcpRecovery = class {
9
+ constructor(getConfig) {
10
+ this.getConfig = getConfig;
11
+ }
12
+ availability(target) {
13
+ const plugin = new AgentPluginStore().get(target.pluginId);
14
+ if (!plugin) return {
15
+ available: false,
16
+ reason: "The plugin is no longer installed."
17
+ };
18
+ if (!plugin.receipt.enabled) return {
19
+ available: false,
20
+ reason: "Enable the plugin before connecting its account."
21
+ };
22
+ if (plugin.readiness === "blocked") return {
23
+ available: false,
24
+ reason: "Repair the plugin before connecting its account."
25
+ };
26
+ if (plugin.servers[target.serverName]?.type !== "streamable-http") return {
27
+ available: false,
28
+ reason: "This plugin server does not support OAuth."
29
+ };
30
+ return { available: true };
31
+ }
32
+ async status(target) {
33
+ const server = this.resolveServer(target);
34
+ return getMcpOAuthManager(server).status(target.serverId, server);
35
+ }
36
+ async start(target) {
37
+ const availability = this.availability(target);
38
+ if (!availability.available) throw new Error(availability.reason);
39
+ await savePluginAuthBinding(new AgentPluginStore(), target.pluginId, target.serverName, { mode: "oauth" });
40
+ const server = this.resolveServer(target);
41
+ return getMcpOAuthManager(server).start({
42
+ serverId: target.serverId,
43
+ rawServer: server,
44
+ cfg: this.getConfig()
45
+ });
46
+ }
47
+ async verify(target) {
48
+ const availability = this.availability(target);
49
+ if (!availability.available) return {
50
+ ready: false,
51
+ error: availability.reason
52
+ };
53
+ const status = await this.status(target);
54
+ if (status.status !== "connected") return {
55
+ ready: false,
56
+ error: status.session?.error
57
+ };
58
+ const cfg = this.getConfig();
59
+ const capabilities = await listBundleMcpServerCapabilitiesForGateway({
60
+ workspaceDir: getWorkspacePath(cfg) || "./workspace",
61
+ cfg,
62
+ serverId: target.serverId
63
+ });
64
+ if (capabilities.error) return {
65
+ ready: false,
66
+ error: capabilities.error.message
67
+ };
68
+ if (capabilities.toolCount === 0) return {
69
+ ready: false,
70
+ error: "The connected MCP server did not expose any tools."
71
+ };
72
+ return { ready: true };
73
+ }
74
+ async submitCallback(target, callbackUrl) {
75
+ const server = this.resolveServer(target);
76
+ return getMcpOAuthManager(server).submitCallback(target.serverId, server, callbackUrl);
77
+ }
78
+ resolveServer(target) {
79
+ const cfg = this.getConfig();
80
+ const server = loadMergedBundleMcpConfig({
81
+ workspaceDir: getWorkspacePath(cfg) || "./workspace",
82
+ cfg
83
+ }).config.mcpServers[target.serverId];
84
+ const origin = server?.xopcPlugin;
85
+ if (!server || origin?.id !== target.pluginId || origin.serverName !== target.serverName) throw new Error("Plugin MCP server is unavailable.");
86
+ return server;
87
+ }
88
+ };
89
+ //#endregion
90
+ export { HostPluginMcpRecovery };
@@ -0,0 +1,39 @@
1
+ import { z } from 'zod';
2
+ import { AgentPluginStore } from './store.js';
3
+ import { type PluginServer } from './validation.js';
4
+ declare const bindingSchema: z.ZodObject<{
5
+ serverName: z.ZodString;
6
+ mode: z.ZodEnum<{
7
+ none: "none";
8
+ auto: "auto";
9
+ oauth: "oauth";
10
+ "api-key": "api-key";
11
+ }>;
12
+ identityScope: z.ZodLiteral<"owner">;
13
+ endpointFingerprint: z.ZodString;
14
+ fields: z.ZodArray<z.ZodObject<{
15
+ target: z.ZodEnum<{
16
+ headers: "headers";
17
+ env: "env";
18
+ }>;
19
+ key: z.ZodString;
20
+ provider: z.ZodString;
21
+ prefix: z.ZodString;
22
+ }, z.core.$strict>>;
23
+ }, z.core.$strict>;
24
+ export type PluginAuthBinding = z.infer<typeof bindingSchema>;
25
+ export declare function pluginEndpointFingerprint(server: PluginServer): string;
26
+ export declare function readPluginAuthBinding(store: AgentPluginStore, id: string, name: string, server: PluginServer): PluginAuthBinding | undefined;
27
+ export declare function savePluginAuthBinding(store: AgentPluginStore, id: string, name: string, input: {
28
+ mode: PluginAuthBinding['mode'];
29
+ secrets?: Array<{
30
+ target: 'headers' | 'env';
31
+ key: string;
32
+ value: string;
33
+ prefix?: string;
34
+ }>;
35
+ }): Promise<void>;
36
+ export declare function applyPluginAuthBinding(raw: Record<string, unknown>, binding: PluginAuthBinding | undefined): Record<string, unknown>;
37
+ export declare function pluginOAuthScope(raw: unknown): string | undefined;
38
+ export declare function removePluginCredentials(store: AgentPluginStore, id: string): Promise<void>;
39
+ export {};
@@ -0,0 +1,156 @@
1
+ import { init_paths_state, resolveStateDir } from "../../config/paths-state.js";
2
+ import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
3
+ import { CredentialResolver, init_credentials } from "../../auth/credentials.js";
4
+ import { pluginName, pluginServerId } from "./validation.js";
5
+ import { clearPluginMcpHealth } from "./health.js";
6
+ import { isDangerousHostEnvVarName } from "../../infra/host-env-security.js";
7
+ import { McpOAuthStore } from "../../agent/mcp/oauth/mcp-oauth-store.js";
8
+ import { join } from "node:path";
9
+ import { existsSync, readFileSync, readdirSync, rmSync } from "node:fs";
10
+ import { createHash } from "node:crypto";
11
+ import { z } from "zod";
12
+ import { validateHeaderName } from "node:http";
13
+ //#region src/extensions/agent-plugins/auth.ts
14
+ init_credentials();
15
+ init_write_file_atomic();
16
+ init_paths_state();
17
+ const bindingSchema = z.strictObject({
18
+ serverName: z.string(),
19
+ mode: z.enum([
20
+ "auto",
21
+ "oauth",
22
+ "api-key",
23
+ "none"
24
+ ]),
25
+ identityScope: z.literal("owner"),
26
+ endpointFingerprint: z.string(),
27
+ fields: z.array(z.strictObject({
28
+ target: z.enum(["headers", "env"]),
29
+ key: z.string(),
30
+ provider: z.string(),
31
+ prefix: z.string()
32
+ }))
33
+ });
34
+ const hash = (value) => createHash("sha256").update(value).digest("hex");
35
+ const providerPrefix = (id) => `plugin-${hash(id).slice(0, 16)}-`;
36
+ function pluginEndpointFingerprint(server) {
37
+ return hash(server.type === "stdio" ? JSON.stringify(server) : new URL(server.url).toString());
38
+ }
39
+ function bindingPath(store, id, name) {
40
+ return join(store.stateDir, "plugin-auth", pluginName.parse(id), `${hash(name)}.json`);
41
+ }
42
+ function readPluginAuthBinding(store, id, name, server) {
43
+ const path = bindingPath(store, id, name);
44
+ if (!existsSync(path)) return void 0;
45
+ const binding = bindingSchema.parse(JSON.parse(readFileSync(path, "utf8")));
46
+ return binding.endpointFingerprint === pluginEndpointFingerprint(server) ? binding : void 0;
47
+ }
48
+ async function savePluginAuthBinding(store, id, name, input) {
49
+ const plugin = store.get(id);
50
+ const server = plugin?.servers[name];
51
+ if (!server || plugin?.readiness === "blocked") throw new Error("Plugin MCP server unavailable");
52
+ if (input.mode === "oauth" && server.type !== "streamable-http") throw new Error("OAuth requires streamable HTTP");
53
+ const endpointFingerprint = pluginEndpointFingerprint(server);
54
+ const fields = [];
55
+ const resolver = new CredentialResolver(store.stateDir === resolveStateDir() ? {} : { stateDir: store.stateDir });
56
+ if (input.mode !== "api-key" && input.secrets?.length) throw new Error("Secrets require api-key mode");
57
+ const seen = /* @__PURE__ */ new Set();
58
+ for (const field of input.secrets ?? []) {
59
+ if (!field.value || field.value.length > 16384 || /[\r\n\0]/.test(field.value) || /[\r\n\0]/.test(field.prefix ?? "")) throw new Error("Invalid secret value");
60
+ if (field.target === "headers") {
61
+ validateHeaderName(field.key);
62
+ if (server.type === "stdio") throw new Error("stdio credentials must use env");
63
+ if ([
64
+ "host",
65
+ "content-length",
66
+ "connection",
67
+ "transfer-encoding",
68
+ "cookie"
69
+ ].includes(field.key.toLowerCase())) throw new Error("Unsupported credential header");
70
+ } else if (server.type !== "stdio" || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(field.key) || /^(PLUGIN_ROOT|PLUGIN_DATA|PATH)$/i.test(field.key) || isDangerousHostEnvVarName(field.key)) throw new Error("Unsupported credential environment variable");
71
+ const normalizedKey = field.target === "headers" || process.platform === "win32" ? field.key.toLowerCase() : field.key;
72
+ if (seen.has(normalizedKey)) throw new Error("Duplicate credential field");
73
+ seen.add(normalizedKey);
74
+ const provider = `${providerPrefix(id)}${hash(JSON.stringify([
75
+ "owner",
76
+ id,
77
+ name,
78
+ endpointFingerprint,
79
+ field.target,
80
+ normalizedKey
81
+ ]))}`;
82
+ fields.push({
83
+ target: field.target,
84
+ key: field.key,
85
+ provider,
86
+ prefix: field.prefix ?? ""
87
+ });
88
+ }
89
+ for (let i = 0; i < fields.length; i++) await resolver.saveApiKey(fields[i].provider, input.secrets[i].value);
90
+ const binding = bindingSchema.parse({
91
+ serverName: name,
92
+ mode: input.mode,
93
+ identityScope: "owner",
94
+ endpointFingerprint,
95
+ fields
96
+ });
97
+ await writeTextAtomic(bindingPath(store, id, name), JSON.stringify(binding));
98
+ clearPluginMcpHealth(id, name, store.stateDir);
99
+ }
100
+ function applyPluginAuthBinding(raw, binding) {
101
+ if (!binding) return raw;
102
+ const result = { ...raw };
103
+ if (binding.mode === "none" || binding.mode === "api-key") {
104
+ delete result.auth;
105
+ delete result.xopcAutoAuth;
106
+ }
107
+ if (binding.mode === "oauth") {
108
+ result.auth = { type: "oauth" };
109
+ delete result.xopcAutoAuth;
110
+ result.headers = Object.fromEntries(Object.entries(result.headers ?? {}).filter(([key]) => key.toLowerCase() !== "authorization"));
111
+ }
112
+ for (const field of binding.fields) {
113
+ const values = { ...result[field.target] };
114
+ const insensitive = field.target === "headers" || process.platform === "win32";
115
+ for (const key of Object.keys(values)) if (insensitive ? key.toLowerCase() === field.key.toLowerCase() : key === field.key) delete values[key];
116
+ values[field.key] = { xopcSecretRef: {
117
+ provider: field.provider,
118
+ fieldKey: field.key,
119
+ prefix: field.prefix
120
+ } };
121
+ result[field.target] = values;
122
+ }
123
+ result.xopcAuthRevision = hash(JSON.stringify(binding));
124
+ return result;
125
+ }
126
+ function pluginOAuthScope(raw) {
127
+ const plugin = raw?.xopcPlugin;
128
+ return plugin ? `owner:${pluginServerId(plugin.id, plugin.serverName)}` : void 0;
129
+ }
130
+ async function removePluginCredentials(store, id) {
131
+ pluginName.parse(id);
132
+ const plugin = store.get(id);
133
+ const serverNames = new Set(Object.keys(plugin?.servers ?? {}));
134
+ const dir = join(store.stateDir, "plugin-auth", id);
135
+ if (existsSync(dir)) for (const file of readdirSync(dir)) {
136
+ if (!/^[a-f0-9]{64}\.json$/.test(file)) throw new Error("Unexpected plugin auth store entry");
137
+ const binding = bindingSchema.parse(JSON.parse(readFileSync(join(dir, file), "utf8")));
138
+ serverNames.add(binding.serverName);
139
+ }
140
+ const { getMcpOAuthManager } = await import("../../agent/mcp/oauth/mcp-oauth-manager.js");
141
+ for (const name of serverNames) {
142
+ await getMcpOAuthManager({ xopcPlugin: {
143
+ id,
144
+ serverName: name
145
+ } }).cancelPending();
146
+ await new McpOAuthStore(`owner:${pluginServerId(id, name)}`).deleteScope();
147
+ }
148
+ const resolver = new CredentialResolver(store.stateDir === resolveStateDir() ? {} : { stateDir: store.stateDir });
149
+ for (const profile of await resolver.listProfiles()) if (profile.provider.startsWith(providerPrefix(id))) await resolver.deleteProviderCredential(profile.provider);
150
+ if (existsSync(dir)) rmSync(dir, {
151
+ recursive: true,
152
+ force: true
153
+ });
154
+ }
155
+ //#endregion
156
+ export { applyPluginAuthBinding, pluginEndpointFingerprint, pluginOAuthScope, readPluginAuthBinding, removePluginCredentials, savePluginAuthBinding };
@@ -0,0 +1,8 @@
1
+ import type { ConnectionNeed } from '@xopcai/gateway-contract';
2
+ import { AgentPluginStore } from './store.js';
3
+ export declare function pluginMcpCandidateRef(pluginId: string, serverName: string): string;
4
+ export declare function parsePluginMcpCandidateRef(ref: string): {
5
+ pluginId: string;
6
+ serverName: string;
7
+ } | undefined;
8
+ export declare function resolvePluginMcpConnectionCandidate(ref: string, store?: AgentPluginStore): ConnectionNeed | undefined;
@@ -0,0 +1,41 @@
1
+ import { pluginServerId } from "./validation.js";
2
+ import { AgentPluginStore } from "./store.js";
3
+ //#region src/extensions/agent-plugins/connection.ts
4
+ const PREFIX = "plugin-mcp:";
5
+ function pluginMcpCandidateRef(pluginId, serverName) {
6
+ return `${PREFIX}${encodeURIComponent(pluginId)}:${encodeURIComponent(serverName)}`;
7
+ }
8
+ function parsePluginMcpCandidateRef(ref) {
9
+ if (!ref.startsWith(PREFIX)) return void 0;
10
+ const parts = ref.slice(11).split(":");
11
+ if (parts.length !== 2) return void 0;
12
+ try {
13
+ return {
14
+ pluginId: decodeURIComponent(parts[0]),
15
+ serverName: decodeURIComponent(parts[1])
16
+ };
17
+ } catch {
18
+ return;
19
+ }
20
+ }
21
+ function resolvePluginMcpConnectionCandidate(ref, store = new AgentPluginStore()) {
22
+ const parsed = parsePluginMcpCandidateRef(ref);
23
+ if (!parsed) return void 0;
24
+ const plugin = store.get(parsed.pluginId);
25
+ const server = plugin?.servers[parsed.serverName];
26
+ if (!plugin || !server || !plugin.receipt.enabled || plugin.readiness === "blocked" || server.type !== "streamable-http") return;
27
+ const serverId = pluginServerId(plugin.id, parsed.serverName);
28
+ return {
29
+ key: serverId,
30
+ target: {
31
+ type: "plugin-mcp",
32
+ pluginId: plugin.id,
33
+ serverId,
34
+ serverName: parsed.serverName
35
+ },
36
+ label: plugin.manifest.name,
37
+ capabilities: [`mcp.tools:${serverId}`]
38
+ };
39
+ }
40
+ //#endregion
41
+ export { parsePluginMcpCandidateRef, pluginMcpCandidateRef, resolvePluginMcpConnectionCandidate };