@xopcai/xopc 0.0.224 → 0.0.227

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 (232) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/demo-memory/src/index.js +10 -1
  3. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  4. package/dist/extensions/telegram/xopc.extension.json +1 -1
  5. package/dist/gateway/static/root/assets/{activity-store--GBciH10.js → activity-store-BevwE16n.js} +1 -1
  6. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-K7V4XXt7.js → agent-avatar-dicebear-BggVQrEZ.js} +1 -1
  7. package/dist/gateway/static/root/assets/agents-TJpjRHnr.js +68 -0
  8. package/dist/gateway/static/root/assets/{api-HoIz_ija.js → api-Bx_BpIt8.js} +1 -1
  9. package/dist/gateway/static/root/assets/{app-management-settings-panel-xQCmkAHh.js → app-management-settings-panel-BtKP9n2r.js} +1 -1
  10. package/dist/gateway/static/root/assets/{appearance-settings-BRoeA4kU.js → appearance-settings-BoH2NAUX.js} +1 -1
  11. package/dist/gateway/static/root/assets/apps-page-CZ4Da51l.js +1 -0
  12. package/dist/gateway/static/root/assets/{archive-plugin-CteCVsBP.js → archive-plugin-DnceUyxm.js} +1 -1
  13. package/dist/gateway/static/root/assets/{attachment-load-D7xNA2jB.js → attachment-load-Bh8_9gkr.js} +1 -1
  14. package/dist/gateway/static/root/assets/{automations-page-BD1vK7r5.js → automations-page-ZKeAAVxD.js} +1 -1
  15. package/dist/gateway/static/root/assets/automations-workspace-2Y00PvJU.js +6 -0
  16. package/dist/gateway/static/root/assets/{binary-plugins-C3DaJa0W.js → binary-plugins-Cy9er6w-.js} +1 -1
  17. package/dist/gateway/static/root/assets/{block-editor-lTkcHTve.js → block-editor-Cc0wWvNX.js} +3 -3
  18. package/dist/gateway/static/root/assets/browser-settings-page-CbJD27_j.js +8 -0
  19. package/dist/gateway/static/root/assets/{browser-workflow-inputs-1UZ0vnIy.js → browser-workflow-inputs-BS7rpLLl.js} +1 -1
  20. package/dist/gateway/static/root/assets/{browser-workflows-page-BHuJOF4M.js → browser-workflows-page-BdBVUZXm.js} +2 -2
  21. package/dist/gateway/static/root/assets/capabilities-settings-panel-Dv8y6OuP.js +7 -0
  22. package/dist/gateway/static/root/assets/{capability-presets-api-yNqTIuyd.js → capability-presets-api-D1Lqz0Tt.js} +1 -1
  23. package/dist/gateway/static/root/assets/capability-presets-settings-panel-TZmjzWzt.js +3 -0
  24. package/dist/gateway/static/root/assets/{channel-recipient-api-krezGsKc.js → channel-recipient-api-CGuEl-l2.js} +1 -1
  25. package/dist/gateway/static/root/assets/{channels-settings-B4AtvQHk.js → channels-settings-g-68dutA.js} +1 -1
  26. package/dist/gateway/static/root/assets/channels-status-swr-D7KsAeWh.js +1 -0
  27. package/dist/gateway/static/root/assets/{chat-terminal-dock-BRrL2iHA.js → chat-terminal-dock-CdX_7aQh.js} +1 -1
  28. package/dist/gateway/static/root/assets/connectors-page-DXA0rAvQ.js +2 -0
  29. package/dist/gateway/static/root/assets/{cron-expression-Bl-2DzBQ.js → cron-expression-BnSQc4Ek.js} +1 -1
  30. package/dist/gateway/static/root/assets/{date-picker-CxTl6Wlz.js → date-picker-BbuG7zQ_.js} +1 -1
  31. package/dist/gateway/static/root/assets/{dependency-picker-DSl0mOPa.js → dependency-picker-snZeqOmG.js} +1 -1
  32. package/dist/gateway/static/root/assets/{desktop-pet-DTeCmCdb.js → desktop-pet-DJQ8JoR1.js} +1 -1
  33. package/dist/gateway/static/root/assets/{desktop-pet-settings-BNebxg0V.js → desktop-pet-settings-B9txsRtv.js} +1 -1
  34. package/dist/gateway/static/root/assets/{directory-picker-path-field-Dn9XpmXY.js → directory-picker-path-field-D7WKWkNB.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-debug-page-D-J-eOTb.js → extension-debug-page-D_7cOCj2.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-page-CpST24nU.js → extension-page-Bwu47iUb.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-settings-page-4nQXFnFq.js → extension-settings-page-Dwg4dSZM.js} +1 -1
  38. package/dist/gateway/static/root/assets/{gateway-config-api-BHWHduDi.js → gateway-config-api-jURUSte_.js} +1 -1
  39. package/dist/gateway/static/root/assets/{gateway-config-swr-yUxMMVjK.js → gateway-config-swr-6SQXF1yR.js} +1 -1
  40. package/dist/gateway/static/root/assets/{gateway-settings-BimMKmkM.js → gateway-settings-UklJOMLX.js} +1 -1
  41. package/dist/gateway/static/root/assets/{gateway-startup-retry-9mrsL84j.js → gateway-startup-retry-DqWaxyvZ.js} +1 -1
  42. package/dist/gateway/static/root/assets/heartbeat-settings-Djs_nduD.js +1 -0
  43. package/dist/gateway/static/root/assets/{home-page-DSM6aPHF.js → home-page-i6bXCHdo.js} +1 -1
  44. package/dist/gateway/static/root/assets/{image-generation-api-CgFAGDi8.js → image-generation-api-Bxmt6LEr.js} +1 -1
  45. package/dist/gateway/static/root/assets/index-BBBE89vm.css +2 -0
  46. package/dist/gateway/static/root/assets/index-BsD5wygl.js +74 -0
  47. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-6Ar5rfX4.js → keyboard-shortcuts-settings-ByVsCH3d.js} +1 -1
  48. package/dist/gateway/static/root/assets/{local-app-workbench-page-tzM0wTL8.js → local-app-workbench-page-BCKEDMlP.js} +2 -2
  49. package/dist/gateway/static/root/assets/{local-apps-page-B5n-x544.js → local-apps-page-D19R-xsz.js} +1 -1
  50. package/dist/gateway/static/root/assets/{locale-store-CPylQjH9.js → locale-store-Ci1Qi0Q-.js} +1 -1
  51. package/dist/gateway/static/root/assets/{logs-page-CgoQlera.js → logs-page-Cy9YQK7j.js} +2 -2
  52. package/dist/gateway/static/root/assets/{management-settings-CXBLyU-0.js → management-settings-G0y7zmfY.js} +1 -1
  53. package/dist/gateway/static/root/assets/{markdown-split-CtmQemJi.js → markdown-split-B69d2HWt.js} +1 -1
  54. package/dist/gateway/static/root/assets/{markdown-view-CUsob4Pz.js → markdown-view-CBM-v2ph.js} +1 -1
  55. package/dist/gateway/static/root/assets/{media-plugins-Dsd-IEOW.js → media-plugins-6TWEQgN_.js} +1 -1
  56. package/dist/gateway/static/root/assets/messages-CtOJwGW3.js +3 -0
  57. package/dist/gateway/static/root/assets/{notes-api-CfKZYrBC.js → notes-api-DLsnnZCS.js} +1 -1
  58. package/dist/gateway/static/root/assets/{notes-page-BKbOTE2n.js → notes-page-CkRJJKDm.js} +1 -1
  59. package/dist/gateway/static/root/assets/notes-workbench-B10T3hGX.js +4 -0
  60. package/dist/gateway/static/root/assets/{product-open-page-DqB9bsDB.js → product-open-page-HxArIvoN.js} +1 -1
  61. package/dist/gateway/static/root/assets/project-detail-page-DsqRlgsy.js +1 -0
  62. package/dist/gateway/static/root/assets/{projects-page-PeXUdGdO.js → projects-page-Bu2PN8OK.js} +1 -1
  63. package/dist/gateway/static/root/assets/{registry-api-B_5D8epF.js → registry-api-lEar5FOV.js} +1 -1
  64. package/dist/gateway/static/root/assets/remote-access-hub-CXACdJ2f.js +1 -0
  65. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DBTH_t0O.js → runtime-tools-settings-panel-Bf03UNGD.js} +2 -2
  66. package/dist/gateway/static/root/assets/{schema-form-CqMKAwV0.js → schema-form-CIXMBgx5.js} +1 -1
  67. package/dist/gateway/static/root/assets/sessions-page-CS2knWDT.js +1 -0
  68. package/dist/gateway/static/root/assets/settings-advanced-gate-ByFGk0q_.js +1 -0
  69. package/dist/gateway/static/root/assets/{settings-form-section-dPriuuYq.js → settings-form-section-DgdB26mE.js} +1 -1
  70. package/dist/gateway/static/root/assets/{settings-loading-skeleton-B-Mbm8Va.js → settings-loading-skeleton-efk5W6lG.js} +1 -1
  71. package/dist/gateway/static/root/assets/{settings-page-Dyj3w-Ml.js → settings-page-BHVf4gEP.js} +1 -1
  72. package/dist/gateway/static/root/assets/{setup-status-panel-C4FxY5J3.js → setup-status-panel-WK0dGNMv.js} +1 -1
  73. package/dist/gateway/static/root/assets/{share-preview-page-emEdx7YL.js → share-preview-page-Cod-w2qm.js} +1 -1
  74. package/dist/gateway/static/root/assets/shares-settings-CUqQ31gt.js +1 -0
  75. package/dist/gateway/static/root/assets/skill-reload-api-DweAPjI8.js +1 -0
  76. package/dist/gateway/static/root/assets/{skills-page-BNtYnrRT.js → skills-page-DwCcipqK.js} +1 -1
  77. package/dist/gateway/static/root/assets/{skills-page.utils-DjnbNFs5.js → skills-page.utils-3WSbtl3S.js} +1 -1
  78. package/dist/gateway/static/root/assets/{system-settings-panel-DDStf-jZ.js → system-settings-panel-C5VxqC_s.js} +1 -1
  79. package/dist/gateway/static/root/assets/task-detail-page-DEj-BFMP.js +1 -0
  80. package/dist/gateway/static/root/assets/{theme-store-BN-32Fz5.js → theme-store-Dd89g_ki.js} +1 -1
  81. package/dist/gateway/static/root/assets/{use-autosave-C2mKZ-ua.js → use-autosave-CeV8VJh2.js} +1 -1
  82. package/dist/gateway/static/root/assets/user-context-page-f7yh7aD5.js +1 -0
  83. package/dist/gateway/static/root/assets/{voice-api-key-field-D7OHeQby.js → voice-api-key-field-EmJ-8aZu.js} +1 -1
  84. package/dist/gateway/static/root/assets/{work-discovery-overlay-CIiXie7F.js → work-discovery-overlay-zsk6E3Mi.js} +1 -1
  85. package/dist/gateway/static/root/assets/workflow-run-setup-panel-CBAYvm3G.js +3 -0
  86. package/dist/gateway/static/root/assets/workflows-page-BN0JmHrG.js +5 -0
  87. package/dist/gateway/static/root/index.html +11 -11
  88. package/dist/package.js +1 -1
  89. package/dist/src/agent/agent-manager.d.ts +3 -1
  90. package/dist/src/agent/agent-manager.js +22 -5
  91. package/dist/src/agent/embedded/run-turn.js +2 -0
  92. package/dist/src/agent/mcp/bundle-mcp-config.d.ts +9 -1
  93. package/dist/src/agent/mcp/bundle-mcp-config.js +11 -15
  94. package/dist/src/agent/mcp/embedded-mcp.d.ts +1 -1
  95. package/dist/src/agent/mcp/index.d.ts +1 -0
  96. package/dist/src/agent/mcp/index.js +7 -1
  97. package/dist/src/agent/mcp/mcp-http.d.ts +4 -0
  98. package/dist/src/agent/mcp/mcp-http.js +25 -1
  99. package/dist/src/agent/mcp/mcp-transport-config.d.ts +4 -0
  100. package/dist/src/agent/mcp/mcp-transport-config.js +1 -0
  101. package/dist/src/agent/mcp/mcp-transport.d.ts +7 -1
  102. package/dist/src/agent/mcp/mcp-transport.js +38 -11
  103. package/dist/src/agent/mcp/oauth/index.d.ts +6 -0
  104. package/dist/src/agent/mcp/oauth/index.js +6 -0
  105. package/dist/src/agent/mcp/oauth/mcp-oauth-errors.d.ts +5 -0
  106. package/dist/src/agent/mcp/oauth/mcp-oauth-errors.js +14 -0
  107. package/dist/src/agent/mcp/oauth/mcp-oauth-manager.d.ts +25 -0
  108. package/dist/src/agent/mcp/oauth/mcp-oauth-manager.js +219 -0
  109. package/dist/src/agent/mcp/oauth/mcp-oauth-provider.d.ts +33 -0
  110. package/dist/src/agent/mcp/oauth/mcp-oauth-provider.js +103 -0
  111. package/dist/src/agent/mcp/oauth/mcp-oauth-session.d.ts +29 -0
  112. package/dist/src/agent/mcp/oauth/mcp-oauth-session.js +169 -0
  113. package/dist/src/agent/mcp/oauth/mcp-oauth-store.d.ts +9 -0
  114. package/dist/src/agent/mcp/oauth/mcp-oauth-store.js +79 -0
  115. package/dist/src/agent/mcp/oauth/mcp-oauth-types.d.ts +22 -0
  116. package/dist/src/agent/mcp/oauth/mcp-oauth-types.js +1 -0
  117. package/dist/src/agent/memory/builtin-provider.js +23 -4
  118. package/dist/src/agent/memory/compaction-promotion.d.ts +18 -0
  119. package/dist/src/agent/memory/compaction-promotion.js +211 -0
  120. package/dist/src/agent/memory/context/types.d.ts +5 -0
  121. package/dist/src/agent/memory/manager.d.ts +3 -0
  122. package/dist/src/agent/memory/manager.js +12 -2
  123. package/dist/src/agent/memory/trusted-recall.d.ts +7 -0
  124. package/dist/src/agent/memory/trusted-recall.js +53 -0
  125. package/dist/src/agent/memory/turn-provenance.d.ts +14 -0
  126. package/dist/src/agent/memory/turn-provenance.js +60 -0
  127. package/dist/src/agent/memory/types.d.ts +18 -3
  128. package/dist/src/agent/memory/understanding/service.js +1 -0
  129. package/dist/src/agent/memory/understanding/types.d.ts +1 -0
  130. package/dist/src/agent/memory/user-context-coordinator.js +57 -6
  131. package/dist/src/agent/service.d.ts +2 -0
  132. package/dist/src/agent/service.js +6 -0
  133. package/dist/src/agent/skills/index.d.ts +22 -2
  134. package/dist/src/agent/skills/index.js +74 -32
  135. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.d.ts +2 -0
  136. package/dist/src/agent/skills/skill-sources.d.ts +0 -1
  137. package/dist/src/agent/skills/skill-sources.js +1 -11
  138. package/dist/src/agent/tools/memory-tool.js +5 -1
  139. package/dist/src/capabilities/store-connector.js +99 -10
  140. package/dist/src/cli/commands/channels.js +1 -1
  141. package/dist/src/cli/commands/connectors.js +1 -1
  142. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  143. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  144. package/dist/src/cli/commands/models.js +1 -1
  145. package/dist/src/cli/commands/onboard.js +1 -1
  146. package/dist/src/config/config-mutation.d.ts +14 -0
  147. package/dist/src/config/config-mutation.js +33 -0
  148. package/dist/src/config/index.js +3 -3
  149. package/dist/src/config/paths.d.ts +2 -0
  150. package/dist/src/config/paths.js +5 -1
  151. package/dist/src/config/schema.d.ts +17 -0
  152. package/dist/src/config/schema.js +26 -2
  153. package/dist/src/connectors/auth-provider-registry.d.ts +1 -1
  154. package/dist/src/connectors/auth-provider-registry.js +23 -2
  155. package/dist/src/connectors/connected-source-understanding.js +1 -1
  156. package/dist/src/connectors/install.js +3 -3
  157. package/dist/src/connectors/instances.d.ts +2 -1
  158. package/dist/src/connectors/instances.js +15 -5
  159. package/dist/src/connectors/materialize.d.ts +1 -0
  160. package/dist/src/connectors/materialize.js +9 -1
  161. package/dist/src/connectors/runtime-adapter-registry.js +1 -0
  162. package/dist/src/connectors/types.d.ts +4 -1
  163. package/dist/src/extensions/connector-dependencies.d.ts +10 -0
  164. package/dist/src/extensions/connector-dependencies.js +65 -0
  165. package/dist/src/extensions/install.js +27 -0
  166. package/dist/src/extensions/normalize-manifest.js +1 -0
  167. package/dist/src/extensions/sdk/index.js +1 -1
  168. package/dist/src/extensions/types/manifest.d.ts +2 -0
  169. package/dist/src/gateway/hono/routes/capabilities.js +8 -8
  170. package/dist/src/gateway/hono/routes/connectors.js +104 -70
  171. package/dist/src/gateway/hono/routes/mcp.js +77 -5
  172. package/dist/src/gateway/hono/routes/project-skills.js +30 -2
  173. package/dist/src/gateway/hono/routes/you.js +52 -0
  174. package/dist/src/gateway/service.js +8 -8
  175. package/dist/src/knowledge/connected-knowledge-pipeline.js +26 -4
  176. package/dist/src/knowledge/connected-understanding-pipeline.js +12 -3
  177. package/dist/src/knowledge/index.d.ts +0 -1
  178. package/dist/src/knowledge/index.js +1 -2
  179. package/dist/src/projects/project-skill-service.d.ts +28 -6
  180. package/dist/src/projects/project-skill-service.js +76 -29
  181. package/dist/src/session/store.js +27 -0
  182. package/dist/src/storage/sqlite/index.d.ts +1 -0
  183. package/dist/src/storage/sqlite/index.js +2 -1
  184. package/dist/src/storage/sqlite/memory-records-repository.d.ts +9 -1
  185. package/dist/src/storage/sqlite/memory-records-repository.js +40 -6
  186. package/dist/src/storage/sqlite/migrations/134_memory_provenance.sql +18 -0
  187. package/dist/src/storage/sqlite/migrations/135_user_people.sql +59 -0
  188. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  189. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  190. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  191. package/dist/src/storage/sqlite/schema.js +1 -1
  192. package/dist/src/storage/sqlite/user-people-repository.d.ts +32 -0
  193. package/dist/src/storage/sqlite/user-people-repository.js +246 -0
  194. package/dist/src/tui/backends/embedded-backend.js +1 -1
  195. package/dist/src/user-context/planner.js +8 -3
  196. package/dist/src/user-context/relationships/indexer.d.ts +13 -0
  197. package/dist/src/user-context/relationships/indexer.js +185 -0
  198. package/dist/src/user-context/relationships/service.d.ts +22 -0
  199. package/dist/src/user-context/relationships/service.js +50 -0
  200. package/dist/src/user-context/relationships/types.d.ts +55 -0
  201. package/dist/src/user-context/relationships/types.js +10 -0
  202. package/dist/src/user-context/sources/repository.d.ts +1 -1
  203. package/dist/src/user-context/sources/repository.js +8 -2
  204. package/dist/src/work-discovery/service.js +1 -1
  205. package/package.json +2 -2
  206. package/dist/gateway/static/root/assets/agents-BsxTpXyq.js +0 -68
  207. package/dist/gateway/static/root/assets/apps-page-BXgpBA8w.js +0 -1
  208. package/dist/gateway/static/root/assets/automations-workspace-wrgf-z7D.js +0 -6
  209. package/dist/gateway/static/root/assets/browser-settings-page-zhzNkeVG.js +0 -8
  210. package/dist/gateway/static/root/assets/capabilities-settings-panel-DuCmg2Ej.js +0 -7
  211. package/dist/gateway/static/root/assets/capability-presets-settings-panel-DjiP3mQQ.js +0 -3
  212. package/dist/gateway/static/root/assets/channels-status-swr-DMxB7slL.js +0 -1
  213. package/dist/gateway/static/root/assets/connectors-page-fmda2NEP.js +0 -2
  214. package/dist/gateway/static/root/assets/heartbeat-settings-MUJ3mEC9.js +0 -1
  215. package/dist/gateway/static/root/assets/index-B3zYJBhK.js +0 -74
  216. package/dist/gateway/static/root/assets/index-D3_xSYKd.css +0 -2
  217. package/dist/gateway/static/root/assets/messages-B82nsi9k.js +0 -3
  218. package/dist/gateway/static/root/assets/notes-workbench-BScELo01.js +0 -4
  219. package/dist/gateway/static/root/assets/project-detail-page-DUoyty8X.js +0 -1
  220. package/dist/gateway/static/root/assets/remote-access-hub-sHho-uXP.js +0 -1
  221. package/dist/gateway/static/root/assets/sessions-page-DyvNgaP9.js +0 -1
  222. package/dist/gateway/static/root/assets/settings-advanced-gate-CnYf1R7z.js +0 -1
  223. package/dist/gateway/static/root/assets/shares-settings-BQBVq-sN.js +0 -1
  224. package/dist/gateway/static/root/assets/skill-reload-api-BFoEpQ4I.js +0 -1
  225. package/dist/gateway/static/root/assets/task-detail-page-ZVwr8KbS.js +0 -1
  226. package/dist/gateway/static/root/assets/user-context-page-CHjIinCW.js +0 -1
  227. package/dist/gateway/static/root/assets/workflow-run-setup-panel-9_dAGW3_.js +0 -3
  228. package/dist/gateway/static/root/assets/workflows-page-DXpYJxao.js +0 -5
  229. package/dist/src/extensions/bundle-mcp.d.ts +0 -18
  230. package/dist/src/extensions/bundle-mcp.js +0 -69
  231. package/dist/src/knowledge/people-graph.d.ts +0 -25
  232. package/dist/src/knowledge/people-graph.js +0 -92
@@ -4,6 +4,7 @@ export declare function materializeConnectorMcpServer(definition: ConnectorDefin
4
4
  serverId: string;
5
5
  server: Record<string, unknown>;
6
6
  };
7
+ export declare function connectorDefinitionFromManagedMarker(marker: unknown): ConnectorDefinition | undefined;
7
8
  export declare function isManagedConnectorServer(server: unknown): server is Record<string, unknown> & {
8
9
  xopcConnector: ManagedConnectorMarker;
9
10
  };
@@ -56,6 +56,7 @@ function materializeConnectorMcpServer(definition, input) {
56
56
  displayName: definition.displayName,
57
57
  source: definition.source,
58
58
  artifactSha256: definition.provenance?.sha256,
59
+ definition,
59
60
  ...input.config && Object.keys(input.config).length > 0 ? { config: input.config } : {}
60
61
  };
61
62
  const server = {
@@ -69,10 +70,17 @@ function materializeConnectorMcpServer(definition, input) {
69
70
  server
70
71
  };
71
72
  }
73
+ function connectorDefinitionFromManagedMarker(marker) {
74
+ if (!marker || typeof marker !== "object" || Array.isArray(marker)) return void 0;
75
+ const definition = marker.definition;
76
+ if (!definition || typeof definition !== "object" || Array.isArray(definition)) return void 0;
77
+ const record = definition;
78
+ return typeof record.id === "string" && typeof record.version === "string" && record.runtime ? record : void 0;
79
+ }
72
80
  function isManagedConnectorServer(server) {
73
81
  if (!server || typeof server !== "object" || Array.isArray(server)) return false;
74
82
  const marker = server.xopcConnector;
75
83
  return Boolean(marker && typeof marker === "object" && !Array.isArray(marker) && marker.managed === true && typeof marker.connectorId === "string");
76
84
  }
77
85
  //#endregion
78
- export { assertValidConnectorServerId, isManagedConnectorServer, materializeConnectorMcpServer };
86
+ export { assertValidConnectorServerId, connectorDefinitionFromManagedMarker, isManagedConnectorServer, materializeConnectorMcpServer };
@@ -32,6 +32,7 @@ function installRecord(config, definition, extra = {}, markerExtra = {}) {
32
32
  displayName: definition.displayName,
33
33
  source: definition.source,
34
34
  artifactSha256: definition.provenance?.sha256,
35
+ definition,
35
36
  ...markerExtra
36
37
  },
37
38
  runtime: definition.runtime,
@@ -8,7 +8,8 @@ export type ConnectorAuthDefinition = {
8
8
  mode: 'apiKey';
9
9
  } | {
10
10
  mode: 'oauth';
11
- provider: string;
11
+ provider?: string;
12
+ clientId?: string;
12
13
  };
13
14
  export type ConnectorScope = 'read' | 'write' | 'admin';
14
15
  export type ConnectorVerificationLevel = 'verified' | 'beta' | 'experimental';
@@ -289,4 +290,6 @@ export type ManagedConnectorMarker = {
289
290
  config?: Record<string, unknown>;
290
291
  source?: ConnectorDefinition['source'];
291
292
  artifactSha256?: string;
293
+ /** Immutable install-time snapshot used for update, health, and uninstall after restart. */
294
+ definition?: ConnectorDefinition;
292
295
  };
@@ -0,0 +1,10 @@
1
+ import type { Config } from '../config/schema.js';
2
+ export type ExtensionConnectorDiagnostic = {
3
+ extensionId: string;
4
+ connectorId: string;
5
+ message: string;
6
+ };
7
+ export declare function inspectExtensionConnectorDependencies(params: {
8
+ cfg?: Config;
9
+ roots?: string[];
10
+ }): ExtensionConnectorDiagnostic[];
@@ -0,0 +1,65 @@
1
+ import { init_paths, resolveBundledExtensionsDir, resolveExtensionsDir } from "../config/paths.js";
2
+ import { isRecord } from "../utils/is-record.js";
3
+ import { join } from "node:path";
4
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
5
+ //#region src/extensions/connector-dependencies.ts
6
+ init_paths();
7
+ function isExtensionEnabled(extensionId, cfg) {
8
+ const disabled = cfg?.extensions?.disabled;
9
+ if (Array.isArray(disabled) && disabled.includes(extensionId)) return false;
10
+ const enabled = cfg?.extensions?.enabled;
11
+ return !Array.isArray(enabled) || enabled.length === 0 || enabled.includes(extensionId);
12
+ }
13
+ function enabledConnectorIds(cfg) {
14
+ const ids = /* @__PURE__ */ new Set();
15
+ for (const server of Object.values(cfg?.mcp?.servers ?? {})) {
16
+ if (!isRecord(server) || !isRecord(server.xopcConnector)) continue;
17
+ if (server.xopcConnector.managed === true && server.xopcConnector.enabled !== false && typeof server.xopcConnector.connectorId === "string") ids.add(server.xopcConnector.connectorId);
18
+ }
19
+ for (const instance of Object.values(cfg?.connectors?.instances ?? {})) {
20
+ if (!isRecord(instance) || !isRecord(instance.xopcConnector)) continue;
21
+ if (instance.xopcConnector.managed === true && instance.xopcConnector.enabled !== false && typeof instance.xopcConnector.connectorId === "string") ids.add(instance.xopcConnector.connectorId);
22
+ }
23
+ return ids;
24
+ }
25
+ function scanRoot(params) {
26
+ if (!existsSync(params.root)) return;
27
+ for (const entry of readdirSync(params.root, { withFileTypes: true })) {
28
+ if (!entry.isDirectory() || params.seenExtensions.has(entry.name) || !isExtensionEnabled(entry.name, params.cfg)) continue;
29
+ const manifestPath = join(params.root, entry.name, "xopc.extension.json");
30
+ if (!existsSync(manifestPath)) continue;
31
+ params.seenExtensions.add(entry.name);
32
+ let manifest;
33
+ try {
34
+ manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
35
+ } catch {
36
+ continue;
37
+ }
38
+ if (!isRecord(manifest) || !Array.isArray(manifest.connectorDependencies)) continue;
39
+ const dependencies = [...new Set(manifest.connectorDependencies.filter((value) => typeof value === "string").map((value) => value.trim()).filter(Boolean))];
40
+ for (const connectorId of dependencies) {
41
+ if (params.installed.has(connectorId)) continue;
42
+ params.diagnostics.push({
43
+ extensionId: entry.name,
44
+ connectorId,
45
+ message: `Extension "${entry.name}" requires enabled Connector "${connectorId}". Install and connect it from the Connector Store.`
46
+ });
47
+ }
48
+ }
49
+ }
50
+ function inspectExtensionConnectorDependencies(params) {
51
+ const diagnostics = [];
52
+ const installed = enabledConnectorIds(params.cfg);
53
+ const seenExtensions = /* @__PURE__ */ new Set();
54
+ const roots = params.roots ?? [resolveExtensionsDir(), resolveBundledExtensionsDir()].filter((root) => Boolean(root));
55
+ for (const root of roots) scanRoot({
56
+ root,
57
+ cfg: params.cfg,
58
+ installed,
59
+ seenExtensions,
60
+ diagnostics
61
+ });
62
+ return diagnostics;
63
+ }
64
+ //#endregion
65
+ export { inspectExtensionConnectorDependencies };
@@ -172,6 +172,24 @@ function isSafeZipPath(name) {
172
172
  for (const p of normalized.split("/")) if (p === "..") return false;
173
173
  return true;
174
174
  }
175
+ function findEmbeddedMcpConfig(root) {
176
+ for (const entry of readdirSync(root, { withFileTypes: true })) {
177
+ if (entry.isSymbolicLink()) continue;
178
+ const path = join(root, entry.name);
179
+ if (entry.isFile() && entry.name.toLowerCase() === ".mcp.json") return path;
180
+ if (entry.isDirectory()) {
181
+ const nested = findEmbeddedMcpConfig(path);
182
+ if (nested) return nested;
183
+ }
184
+ }
185
+ }
186
+ function validateConnectorDependencies(value) {
187
+ if (value === void 0) return void 0;
188
+ if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) return "Extension connectorDependencies must be an array of unique Connector ids";
189
+ const dependencies = value;
190
+ const validId = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/;
191
+ if (dependencies.some((id) => !validId.test(id)) || new Set(dependencies).size !== dependencies.length) return "Extension connectorDependencies must be an array of unique Connector ids";
192
+ }
175
193
  function isIgnorableZipEntry(name) {
176
194
  const n = name.replace(/\\/g, "/");
177
195
  if (n.startsWith("__MACOSX/")) return true;
@@ -448,6 +466,15 @@ async function installFromDirectory(sourceDir, extensionsDir) {
448
466
  ok: false,
449
467
  error: "Extension must include xopc.extension.json"
450
468
  };
469
+ if (findEmbeddedMcpConfig(sourceDir)) return {
470
+ ok: false,
471
+ error: "Extensions must declare connectorDependencies instead of embedding .mcp.json"
472
+ };
473
+ const connectorDependencyError = validateConnectorDependencies(manifest.connectorDependencies);
474
+ if (connectorDependencyError) return {
475
+ ok: false,
476
+ error: connectorDependencyError
477
+ };
451
478
  if (!manifest.engines?.xopc) return {
452
479
  ok: false,
453
480
  error: "Extension manifest must declare engines.xopc"
@@ -130,6 +130,7 @@ function normalizeExtensionManifest(raw) {
130
130
  main: typeof raw.main === "string" ? raw.main : void 0,
131
131
  configSchema: isRecord(raw.configSchema) ? raw.configSchema : void 0,
132
132
  dependencies: isRecord(raw.dependencies) ? raw.dependencies : void 0,
133
+ connectorDependencies: Array.isArray(raw.connectorDependencies) ? [...new Set(raw.connectorDependencies.filter((value) => typeof value === "string").map((value) => value.trim()).filter(Boolean))] : void 0,
133
134
  enabledByDefault: typeof raw.enabledByDefault === "boolean" ? raw.enabledByDefault : void 0,
134
135
  providers: Array.isArray(raw.providers) ? raw.providers.filter((x) => typeof x === "string") : void 0,
135
136
  speechProviders: Array.isArray(raw.speechProviders) ? raw.speechProviders.filter((x) => typeof x === "string") : void 0,
@@ -7,8 +7,8 @@ import { SlotRegistry, getSlotRegistry, registerSlotType } from "../slots.js";
7
7
  import { ExtensionDiagnostics, ExtensionLoaderCacheImpl, getExtensionCache, getExtensionDiagnostics } from "../diagnostics.js";
8
8
  import "../loader.js";
9
9
  import { ExtensionHookRunner, createHookContext, isHookEvent } from "../hooks.js";
10
- import { registerExtensionCliProgram } from "./channel-helpers.js";
11
10
  import { defineChannelPluginEntry } from "./channel-entry.js";
11
+ import { registerExtensionCliProgram } from "./channel-helpers.js";
12
12
  import { lazyFunction, lazyModule } from "./lazy.js";
13
13
  import { createMockExtensionApi, createTestGateway } from "./testing.js";
14
14
  //#region src/extensions/sdk/index.ts
@@ -20,6 +20,8 @@ export interface ExtensionManifest {
20
20
  main?: string;
21
21
  configSchema?: Record<string, unknown>;
22
22
  dependencies?: Record<string, string>;
23
+ /** Connector ids that must already be installed and enabled. Extensions never embed MCP server configuration. */
24
+ connectorDependencies?: string[];
23
25
  enabledByDefault?: boolean;
24
26
  providers?: string[];
25
27
  /** Speech/TTS provider ids implemented by this extension. */
@@ -1,4 +1,5 @@
1
1
  import { getStoreConnectorInstallPlan, installStoreConnector, listStoreConnectors } from "../../../capabilities/store-connector.js";
2
+ import { ConfigPersistenceError, persistConfigMutation } from "../../../config/config-mutation.js";
2
3
  //#region src/gateway/hono/routes/capabilities.ts
3
4
  function errorMessage(error) {
4
5
  return error instanceof Error ? error.message : String(error);
@@ -50,14 +51,13 @@ function registerCapabilityRoutes(authenticated, deps) {
50
51
  authenticated.post("/api/capabilities/connectors/:name/install", strictRateLimitMiddleware, async (c) => {
51
52
  const body = await c.req.json().catch(() => ({}));
52
53
  const input = body && typeof body === "object" && !Array.isArray(body) ? body : {};
54
+ const config = service.currentConfig;
53
55
  try {
54
- const config = service.currentConfig;
55
- const { instance, plan } = await installStoreConnector(config, c.req.param("name"), input, optionalVersion(body));
56
- const saved = await service.saveConfig(config);
57
- if (!saved.saved) return c.json({
58
- ok: false,
59
- error: saved.error ?? "Failed to save connector configuration."
60
- }, 500);
56
+ const { instance, plan } = await persistConfigMutation({
57
+ config,
58
+ mutate: () => installStoreConnector(config, c.req.param("name"), input, optionalVersion(body)),
59
+ save: () => service.saveConfig(config)
60
+ });
61
61
  return c.json({
62
62
  ok: true,
63
63
  payload: {
@@ -69,7 +69,7 @@ function registerCapabilityRoutes(authenticated, deps) {
69
69
  return c.json({
70
70
  ok: false,
71
71
  error: errorMessage(error)
72
- }, 400);
72
+ }, error instanceof ConfigPersistenceError ? 500 : 400);
73
73
  }
74
74
  });
75
75
  }
@@ -13,18 +13,19 @@ import { listConnectorProviders } from "../../../connectors/providers.js";
13
13
  import { getConnectorDefinition, listConnectorCatalog } from "../../../connectors/catalog.js";
14
14
  import { listUnderstandingSourceGrants, revokeUnderstandingSourceGrant } from "../../../user-context/sources/repository.js";
15
15
  import { recordConnectorHealthUsage } from "../../../connectors/usage.js";
16
- import { getConnectorInstance, listConnectorInstances } from "../../../connectors/instances.js";
16
+ import { getConnectorInstance, getInstalledConnectorDefinition, listConnectorInstances } from "../../../connectors/instances.js";
17
17
  import { installConnector, installConnectorDefinition, uninstallConnector, updateConnectorConfig } from "../../../connectors/install.js";
18
+ import { ConfigPersistenceError, persistConfigMutation } from "../../../config/config-mutation.js";
19
+ import { getMcpOAuthManager } from "../../../agent/mcp/oauth/mcp-oauth-manager.js";
18
20
  import { startConnectorAuthorization } from "../../../connectors/auth-provider-registry.js";
19
21
  import { composioLogoResponse } from "../../../connectors/composio-logo.js";
20
22
  import { inspectManagedComposioStatus } from "../../../connectors/composio-managed-client.js";
21
23
  import { appendComposioTriggerEvent, listComposioTriggerEvents } from "../../../connectors/composio-triggers.js";
22
- import { buildConnectedPeopleGraph } from "../../../knowledge/people-graph.js";
23
- import "../../../knowledge/index.js";
24
24
  import { ingestLocalFolderSource } from "../../../connectors/connected-source-ingestion.js";
25
25
  import { previewConnectorDefinition, testConnectorInstance } from "../../../connectors/health.js";
26
26
  import { setConnectorEnabled } from "../../../connectors/lifecycle.js";
27
27
  import { projectComposioConnectionStatus } from "../../../connectors/runtime-status.js";
28
+ import { applySourceRevocationChoices, sourceRevocationImpact } from "./understanding-sources.js";
28
29
  //#region src/gateway/hono/routes/connectors.ts
29
30
  init_agent_scope();
30
31
  function errorMessage(error) {
@@ -48,9 +49,39 @@ function registerConnectorRoutes(authenticated, deps) {
48
49
  }
49
50
  });
50
51
  });
51
- authenticated.get("/api/connectors/installed", (c) => {
52
+ authenticated.get("/api/connectors/installed", async (c) => {
52
53
  const config = service.currentConfig;
53
- const instances = listConnectorInstances(config);
54
+ const instances = await Promise.all(listConnectorInstances(config).map(async (instance) => {
55
+ if (!instance.enabled || instance.materialized.type !== "mcp") return instance;
56
+ const server = config.mcp?.servers?.[instance.materialized.serverId];
57
+ if (!server) return instance;
58
+ const oauth = await getMcpOAuthManager().status(instance.materialized.serverId, server);
59
+ if (!oauth.configured) return instance;
60
+ if (oauth.status === "connected") return {
61
+ ...instance,
62
+ authStatus: "connected",
63
+ connectionStatus: "connected"
64
+ };
65
+ if (oauth.status === "authorizing") return {
66
+ ...instance,
67
+ status: "connecting",
68
+ authStatus: "unknown",
69
+ connectionStatus: "connecting"
70
+ };
71
+ if (oauth.status === "error") return {
72
+ ...instance,
73
+ status: "failed",
74
+ authStatus: "unauthorized",
75
+ connectionStatus: "error",
76
+ lastError: oauth.session?.error ?? instance.lastError
77
+ };
78
+ return {
79
+ ...instance,
80
+ status: "unauthorized",
81
+ authStatus: "missing",
82
+ connectionStatus: "disconnected"
83
+ };
84
+ }));
54
85
  const connections = listConnectorConnections({ principalId: "local-owner" });
55
86
  return c.json({
56
87
  ok: true,
@@ -164,7 +195,14 @@ function registerConnectorRoutes(authenticated, deps) {
164
195
  if (connectionId && !policy.scanEnabled) {
165
196
  service.setConnectorLearningPaused(connectionId, true);
166
197
  const grant = listUnderstandingSourceGrants().find((item) => item.sourceKey === `connector-account:${account.id}`);
167
- if (grant) revokeUnderstandingSourceGrant(grant.id);
198
+ if (grant) {
199
+ const impact = sourceRevocationImpact(grant.id);
200
+ revokeUnderstandingSourceGrant(grant.id);
201
+ if (impact) applySourceRevocationChoices(impact, {
202
+ derived: "retain",
203
+ raw: "retain"
204
+ });
205
+ }
168
206
  } else if (connectionId && previous?.scanEnabled === false) {
169
207
  if (service.setConnectorLearningPaused(connectionId, false) === 0) service.requestConnectorLearning(connectionId, {
170
208
  mode: "incremental",
@@ -256,7 +294,14 @@ function registerConnectorRoutes(authenticated, deps) {
256
294
  await revokeComposioConnection(connectionId);
257
295
  if (connection?.accountId) {
258
296
  const grant = listUnderstandingSourceGrants().find((item) => item.sourceKey === `connector-account:${connection.accountId}`);
259
- if (grant) revokeUnderstandingSourceGrant(grant.id);
297
+ if (grant) {
298
+ const impact = sourceRevocationImpact(grant.id);
299
+ revokeUnderstandingSourceGrant(grant.id);
300
+ if (impact) applySourceRevocationChoices(impact, {
301
+ derived: "retain",
302
+ raw: "retain"
303
+ });
304
+ }
260
305
  }
261
306
  return c.json({
262
307
  ok: true,
@@ -348,12 +393,11 @@ function registerConnectorRoutes(authenticated, deps) {
348
393
  }, 400);
349
394
  const config = service.currentConfig;
350
395
  try {
351
- setComposioToolkitScope(config, toolkit, scope);
352
- const saved = await service.saveConfig(config);
353
- if (!saved.saved) return c.json({
354
- ok: false,
355
- error: saved.error
356
- }, 500);
396
+ await persistConfigMutation({
397
+ config,
398
+ mutate: () => setComposioToolkitScope(config, toolkit, scope),
399
+ save: () => service.saveConfig(config)
400
+ });
357
401
  return c.json({
358
402
  ok: true,
359
403
  payload: {
@@ -365,7 +409,7 @@ function registerConnectorRoutes(authenticated, deps) {
365
409
  return c.json({
366
410
  ok: false,
367
411
  error: errorMessage(error)
368
- }, 400);
412
+ }, error instanceof ConfigPersistenceError ? 500 : 400);
369
413
  }
370
414
  });
371
415
  authenticated.post("/api/connectors/composio/tools/:slug/execute", strictRateLimitMiddleware, async (c) => {
@@ -419,17 +463,6 @@ function registerConnectorRoutes(authenticated, deps) {
419
463
  }, 400);
420
464
  }
421
465
  });
422
- authenticated.get("/api/connectors/people", (c) => {
423
- const query = c.req.query("q") ?? "";
424
- const limit = Number(c.req.query("limit") ?? "100");
425
- return c.json({
426
- ok: true,
427
- payload: buildConnectedPeopleGraph({
428
- query,
429
- limit
430
- })
431
- });
432
- });
433
466
  authenticated.get("/api/connectors/:id", (c) => {
434
467
  const connectorId = c.req.param("id");
435
468
  const connector = getConnectorDefinition(connectorId);
@@ -573,14 +606,16 @@ function registerConnectorRoutes(authenticated, deps) {
573
606
  });
574
607
  });
575
608
  authenticated.post("/api/connectors/:id/auth/start", strictRateLimitMiddleware, async (c) => {
576
- const connectorId = c.req.param("id");
577
- const connector = getConnectorDefinition(connectorId);
609
+ const connectorOrInstanceId = c.req.param("id");
610
+ const config = service.currentConfig;
611
+ const instance = getConnectorInstance(config, connectorOrInstanceId);
612
+ const connector = instance ? getInstalledConnectorDefinition(config, instance.instanceId) : getConnectorDefinition(connectorOrInstanceId);
578
613
  if (!connector) return c.json({
579
614
  ok: false,
580
- error: `Unknown connector: ${connectorId}`
615
+ error: `Unknown connector: ${connectorOrInstanceId}`
581
616
  }, 404);
582
617
  try {
583
- const authorization = await startConnectorAuthorization(connector, service.currentConfig);
618
+ const authorization = await startConnectorAuthorization(connector, config, instance?.instanceId);
584
619
  return c.json({
585
620
  ok: true,
586
621
  payload: { authorization }
@@ -628,12 +663,11 @@ function registerConnectorRoutes(authenticated, deps) {
628
663
  const registryDefinition = body && typeof body === "object" && !Array.isArray(body) && body.definition && typeof body.definition === "object" && !Array.isArray(body.definition) ? body.definition : void 0;
629
664
  const config = service.currentConfig;
630
665
  try {
631
- const instance = registryDefinition?.id === connectorId ? await installConnectorDefinition(config, registryDefinition, input) : await installConnector(config, connectorId, input);
632
- const saved = await service.saveConfig(config);
633
- if (!saved.saved) return c.json({
634
- ok: false,
635
- error: saved.error
636
- }, 500);
666
+ const instance = await persistConfigMutation({
667
+ config,
668
+ mutate: () => registryDefinition?.id === connectorId ? installConnectorDefinition(config, registryDefinition, input) : installConnector(config, connectorId, input),
669
+ save: () => service.saveConfig(config)
670
+ });
637
671
  return c.json({
638
672
  ok: true,
639
673
  payload: { instance }
@@ -642,7 +676,7 @@ function registerConnectorRoutes(authenticated, deps) {
642
676
  return c.json({
643
677
  ok: false,
644
678
  error: errorMessage(error)
645
- }, 400);
679
+ }, error instanceof ConfigPersistenceError ? 500 : 400);
646
680
  }
647
681
  });
648
682
  authenticated.post("/api/connectors/:id/test", async (c) => {
@@ -659,12 +693,11 @@ function registerConnectorRoutes(authenticated, deps) {
659
693
  }, 400);
660
694
  try {
661
695
  const result = await testConnectorInstance(config, instance.materialized.serverId);
662
- recordConnectorHealthUsage(config, instance.instanceId, result);
663
- const saved = await service.saveConfig(config);
664
- if (!saved.saved) return c.json({
665
- ok: false,
666
- error: saved.error
667
- }, 500);
696
+ await persistConfigMutation({
697
+ config,
698
+ mutate: () => recordConnectorHealthUsage(config, instance.instanceId, result),
699
+ save: () => service.saveConfig(config)
700
+ });
668
701
  return c.json({
669
702
  ok: true,
670
703
  payload: result
@@ -701,12 +734,11 @@ function registerConnectorRoutes(authenticated, deps) {
701
734
  const input = body && typeof body === "object" && !Array.isArray(body) ? body : {};
702
735
  const config = service.currentConfig;
703
736
  try {
704
- const instance = updateConnectorConfig(config, instanceId, input);
705
- const saved = await service.saveConfig(config);
706
- if (!saved.saved) return c.json({
707
- ok: false,
708
- error: saved.error
709
- }, 500);
737
+ const instance = await persistConfigMutation({
738
+ config,
739
+ mutate: () => updateConnectorConfig(config, instanceId, input),
740
+ save: () => service.saveConfig(config)
741
+ });
710
742
  return c.json({
711
743
  ok: true,
712
744
  payload: { instance }
@@ -715,19 +747,18 @@ function registerConnectorRoutes(authenticated, deps) {
715
747
  return c.json({
716
748
  ok: false,
717
749
  error: errorMessage(error)
718
- }, 400);
750
+ }, error instanceof ConfigPersistenceError ? 500 : 400);
719
751
  }
720
752
  });
721
753
  authenticated.post("/api/connectors/:id/enable", strictRateLimitMiddleware, async (c) => {
722
754
  const instanceId = c.req.param("id");
723
755
  const config = service.currentConfig;
724
756
  try {
725
- const instance = setConnectorEnabled(config, instanceId, true);
726
- const saved = await service.saveConfig(config);
727
- if (!saved.saved) return c.json({
728
- ok: false,
729
- error: saved.error
730
- }, 500);
757
+ const instance = await persistConfigMutation({
758
+ config,
759
+ mutate: () => setConnectorEnabled(config, instanceId, true),
760
+ save: () => service.saveConfig(config)
761
+ });
731
762
  return c.json({
732
763
  ok: true,
733
764
  payload: { instance }
@@ -736,19 +767,18 @@ function registerConnectorRoutes(authenticated, deps) {
736
767
  return c.json({
737
768
  ok: false,
738
769
  error: errorMessage(error)
739
- }, 400);
770
+ }, error instanceof ConfigPersistenceError ? 500 : 400);
740
771
  }
741
772
  });
742
773
  authenticated.post("/api/connectors/:id/disable", strictRateLimitMiddleware, async (c) => {
743
774
  const instanceId = c.req.param("id");
744
775
  const config = service.currentConfig;
745
776
  try {
746
- const instance = setConnectorEnabled(config, instanceId, false);
747
- const saved = await service.saveConfig(config);
748
- if (!saved.saved) return c.json({
749
- ok: false,
750
- error: saved.error
751
- }, 500);
777
+ const instance = await persistConfigMutation({
778
+ config,
779
+ mutate: () => setConnectorEnabled(config, instanceId, false),
780
+ save: () => service.saveConfig(config)
781
+ });
752
782
  return c.json({
753
783
  ok: true,
754
784
  payload: { instance }
@@ -757,19 +787,23 @@ function registerConnectorRoutes(authenticated, deps) {
757
787
  return c.json({
758
788
  ok: false,
759
789
  error: errorMessage(error)
760
- }, 400);
790
+ }, error instanceof ConfigPersistenceError ? 500 : 400);
761
791
  }
762
792
  });
763
793
  authenticated.delete("/api/connectors/:id", strictRateLimitMiddleware, async (c) => {
764
794
  const instanceId = c.req.param("id");
765
795
  const config = service.currentConfig;
766
796
  try {
767
- const instance = uninstallConnector(config, instanceId);
768
- const saved = await service.saveConfig(config);
769
- if (!saved.saved) return c.json({
770
- ok: false,
771
- error: saved.error
772
- }, 500);
797
+ const definition = getInstalledConnectorDefinition(config, instanceId);
798
+ const installed = getConnectorInstance(config, instanceId);
799
+ const serverId = installed?.materialized.type === "mcp" ? installed.materialized.serverId : void 0;
800
+ const rawServer = serverId ? config.mcp?.servers?.[serverId] : void 0;
801
+ if (definition?.auth.mode === "oauth" && definition.runtime.type === "mcp" && rawServer) await getMcpOAuthManager().disconnect(serverId, rawServer);
802
+ const instance = await persistConfigMutation({
803
+ config,
804
+ mutate: () => uninstallConnector(config, instanceId),
805
+ save: () => service.saveConfig(config)
806
+ });
773
807
  return c.json({
774
808
  ok: true,
775
809
  payload: { instance }
@@ -778,7 +812,7 @@ function registerConnectorRoutes(authenticated, deps) {
778
812
  return c.json({
779
813
  ok: false,
780
814
  error: errorMessage(error)
781
- }, 400);
815
+ }, error instanceof ConfigPersistenceError ? 500 : 400);
782
816
  }
783
817
  });
784
818
  }