@xopcai/xopc 0.0.303 → 0.0.307

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 (431) hide show
  1. package/README.md +4 -4
  2. package/README.zh-CN.md +4 -4
  3. package/dist/browser-ext/dist/assets/{auth-B_9ZuGDx.js → auth-C3yV1y_l.js} +67 -22
  4. package/dist/browser-ext/dist/background.js +4 -4
  5. package/dist/browser-ext/dist/sidepanel.html +1 -1
  6. package/dist/browser-ext/dist/sidepanel.js +3 -3
  7. package/dist/browser-ext/manifest.json +1 -1
  8. package/dist/extensions/feishu/xopc.extension.json +0 -3
  9. package/dist/extensions/telegram/xopc.extension.json +1 -4
  10. package/dist/extensions/weixin/xopc.extension.json +0 -3
  11. package/dist/gateway/static/root/assets/{activity-store-DCi5rh4e.js → activity-store-wgSB2HYK.js} +1 -1
  12. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-Ch3DzUvP.js → agent-avatar-dicebear-CZeQo09T.js} +1 -1
  13. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-BPsRb9Ck.js +1 -0
  14. package/dist/gateway/static/root/assets/{agents-DXHD-ST3.js → agents-BlrHMbRx.js} +1 -1
  15. package/dist/gateway/static/root/assets/{api-CAV9PN9i.js → api-BKHmTb0w.js} +1 -1
  16. package/dist/gateway/static/root/assets/api-DFOlahZv.js +1 -0
  17. package/dist/gateway/static/root/assets/app-management-settings-panel-Bzw4fQP8.js +1 -0
  18. package/dist/gateway/static/root/assets/appearance-settings-8GZpUXva.js +1 -0
  19. package/dist/gateway/static/root/assets/apps-page-BkQQtIxH.js +1 -0
  20. package/dist/gateway/static/root/assets/{archive-plugin-BKGzaVvM.js → archive-plugin-CQ2NaoHb.js} +1 -1
  21. package/dist/gateway/static/root/assets/{attachment-load-8bARdLnp.js → attachment-load-BFi1H7yJ.js} +1 -1
  22. package/dist/gateway/static/root/assets/{automations-page-BAEenyzx.js → automations-page-CDBXcii_.js} +1 -1
  23. package/dist/gateway/static/root/assets/automations-workspace-CUpiTTiY.js +6 -0
  24. package/dist/gateway/static/root/assets/{binary-plugins-Cv3GS9Eo.js → binary-plugins-D07eWmOx.js} +1 -1
  25. package/dist/gateway/static/root/assets/{block-editor-D4ZIVQbk.css → block-editor-BdOTO0Yo.css} +1 -1
  26. package/dist/gateway/static/root/assets/{block-editor-DUeb92LG.js → block-editor-CtVnjyYU.js} +3 -3
  27. package/dist/gateway/static/root/assets/{browser-automation-inputs-BGT0xoTv.js → browser-automation-inputs-BzkJog8e.js} +1 -1
  28. package/dist/gateway/static/root/assets/{browser-automations-page-D1O22WIf.js → browser-automations-page-DyrSbDdG.js} +2 -2
  29. package/dist/gateway/static/root/assets/browser-settings-page-CqTxLpil.js +3 -0
  30. package/dist/gateway/static/root/assets/button-CS04eWY9.js +1 -0
  31. package/dist/gateway/static/root/assets/capabilities-settings-panel-BZ_-pnS6.js +8 -0
  32. package/dist/gateway/static/root/assets/channels-settings-DAD9qE3J.js +1 -0
  33. package/dist/gateway/static/root/assets/{channels-status-swr-C_icwbWj.js → channels-status-swr-B2JwuTjG.js} +1 -1
  34. package/dist/gateway/static/root/assets/{chat-terminal-dock-D-JYPVYl.js → chat-terminal-dock-B62SZdAo.js} +2 -2
  35. package/dist/gateway/static/root/assets/{computer-settings-page-Bcfp948A.js → computer-settings-page-ClSresNq.js} +1 -1
  36. package/dist/gateway/static/root/assets/connector-service-page-CPqVmNvx.js +1 -0
  37. package/dist/gateway/static/root/assets/connectors-page-BUQyg3CW.js +2 -0
  38. package/dist/gateway/static/root/assets/cron-expression-CTMi_tql.js +2 -0
  39. package/dist/gateway/static/root/assets/date-picker-B71AJK50.js +1 -0
  40. package/dist/gateway/static/root/assets/{dependency-picker-UtoUm57Q.js → dependency-picker-DlyGK-kA.js} +1 -1
  41. package/dist/gateway/static/root/assets/{desktop-pet-Bryx7gRM.js → desktop-pet-DGkbTE8_.js} +1 -1
  42. package/dist/gateway/static/root/assets/desktop-pet-settings-BY8r9j66.js +1 -0
  43. package/dist/gateway/static/root/assets/device-pairing-wizard-DzRrgd59.js +1 -0
  44. package/dist/gateway/static/root/assets/{extension-debug-page-DQlFTVBx.js → extension-debug-page-L8Mm1n3A.js} +1 -1
  45. package/dist/gateway/static/root/assets/{extension-page-BSsqRDXh.js → extension-page-CFc4vSNU.js} +1 -1
  46. package/dist/gateway/static/root/assets/{extension-settings-page-DbVZv9ve.js → extension-settings-page-B5zWyHr3.js} +1 -1
  47. package/dist/gateway/static/root/assets/{gateway-config-swr-D5AM8cyQ.js → gateway-config-swr-B6wHa6ZI.js} +1 -1
  48. package/dist/gateway/static/root/assets/gateway-realtime-B53R0CA4.js +1 -0
  49. package/dist/gateway/static/root/assets/gateway-realtime-store-BLDgrJ30.js +1 -0
  50. package/dist/gateway/static/root/assets/gateway-settings-D7qmTH4R.js +1 -0
  51. package/dist/gateway/static/root/assets/{gateway-startup-retry-CSJWdnFs.js → gateway-startup-retry-DRzGnEV-.js} +1 -1
  52. package/dist/gateway/static/root/assets/{heartbeat-settings-Cxowc29b.js → heartbeat-settings-Glsl3X5b.js} +1 -1
  53. package/dist/gateway/static/root/assets/home-page-s9hDQ8Hc.js +1 -0
  54. package/dist/gateway/static/root/assets/{image-generation-api-BNh604hw.js → image-generation-api-Ck_pyDom.js} +1 -1
  55. package/dist/gateway/static/root/assets/imports-page-ByBX7ome.js +1 -0
  56. package/dist/gateway/static/root/assets/index-RBCkv8a_.js +79 -0
  57. package/dist/gateway/static/root/assets/index-cFU4S35z.css +1 -0
  58. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-C45RlO8a.js +1 -0
  59. package/dist/gateway/static/root/assets/local-app-workbench-page-DP0x2jpR.js +2 -0
  60. package/dist/gateway/static/root/assets/{local-apps-page-CXPaPDGm.js → local-apps-page-C_AQc2bI.js} +1 -1
  61. package/dist/gateway/static/root/assets/{locale-store-DLK05Y1a.js → locale-store-msTfRK8P.js} +1 -1
  62. package/dist/gateway/static/root/assets/logs-page-DvM8Pyok.js +2 -0
  63. package/dist/gateway/static/root/assets/management-settings-D1uwSutV.js +1 -0
  64. package/dist/gateway/static/root/assets/{markdown-view-B8maDRWh.js → markdown-view-BInabSKf.js} +2 -2
  65. package/dist/gateway/static/root/assets/{media-plugins-tSJ0CvcX.js → media-plugins-C4mhf13f.js} +1 -1
  66. package/dist/gateway/static/root/assets/messages-F74LVAiU.js +3 -0
  67. package/dist/gateway/static/root/assets/note-detail-panel-D35sErp2.js +5 -0
  68. package/dist/gateway/static/root/assets/notes-page-8jCDklDn.js +8 -0
  69. package/dist/gateway/static/root/assets/{page-tabs-CQx6H-GS.js → page-tabs-1go_BtX1.js} +1 -1
  70. package/dist/gateway/static/root/assets/{popover-select-DldSX8GX.js → popover-select-9i-ZtHXL.js} +1 -1
  71. package/dist/gateway/static/root/assets/{preview-open-alternatives-A3-bVtdy.js → preview-open-alternatives-DmoSC0j1.js} +1 -1
  72. package/dist/gateway/static/root/assets/{proactive-page-D46cR3sf.js → proactive-page-xAjKTIID.js} +1 -1
  73. package/dist/gateway/static/root/assets/{product-open-page-CujZXOea.js → product-open-page-gmi5LLwM.js} +1 -1
  74. package/dist/gateway/static/root/assets/project-detail-page-BUMQHy_N.js +1 -0
  75. package/dist/gateway/static/root/assets/projects-page-DT-Mt7XR.js +1 -0
  76. package/dist/gateway/static/root/assets/{registry-api-BMFL4vis.js → registry-api-BSWtko7U.js} +1 -1
  77. package/dist/gateway/static/root/assets/remote-access-hub-Clz3byir.js +1 -0
  78. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-CR0qvq9C.js → runtime-tools-settings-panel-ClkOoxDl.js} +2 -2
  79. package/dist/gateway/static/root/assets/{schema-form-BUD9lLEE.js → schema-form-BuEmLiaU.js} +1 -1
  80. package/dist/gateway/static/root/assets/sessions-page-tQRwktKm.js +1 -0
  81. package/dist/gateway/static/root/assets/settings-advanced-gate-DqWg9XS5.js +1 -0
  82. package/dist/gateway/static/root/assets/{settings-form-section-BZPCUH6a.js → settings-form-section-Dor39QON.js} +1 -1
  83. package/dist/gateway/static/root/assets/{settings-page-XoHmqIdm.js → settings-page-Xj-yvIc8.js} +1 -1
  84. package/dist/gateway/static/root/assets/setup-status-panel-BB_sMB7P.js +1 -0
  85. package/dist/gateway/static/root/assets/share-preview-page-BFWZoXdm.js +2 -0
  86. package/dist/gateway/static/root/assets/shares-settings-oDALm4b6.js +1 -0
  87. package/dist/gateway/static/root/assets/skill-reload-api-DmwelnfK.js +1 -0
  88. package/dist/gateway/static/root/assets/skills-page-BE9JXz4U.js +2 -0
  89. package/dist/gateway/static/root/assets/{skills-page.utils-CH-quGxZ.js → skills-page.utils-Ii8qeXhs.js} +1 -1
  90. package/dist/gateway/static/root/assets/{system-settings-panel-CGC7eBso.js → system-settings-panel-Di6OSO-0.js} +1 -1
  91. package/dist/gateway/static/root/assets/task-detail-page-D1AWszc7.js +1 -0
  92. package/dist/gateway/static/root/assets/theme-store-1SZ-HFHX.js +1 -0
  93. package/dist/gateway/static/root/assets/tunnel-api-DDOlOYlj.js +1 -0
  94. package/dist/gateway/static/root/assets/{use-autosave-BydB6x2K.js → use-autosave-CQ8uWNnB.js} +1 -1
  95. package/dist/gateway/static/root/assets/user-model-page-C00i4ea0.js +2 -0
  96. package/dist/gateway/static/root/assets/{voice-api-key-field-CPUDBcag.js → voice-api-key-field-COTzshjL.js} +1 -1
  97. package/dist/gateway/static/root/assets/{voice-config-api-bZqN8-UF.js → voice-config-api-DgJML_uM.js} +1 -1
  98. package/dist/gateway/static/root/assets/{work-discovery-overlay-D_FmJbGH.js → work-discovery-overlay-_URrXbi4.js} +1 -1
  99. package/dist/gateway/static/root/assets/workflow-run-setup-panel-CALs-1nd.js +3 -0
  100. package/dist/gateway/static/root/assets/workflows-page-BUiBjz6m.js +6 -0
  101. package/dist/gateway/static/root/channel-icons/feishu.svg +6 -12
  102. package/dist/gateway/static/root/connector-icons/SOURCES.md +12 -0
  103. package/dist/gateway/static/root/connector-icons/dingtalk-mark.svg +1 -0
  104. package/dist/gateway/static/root/connector-icons/tencent-meeting-mark.svg +37 -0
  105. package/dist/gateway/static/root/connector-icons/wps-calendar.svg +14 -0
  106. package/dist/gateway/static/root/connector-icons/wps-docs.svg +14 -0
  107. package/dist/gateway/static/root/connector-icons/wps-mail.svg +7 -0
  108. package/dist/gateway/static/root/index.html +14 -12
  109. package/dist/package.js +1 -1
  110. package/dist/packages/gateway-contract/src/device-pairing.js +100 -7
  111. package/dist/packages/gateway-contract/src/gateway-scopes.js +53 -0
  112. package/dist/packages/gateway-contract/src/index.js +2 -0
  113. package/dist/packages/realtime-client/src/index.js +14 -2
  114. package/dist/packages/realtime-protocol/src/index.js +18 -14
  115. package/dist/src/agent/agent-instance-gateway.d.ts +2 -0
  116. package/dist/src/agent/agent-manager.d.ts +2 -0
  117. package/dist/src/agent/agent-manager.js +40 -12
  118. package/dist/src/agent/agent-scope.d.ts +4 -1
  119. package/dist/src/agent/agent-scope.js +19 -3
  120. package/dist/src/agent/commands/command-isolation.js +11 -9
  121. package/dist/src/agent/commands/command-registry.js +18 -33
  122. package/dist/src/agent/context/audit.js +12 -2
  123. package/dist/src/agent/context/coordinator.d.ts +13 -3
  124. package/dist/src/agent/context/coordinator.js +27 -11
  125. package/dist/src/agent/context/execution-context.js +42 -22
  126. package/dist/src/agent/context/execution-context.types.d.ts +4 -2
  127. package/dist/src/agent/context/execution-scope.d.ts +2 -2
  128. package/dist/src/agent/context/execution-scope.js +1 -1
  129. package/dist/src/agent/context/project-context.d.ts +2 -2
  130. package/dist/src/agent/context/project-context.js +3 -3
  131. package/dist/src/agent/embedded/run-for-session.d.ts +1 -0
  132. package/dist/src/agent/embedded/run-for-session.js +7 -1
  133. package/dist/src/agent/external-tools/composio-provider.js +83 -20
  134. package/dist/src/agent/external-tools/gateway-tools.js +2 -1
  135. package/dist/src/agent/inbound/attachment-pipeline.d.ts +2 -0
  136. package/dist/src/agent/inbound/attachment-pipeline.js +3 -3
  137. package/dist/src/agent/inbound/inbound-loop.js +1 -0
  138. package/dist/src/agent/inbound/turn-dispatcher.js +3 -3
  139. package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
  140. package/dist/src/agent/mcp/mcp-stdio-transport.js +5 -2
  141. package/dist/src/agent/mcp/oauth/mcp-oauth-manager.js +1 -1
  142. package/dist/src/agent/memory/compaction-promotion.js +7 -2
  143. package/dist/src/agent/memory/create-memory-manager.js +1 -0
  144. package/dist/src/agent/memory/manager.d.ts +6 -0
  145. package/dist/src/agent/memory/manager.js +74 -39
  146. package/dist/src/agent/memory/runtime.d.ts +3 -3
  147. package/dist/src/agent/memory/runtime.js +11 -4
  148. package/dist/src/agent/orchestration/agent-orchestrator.js +4 -1
  149. package/dist/src/agent/prompt/cache-boundary.d.ts +2 -0
  150. package/dist/src/agent/prompt/cache-boundary.js +10 -1
  151. package/dist/src/agent/service/build-direct-message-content.d.ts +1 -0
  152. package/dist/src/agent/service/build-direct-message-content.js +2 -1
  153. package/dist/src/agent/service/direct-turn-helpers.js +3 -2
  154. package/dist/src/agent/service/process-direct-streaming.d.ts +3 -1
  155. package/dist/src/agent/service/process-direct-streaming.js +3 -2
  156. package/dist/src/agent/service/webchat-tts.d.ts +0 -4
  157. package/dist/src/agent/service/webchat-tts.js +20 -19
  158. package/dist/src/agent/tools/factory.js +3 -3
  159. package/dist/src/agent/tools/knowledge-memory-tool.d.ts +2 -2
  160. package/dist/src/agent/tools/knowledge-memory-tool.js +7 -7
  161. package/dist/src/browser/native-messaging-host.js +2 -2
  162. package/dist/src/channels/attachments/voice-stt-webchat.d.ts +3 -0
  163. package/dist/src/channels/attachments/voice-stt-webchat.js +22 -9
  164. package/dist/src/cli/commands/agent.js +2 -0
  165. package/dist/src/cli/commands/config.js +8 -9
  166. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  167. package/dist/src/cli/commands/extension-marketplace.js +69 -44
  168. package/dist/src/cli/commands/extension-pack.js +0 -2
  169. package/dist/src/cli/commands/extension.js +4 -25
  170. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  171. package/dist/src/cli/commands/onboard/gateway.js +2 -1
  172. package/dist/src/cli/utils/init-workspace-core.js +5 -2
  173. package/dist/src/config/index.js +2 -2
  174. package/dist/src/config/loader.d.ts +1 -0
  175. package/dist/src/config/loader.js +14 -1
  176. package/dist/src/config/schema.d.ts +22 -3
  177. package/dist/src/config/schema.js +13 -3
  178. package/dist/src/connectors/account-access.d.ts +4 -0
  179. package/dist/src/connectors/account-access.js +23 -0
  180. package/dist/src/connectors/approval-resume.d.ts +4 -0
  181. package/dist/src/connectors/approval-resume.js +23 -0
  182. package/dist/src/connectors/auth-provider-registry.d.ts +1 -0
  183. package/dist/src/connectors/auth-provider-registry.js +2 -1
  184. package/dist/src/connectors/authorization-attempts.d.ts +21 -0
  185. package/dist/src/connectors/authorization-attempts.js +33 -0
  186. package/dist/src/connectors/builtin-catalog.js +1 -3
  187. package/dist/src/connectors/catalog.js +2 -1
  188. package/dist/src/connectors/china-catalog.d.ts +2 -0
  189. package/dist/src/connectors/china-catalog.js +430 -0
  190. package/dist/src/connectors/composio-backends.d.ts +26 -0
  191. package/dist/src/connectors/composio-backends.js +65 -0
  192. package/dist/src/connectors/composio-catalog.js +2 -1
  193. package/dist/src/connectors/composio-managed-client.js +3 -1
  194. package/dist/src/connectors/composio-managed-events.js +5 -2
  195. package/dist/src/connectors/composio-session-types.d.ts +2 -0
  196. package/dist/src/connectors/composio-sessions.d.ts +11 -2
  197. package/dist/src/connectors/composio-sessions.js +137 -35
  198. package/dist/src/connectors/composio-triggers.js +4 -2
  199. package/dist/src/connectors/composio.d.ts +11 -8
  200. package/dist/src/connectors/composio.js +68 -84
  201. package/dist/src/connectors/connected-source-ingestion.js +4 -3
  202. package/dist/src/connectors/connection-recovery-service.js +25 -13
  203. package/dist/src/connectors/connector-identity.d.ts +2 -0
  204. package/dist/src/connectors/connector-identity.js +18 -5
  205. package/dist/src/connectors/content-enrichment.js +1 -1
  206. package/dist/src/connectors/instances.js +1 -7
  207. package/dist/src/connectors/learning-coordinator.js +4 -3
  208. package/dist/src/connectors/materialize.js +14 -1
  209. package/dist/src/connectors/policy.d.ts +1 -1
  210. package/dist/src/connectors/policy.js +1 -1
  211. package/dist/src/connectors/principal.js +24 -3
  212. package/dist/src/connectors/providers.d.ts +1 -0
  213. package/dist/src/connectors/providers.js +14 -2
  214. package/dist/src/connectors/runtime-adapter-registry.js +4 -9
  215. package/dist/src/connectors/secret-store.d.ts +4 -1
  216. package/dist/src/connectors/secret-store.js +7 -3
  217. package/dist/src/connectors/source-change-publisher.js +4 -2
  218. package/dist/src/connectors/types.d.ts +16 -11
  219. package/dist/src/connectors/workflow-preflight.d.ts +2 -1
  220. package/dist/src/connectors/workflow-preflight.js +20 -3
  221. package/dist/src/execution-environments/local-worktree-manager.js +17 -15
  222. package/dist/src/execution-environments/store.js +4 -2
  223. package/dist/src/execution-environments/types.d.ts +3 -0
  224. package/dist/src/execution-environments/types.js +2 -1
  225. package/dist/src/execution-environments/worktree-safety.d.ts +8 -0
  226. package/dist/src/execution-environments/worktree-safety.js +43 -0
  227. package/dist/src/extensions/activation-planner.d.ts +1 -1
  228. package/dist/src/extensions/activation-planner.js +1 -1
  229. package/dist/src/extensions/api-version.d.ts +4 -0
  230. package/dist/src/extensions/api-version.js +15 -0
  231. package/dist/src/extensions/api.d.ts +3 -9
  232. package/dist/src/extensions/api.js +26 -32
  233. package/dist/src/extensions/config-validation.d.ts +8 -0
  234. package/dist/src/extensions/config-validation.js +25 -0
  235. package/dist/src/extensions/extension-registry-impl.d.ts +20 -9
  236. package/dist/src/extensions/extension-registry-impl.js +79 -11
  237. package/dist/src/extensions/hooks.d.ts +1 -1
  238. package/dist/src/extensions/index.d.ts +2 -1
  239. package/dist/src/extensions/install-transaction.d.ts +2 -0
  240. package/dist/src/extensions/install-transaction.js +32 -21
  241. package/dist/src/extensions/install.js +18 -1
  242. package/dist/src/extensions/loader.d.ts +5 -5
  243. package/dist/src/extensions/loader.js +109 -47
  244. package/dist/src/extensions/lockfile.d.ts +3 -5
  245. package/dist/src/extensions/lockfile.js +41 -14
  246. package/dist/src/extensions/normalize-manifest.js +6 -60
  247. package/dist/src/extensions/sdk/index.d.ts +3 -2
  248. package/dist/src/extensions/sdk/index.js +2 -2
  249. package/dist/src/extensions/sdk/testing.js +0 -4
  250. package/dist/src/extensions/security.js +5 -7
  251. package/dist/src/extensions/types/core.d.ts +0 -5
  252. package/dist/src/extensions/types/index.d.ts +1 -1
  253. package/dist/src/extensions/types/manifest.d.ts +1 -25
  254. package/dist/src/extensions/types/providers.d.ts +1 -1
  255. package/dist/src/extensions/types/registration.d.ts +0 -12
  256. package/dist/src/extensions/update.js +71 -30
  257. package/dist/src/gateway/heartbeat/service.js +2 -2
  258. package/dist/src/gateway/hono/lib/config-payload.d.ts +3 -1
  259. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +47 -10
  260. package/dist/src/gateway/hono/routes/connectors.js +208 -17
  261. package/dist/src/gateway/hono/routes/context-sources.js +1 -1
  262. package/dist/src/gateway/hono/routes/devices.js +10 -7
  263. package/dist/src/gateway/hono/routes/endpoint-compatibility.js +6 -0
  264. package/dist/src/gateway/hono/routes/extension-gateway.js +0 -33
  265. package/dist/src/gateway/hono/routes/home.js +4 -1
  266. package/dist/src/gateway/hono/routes/lazy-bundles.js +0 -1
  267. package/dist/src/gateway/hono/routes/mcp.js +1 -1
  268. package/dist/src/gateway/hono/routes/realtime.js +30 -8
  269. package/dist/src/gateway/hono/routes/user-model.js +25 -6
  270. package/dist/src/gateway/index.js +4 -1
  271. package/dist/src/gateway/lock.d.ts +2 -0
  272. package/dist/src/gateway/lock.js +31 -14
  273. package/dist/src/gateway/run-loop.js +2 -1
  274. package/dist/src/gateway/security/gateway-scopes.d.ts +2 -5
  275. package/dist/src/gateway/security/gateway-scopes.js +3 -45
  276. package/dist/src/gateway/security/index.js +2 -1
  277. package/dist/src/gateway/service.js +11 -7
  278. package/dist/src/heartbeat/index.js +1 -1
  279. package/dist/src/imports/importService.d.ts +1 -1
  280. package/dist/src/imports/inventory.js +16 -2
  281. package/dist/src/imports/productImport.js +5 -5
  282. package/dist/src/imports/types.d.ts +3 -3
  283. package/dist/src/infra/exec.d.ts +2 -2
  284. package/dist/src/infra/exec.js +32 -27
  285. package/dist/src/infra/run-command.js +15 -50
  286. package/dist/src/infra/update-restart.js +1 -1
  287. package/dist/src/knowledge/connected-knowledge-pipeline.js +13 -3
  288. package/dist/src/knowledge-memory/domain.d.ts +17 -1
  289. package/dist/src/knowledge-memory/index.js +2 -2
  290. package/dist/src/knowledge-memory/repository.d.ts +26 -4
  291. package/dist/src/knowledge-memory/repository.js +171 -36
  292. package/dist/src/mcp/channel-bridge.js +7 -3
  293. package/dist/src/media-understanding/registry.js +6 -1
  294. package/dist/src/migrations/knowledge-memory-read-policy-config.d.ts +2 -0
  295. package/dist/src/migrations/knowledge-memory-read-policy-config.js +48 -0
  296. package/dist/src/migrations/runner.js +2 -1
  297. package/dist/src/proactive/follow-ups.js +2 -1
  298. package/dist/src/process/bounded-output.d.ts +10 -0
  299. package/dist/src/process/bounded-output.js +41 -0
  300. package/dist/src/process/kill-tree.d.ts +6 -17
  301. package/dist/src/process/kill-tree.js +43 -75
  302. package/dist/src/process/process-spec.d.ts +39 -0
  303. package/dist/src/process/process-spec.js +13 -0
  304. package/dist/src/process/run-process.d.ts +4 -0
  305. package/dist/src/process/run-process.js +97 -0
  306. package/dist/src/providers/plugin-registry.d.ts +1 -1
  307. package/dist/src/providers/plugin-registry.js +6 -0
  308. package/dist/src/realtime/runtime.js +3 -1
  309. package/dist/src/session/store.js +1 -1
  310. package/dist/src/storage/sqlite/connection-wait-repository.d.ts +3 -0
  311. package/dist/src/storage/sqlite/connection-wait-repository.js +63 -2
  312. package/dist/src/storage/sqlite/connector-account-repository.d.ts +6 -0
  313. package/dist/src/storage/sqlite/connector-account-repository.js +35 -7
  314. package/dist/src/storage/sqlite/connector-repository.js +15 -10
  315. package/dist/src/storage/sqlite/connector-sync-policy-repository.js +1 -1
  316. package/dist/src/storage/sqlite/device-pairing-approval.js +1 -1
  317. package/dist/src/storage/sqlite/index.d.ts +1 -1
  318. package/dist/src/storage/sqlite/index.js +6 -4
  319. package/dist/src/storage/sqlite/migrations/180_execution_environment_ownership.sql +7 -0
  320. package/dist/src/storage/sqlite/migrations/181_knowledge_item_status_events.sql +12 -0
  321. package/dist/src/storage/sqlite/migrations/182_connector_account_policies.sql +92 -0
  322. package/dist/src/storage/sqlite/migrations/183_connector_backend_consistency.sql +20 -0
  323. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  324. package/dist/src/storage/sqlite/migrations/runner.js +7 -7
  325. package/dist/src/storage/sqlite/schema.js +1 -1
  326. package/dist/src/storage/sqlite/schema.sql +13 -0
  327. package/dist/src/storage/sqlite/transcript-repository.d.ts +4 -0
  328. package/dist/src/storage/sqlite/transcript-repository.js +36 -1
  329. package/dist/src/tasks/home-query-service.js +3 -3
  330. package/dist/src/tui/backends/embedded-backend.d.ts +24 -8
  331. package/dist/src/tui/backends/embedded-backend.js +114 -10
  332. package/dist/src/tui/backends/gateway-realtime-backend.d.ts +18 -0
  333. package/dist/src/tui/backends/gateway-realtime-backend.js +31 -4
  334. package/dist/src/tui/components/assistant-message.d.ts +4 -1
  335. package/dist/src/tui/components/assistant-message.js +10 -2
  336. package/dist/src/tui/components/cell-render-mode.d.ts +4 -0
  337. package/dist/src/tui/components/cell-render-mode.js +1 -0
  338. package/dist/src/tui/components/chat-log.d.ts +17 -4
  339. package/dist/src/tui/components/chat-log.js +68 -50
  340. package/dist/src/tui/components/custom-editor.d.ts +2 -2
  341. package/dist/src/tui/components/custom-editor.js +5 -1
  342. package/dist/src/tui/components/pending-input-preview.d.ts +9 -0
  343. package/dist/src/tui/components/pending-input-preview.js +33 -0
  344. package/dist/src/tui/components/semantic-cell.d.ts +17 -0
  345. package/dist/src/tui/components/semantic-cell.js +29 -0
  346. package/dist/src/tui/components/tool-execution.d.ts +5 -1
  347. package/dist/src/tui/components/tool-execution.js +33 -10
  348. package/dist/src/tui/components/transcript-overlay.d.ts +29 -0
  349. package/dist/src/tui/components/transcript-overlay.js +114 -0
  350. package/dist/src/tui/components/tui-bottom-bar.js +3 -1
  351. package/dist/src/tui/components/user-message.d.ts +5 -1
  352. package/dist/src/tui/components/user-message.js +12 -1
  353. package/dist/src/tui/extension-host/load-extensions.d.ts +1 -1
  354. package/dist/src/tui/extension-host/runtime-context.js +2 -1
  355. package/dist/src/tui/extension-host/runtime.d.ts +1 -1
  356. package/dist/src/tui/format-tui-hotkeys.js +8 -1
  357. package/dist/src/tui/tui-agent-events.js +31 -0
  358. package/dist/src/tui/tui-backend.d.ts +23 -11
  359. package/dist/src/tui/tui-backend.js +1 -9
  360. package/dist/src/tui/tui-chat-input-state.d.ts +25 -0
  361. package/dist/src/tui/tui-chat-input-state.js +36 -0
  362. package/dist/src/tui/tui-command-formatters.js +2 -1
  363. package/dist/src/tui/tui-commands.js +1 -1
  364. package/dist/src/tui/tui-startup-resources.js +1 -1
  365. package/dist/src/tui/tui-types.d.ts +2 -1
  366. package/dist/src/tui/tui-types.js +2 -1
  367. package/dist/src/tui/tui.js +122 -30
  368. package/dist/src/tui/xopc-tui-keybindings.d.ts +23 -3
  369. package/dist/src/tui/xopc-tui-keybindings.js +22 -2
  370. package/dist/src/user-context/access-policy.d.ts +2 -2
  371. package/dist/src/user-context/access-policy.js +10 -2
  372. package/dist/src/user-context/config.d.ts +23 -6
  373. package/dist/src/user-context/config.js +54 -7
  374. package/dist/src/voice/platform-streams.js +11 -1
  375. package/dist/src/voice/realtime/omniEngine.js +13 -1
  376. package/dist/src/voice/realtime/runtime.js +2 -1
  377. package/dist/src/voice/tts/audio.js +1 -1
  378. package/dist/src/voice/tts/speech-registry.js +6 -1
  379. package/dist/src/workflows/domain/definition.d.ts +1 -0
  380. package/dist/src/workflows/domain/validation.js +1 -1
  381. package/dist/src/workflows/service/workflow-run-service.js +14 -0
  382. package/dist/src/workflows/service/workflow-session-bridge.d.ts +1 -0
  383. package/dist/src/workflows/service/workflow-session-bridge.js +1 -0
  384. package/package.json +5 -3
  385. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-4oGrNj3m.js +0 -1
  386. package/dist/gateway/static/root/assets/api-fPapljyb.js +0 -1
  387. package/dist/gateway/static/root/assets/app-management-settings-panel-CdXnNtTg.js +0 -1
  388. package/dist/gateway/static/root/assets/appearance-settings-izNAyDhW.js +0 -1
  389. package/dist/gateway/static/root/assets/apps-page-BQb3RCga.js +0 -1
  390. package/dist/gateway/static/root/assets/automations-workspace-5vTl4x0h.js +0 -6
  391. package/dist/gateway/static/root/assets/browser-settings-page-CH9prS-f.js +0 -3
  392. package/dist/gateway/static/root/assets/button-CGlRPNzi.js +0 -1
  393. package/dist/gateway/static/root/assets/capabilities-settings-panel-DMURlZbj.js +0 -8
  394. package/dist/gateway/static/root/assets/channels-settings-CFBS3Yqy.js +0 -1
  395. package/dist/gateway/static/root/assets/connectors-page-DI1c3BMz.js +0 -2
  396. package/dist/gateway/static/root/assets/cron-expression-BJMBFKCh.js +0 -2
  397. package/dist/gateway/static/root/assets/date-picker-BFRIn5y9.js +0 -1
  398. package/dist/gateway/static/root/assets/desktop-pet-settings-DFsyEJUr.js +0 -1
  399. package/dist/gateway/static/root/assets/device-pairing-wizard-C3TQVPRy.js +0 -1
  400. package/dist/gateway/static/root/assets/gateway-settings-DUqVsB3X.js +0 -1
  401. package/dist/gateway/static/root/assets/home-page-CLkumXdN.js +0 -1
  402. package/dist/gateway/static/root/assets/imports-page-DXNfRmk9.js +0 -1
  403. package/dist/gateway/static/root/assets/index-BLRIcVQa.css +0 -1
  404. package/dist/gateway/static/root/assets/index-gheM453N.js +0 -79
  405. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-5Hcec8Xf.js +0 -1
  406. package/dist/gateway/static/root/assets/local-app-workbench-page-BDg1-fcw.js +0 -2
  407. package/dist/gateway/static/root/assets/logs-page-BWZc5jwO.js +0 -2
  408. package/dist/gateway/static/root/assets/management-settings-COa3PhMs.js +0 -1
  409. package/dist/gateway/static/root/assets/messages-C9h8SImu.js +0 -3
  410. package/dist/gateway/static/root/assets/note-detail-panel-D_YGzNcR.js +0 -5
  411. package/dist/gateway/static/root/assets/notes-page-D1f2oI2-.js +0 -8
  412. package/dist/gateway/static/root/assets/project-detail-page-CRlD_Rwv.js +0 -1
  413. package/dist/gateway/static/root/assets/projects-page-mmX0SavY.js +0 -1
  414. package/dist/gateway/static/root/assets/remote-access-hub-Cqr3K6T5.js +0 -1
  415. package/dist/gateway/static/root/assets/sessions-page-CPkvbdJP.js +0 -1
  416. package/dist/gateway/static/root/assets/settings-advanced-gate-Cu0DAbeH.js +0 -1
  417. package/dist/gateway/static/root/assets/setup-status-panel-D8fQF1jZ.js +0 -1
  418. package/dist/gateway/static/root/assets/share-preview-page-BgHqwTuT.js +0 -2
  419. package/dist/gateway/static/root/assets/shares-settings-Id4vRHzI.js +0 -1
  420. package/dist/gateway/static/root/assets/skill-reload-api-BB2Fj_di.js +0 -1
  421. package/dist/gateway/static/root/assets/skills-page-BAwF4LpS.js +0 -2
  422. package/dist/gateway/static/root/assets/task-detail-page-BVjw812D.js +0 -1
  423. package/dist/gateway/static/root/assets/theme-store-KfFEGMlp.js +0 -1
  424. package/dist/gateway/static/root/assets/tunnel-api-Do98Xk05.js +0 -1
  425. package/dist/gateway/static/root/assets/user-model-page-Nv68a4ak.js +0 -2
  426. package/dist/gateway/static/root/assets/workflow-run-setup-panel-1lZ_btki.js +0 -3
  427. package/dist/gateway/static/root/assets/workflows-page-DFOhccm3.js +0 -6
  428. package/dist/src/extensions/when-context.d.ts +0 -6
  429. package/dist/src/extensions/when-context.js +0 -26
  430. package/dist/src/extensions/when-expression.d.ts +0 -11
  431. package/dist/src/extensions/when-expression.js +0 -213
@@ -1,20 +1,26 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
- import { connectionBinding, connectionBindings, init_connection_wait_repository, publishConnectionWait, requireSessionConnection } from "../../storage/sqlite/connection-wait-repository.js";
4
- import { consumeConnectorApproval, createConnectorApproval, getConnectorApproval, getConnectorInstallation, listConnectorActionMetadata, listConnectorConnections, listConnectorInstallations, upsertConnectorActionMetadata, upsertConnectorInstallation } from "../../storage/sqlite/connector-repository.js";
3
+ import { getSessionInputState, init_session_input_repository } from "../../storage/sqlite/session-input-repository.js";
4
+ import { getConnectorAccount } from "../../storage/sqlite/connector-account-repository.js";
5
+ import { consumeConnectorApproval, createConnectorApproval, getConnectorApproval, getConnectorConnection, getConnectorInstallation, listConnectorActionMetadata, listConnectorConnections, listConnectorInstallations, upsertConnectorActionMetadata, upsertConnectorInstallation } from "../../storage/sqlite/connector-repository.js";
6
+ import { bindObjectiveAccount, connectionBinding, connectionBindings, connectorObjectiveScope, init_connection_wait_repository, publishConnectionWait, requireSessionConnection } from "../../storage/sqlite/connection-wait-repository.js";
5
7
  import "../../storage/sqlite/index.js";
6
8
  import { connectorArgumentsHash, connectorArgumentsPreview } from "../../connectors/approval.js";
9
+ import { connectorIdentitySummary } from "../../connectors/connector-identity.js";
10
+ import { canAccessConnectorAccount, currentAccountConnections } from "../../connectors/account-access.js";
7
11
  import { ComposioSessionsAdapter } from "../../connectors/composio-sessions.js";
8
12
  import { getComposioToolkitScope, getConfiguredComposioAuthConfigs, isComposioActionAllowedByCatalog, scopeForComposioAction } from "../../connectors/composio.js";
9
13
  import { getConnectorDefinition } from "../../connectors/catalog.js";
14
+ import { listConnectorInstances } from "../../connectors/instances.js";
10
15
  import { isToolInputSchema } from "../../connectors/connection-capabilities.js";
11
16
  import { connectorPrincipalForSession } from "../../connectors/principal.js";
12
17
  import { ExternalToolSearchError } from "./search-error.js";
13
18
  import { externalToolRef, parseExternalToolRef } from "./refs.js";
14
19
  //#region src/agent/external-tools/composio-provider.ts
20
+ init_session_input_repository();
15
21
  init_connection_wait_repository();
16
22
  init_logger();
17
- const CONNECTION_ARGUMENT = "xopcConnectionId";
23
+ const CONNECTION_ARGUMENT = "xopcAccountId";
18
24
  const log = createLogger("ComposioToolProvider");
19
25
  function textResult(value) {
20
26
  return {
@@ -62,7 +68,7 @@ function syncLocalOwnerInstallations(config) {
62
68
  allowedAgentIds: existing?.allowedAgentIds ?? [],
63
69
  maxScope: existing?.maxScope ?? getComposioToolkitScope(config, toolkit),
64
70
  confirmationPolicy: existing?.confirmationPolicy ?? "writes",
65
- selectedConnectionIds: existing?.selectedConnectionIds ?? [],
71
+ selectedAccountIds: existing?.selectedAccountIds ?? null,
66
72
  createdAt: existing?.createdAt
67
73
  });
68
74
  }
@@ -98,6 +104,7 @@ function actionInputSchema(action) {
98
104
  if (!isToolInputSchema(action.inputSchema)) throw new Error(`Exact input contract is unavailable for ${action.actionId}`);
99
105
  const schema = action.inputSchema;
100
106
  const properties = schema.properties && typeof schema.properties === "object" && !Array.isArray(schema.properties) ? schema.properties : {};
107
+ if (Object.hasOwn(properties, CONNECTION_ARGUMENT)) throw new Error("The provider contract conflicts with the reserved account selector.");
101
108
  return {
102
109
  ...schema,
103
110
  type: "object",
@@ -105,7 +112,7 @@ function actionInputSchema(action) {
105
112
  ...properties,
106
113
  [CONNECTION_ARGUMENT]: {
107
114
  type: "string",
108
- description: "Optional local connection id when more than one account is connected."
115
+ description: "Stable local account ID. Required when this objective uses multiple accounts. Never guess an account."
109
116
  }
110
117
  }
111
118
  };
@@ -190,13 +197,22 @@ var ComposioToolProvider = class {
190
197
  const action = listConnectorActionMetadata(resolved.installation.connectorId).find((candidate) => candidate.actionId === resolved.actionId);
191
198
  if (!action || !isToolInputSchema(action.inputSchema) || !isComposioActionAllowedByCatalog(action.actionId)) return void 0;
192
199
  const summary = `Run ${action.actionId} in ${toolkit}.`;
200
+ const available = this.availableInstallations();
201
+ const accounts = currentAccountConnections(listConnectorConnections({
202
+ principalId: available.principalId,
203
+ connectorId: resolved.installation.connectorId
204
+ }).filter((connection) => canAccessConnectorAccount(connection, resolved.installation, available.agentId))).map((connection) => ({
205
+ accountId: connection.accountId,
206
+ label: getConnectorAccount(connection.accountId)?.label,
207
+ identity: connectorIdentitySummary(connection.identity)
208
+ }));
193
209
  return {
194
210
  toolRef,
195
211
  source: this.source,
196
212
  namespace: toolkit,
197
213
  title: action.actionId,
198
214
  summary,
199
- description: summary,
215
+ description: `${summary} Available accounts: ${JSON.stringify(accounts)}. Use xopcAccountId to select one; never guess when the user's intent is ambiguous.`,
200
216
  inputSchema: actionInputSchema(action)
201
217
  };
202
218
  }
@@ -220,19 +236,20 @@ var ComposioToolProvider = class {
220
236
  const refreshed = await this.adapter.refreshConnection(expired);
221
237
  fresh = fresh.map((item) => item.id === refreshed.id ? refreshed : item);
222
238
  }
223
- const connections = listConnectorConnections({
239
+ const connections = currentAccountConnections(listConnectorConnections({
224
240
  principalId: available.principalId,
225
241
  connectorId: resolved.installation.connectorId
226
- }).filter((connection) => connection.status === "active" && fresh.some((item) => item.id === connection.id) && (!resolved.installation.selectedConnectionIds.length || resolved.installation.selectedConnectionIds.includes(connection.id)));
227
- const requestedConnection = typeof executionArgs[CONNECTION_ARGUMENT] === "string" ? executionArgs[CONNECTION_ARGUMENT] : available.context ? connectionBinding(available.context.conversationId, resolved.installation.connectorId) : void 0;
242
+ }).filter((connection) => connection.status === "active" && fresh.some((item) => item.id === connection.id) && canAccessConnectorAccount(connection, resolved.installation, available.agentId)));
243
+ const boundConnection = available.context ? connectionBinding(available.context.conversationId, resolved.installation.connectorId) : void 0;
244
+ const requestedAccount = typeof executionArgs[CONNECTION_ARGUMENT] === "string" ? executionArgs[CONNECTION_ARGUMENT] : boundConnection ? getConnectorConnection(boundConnection)?.accountId : void 0;
228
245
  const bindings = available.context ? connectionBindings(available.context.conversationId).filter((need) => need.connectorId === resolved.installation.connectorId) : [];
229
- if (bindings.length > 1 && !requestedConnection) return textResult({
246
+ if (bindings.length > 1 && !requestedAccount) return textResult({
230
247
  status: "account_selection_required",
231
248
  accounts: bindings,
232
- instruction: "Choose the account for this operation using xopcConnectionId."
249
+ instruction: "Choose the account for this operation using xopcAccountId."
233
250
  });
234
- if (bindings.length && requestedConnection && !bindings.some((need) => need.connectionId === requestedConnection)) return textResult("This account was not selected for the current objective.");
235
- const connection = requestedConnection ? connections.find((candidate) => candidate.id === requestedConnection) : connections.length === 1 ? connections[0] : void 0;
251
+ if (bindings.length && requestedAccount && !bindings.some((need) => need.accountId === requestedAccount)) return textResult("This account was not selected for the current objective.");
252
+ const connection = requestedAccount ? connections.find((candidate) => candidate.accountId === requestedAccount) : connections.length === 1 ? connections[0] : void 0;
236
253
  const requestConnection = () => {
237
254
  if (!available.context) return textResult({ status: "connection_required" });
238
255
  const result = requireSessionConnection({
@@ -243,7 +260,7 @@ var ComposioToolProvider = class {
243
260
  needs: [{
244
261
  key: `${resolved.installation.connectorId}:default`,
245
262
  connectorId: resolved.installation.connectorId,
246
- connectionId: requestedConnection,
263
+ accountId: requestedAccount,
247
264
  label: getConnectorDefinition(resolved.installation.connectorId)?.displayName ?? toolkit,
248
265
  capabilities: [action.actionId]
249
266
  }]
@@ -252,13 +269,18 @@ var ComposioToolProvider = class {
252
269
  return textResult(result);
253
270
  };
254
271
  if (!connection) return requestConnection();
272
+ if (available.context && connection.accountId) bindObjectiveAccount(available.context.conversationId, resolved.installation.connectorId, connection.accountId);
255
273
  const actionArgs = { ...executionArgs };
256
274
  delete actionArgs[CONNECTION_ARGUMENT];
257
- const argsHash = connectorArgumentsHash(actionArgs);
275
+ const argsHash = connectorArgumentsHash({
276
+ args: actionArgs,
277
+ accountId: connection.accountId,
278
+ objective: available.context ? connectorObjectiveScope(available.context.conversationId) : void 0
279
+ });
258
280
  let confirmed = false;
259
281
  if (approvalId) {
260
282
  const pending = getConnectorApproval(approvalId);
261
- if (!pending || pending.principalId !== available.principalId || pending.connectorId !== resolved.installation.connectorId || pending.actionId !== action.actionId || pending.conversationId !== available.context?.conversationId) return textResult("The connector approval is invalid for this session or action.");
283
+ if (!pending || pending.principalId !== available.principalId || pending.connectorId !== resolved.installation.connectorId || pending.actionId !== action.actionId || pending.conversationId !== available.context?.conversationId || pending.agentId !== available.agentId || !pending.connectionId || getConnectorConnection(pending.connectionId)?.accountId !== connection.accountId) return textResult("The connector approval is invalid for this session or action.");
262
284
  confirmed = Boolean(consumeConnectorApproval(approvalId, argsHash));
263
285
  if (!confirmed) return textResult("The connector approval is not approved, has expired, or was already used.");
264
286
  }
@@ -286,7 +308,22 @@ var ComposioToolProvider = class {
286
308
  throw error;
287
309
  }
288
310
  if (result.decision === "confirmation_required") {
311
+ const wait = available.context && getSessionInputState(available.context.conversationId).activeInputId ? requireSessionConnection({
312
+ conversationId: available.context.conversationId,
313
+ principalId: available.principalId,
314
+ agentId: available.agentId ?? "main",
315
+ summary: `Confirm ${action.actionId}`,
316
+ needs: [{
317
+ key: `${resolved.installation.connectorId}:${connection.accountId}`,
318
+ connectorId: resolved.installation.connectorId,
319
+ accountId: connection.accountId,
320
+ connectionId: connection.id,
321
+ label: toolkit,
322
+ capabilities: [action.actionId]
323
+ }]
324
+ }) : void 0;
289
325
  const approval = createConnectorApproval({
326
+ waitId: wait?.waitId,
290
327
  principalId: available.principalId,
291
328
  connectorId: resolved.installation.connectorId,
292
329
  connectionId: connection?.id,
@@ -294,10 +331,22 @@ var ComposioToolProvider = class {
294
331
  conversationId: available.context?.conversationId,
295
332
  actionId: action.actionId,
296
333
  scope: action.scope,
297
- argumentsHash: argsHash,
298
- argumentsPreview: connectorArgumentsPreview(actionArgs),
334
+ argumentsHash: connectorArgumentsHash({
335
+ args: actionArgs,
336
+ accountId: connection.accountId,
337
+ objective: available.context ? connectorObjectiveScope(available.context.conversationId) : void 0
338
+ }),
339
+ argumentsPreview: {
340
+ account: {
341
+ id: connection.accountId,
342
+ label: getConnectorAccount(connection.accountId)?.label,
343
+ identity: connectorIdentitySummary(connection.identity)
344
+ },
345
+ arguments: connectorArgumentsPreview(actionArgs)
346
+ },
299
347
  expiresAt: new Date(Date.now() + 10 * 6e4).toISOString()
300
348
  });
349
+ if (available.context && wait?.waitId) publishConnectionWait(available.context.conversationId);
301
350
  return textResult({
302
351
  status: "confirmation_required",
303
352
  approvalId: approval.id,
@@ -305,17 +354,31 @@ var ComposioToolProvider = class {
305
354
  scope: approval.scope,
306
355
  argumentsPreview: approval.argumentsPreview,
307
356
  expiresAt: approval.expiresAt,
357
+ account: {
358
+ id: connection.accountId,
359
+ label: getConnectorAccount(connection.accountId)?.label,
360
+ identity: connectorIdentitySummary(connection.identity)
361
+ },
308
362
  instruction: "Ask the user to approve this exact action in xopc, then retry with the approvalId and unchanged arguments."
309
363
  });
310
364
  }
311
- return textResult(result.decision === "allowed" ? result.result : result.reason);
365
+ return textResult(result.decision === "allowed" ? {
366
+ account: {
367
+ id: connection.accountId,
368
+ label: getConnectorAccount(connection.accountId)?.label,
369
+ identity: connectorIdentitySummary(connection.identity)
370
+ },
371
+ result: result.result
372
+ } : result.reason);
312
373
  }
313
374
  availableInstallations() {
314
375
  const context = this.deps.getCurrentContext();
315
376
  const principal = connectorPrincipalForSession(context?.conversationId);
316
377
  if (principal.isLocalOwner) syncLocalOwnerInstallations(this.deps.getConfig());
317
378
  const agentId = this.deps.agentId ?? principal.agentId;
318
- const installations = listConnectorInstallations(principal.principalId).filter((installation) => installation.enabled && composioToolkitFromConnectorId(installation.connectorId) !== void 0 && (installation.allowedAgentIds.length === 0 || Boolean(agentId && installation.allowedAgentIds.includes(agentId))));
379
+ const config = this.deps.getConfig();
380
+ const disabled = new Set(config ? listConnectorInstances(config).filter((instance) => !instance.enabled).map((instance) => instance.connectorId) : []);
381
+ const installations = listConnectorInstallations(principal.principalId).filter((installation) => installation.enabled && !disabled.has(installation.connectorId) && composioToolkitFromConnectorId(installation.connectorId) !== void 0 && (installation.allowedAgentIds.length === 0 || Boolean(agentId && installation.allowedAgentIds.includes(agentId))));
319
382
  return {
320
383
  principalId: principal.principalId,
321
384
  agentId,
@@ -1,11 +1,12 @@
1
+ import { init_connector_repository, listConnectorConnections } from "../../storage/sqlite/connector-repository.js";
1
2
  import { connectionBindings, getActiveConnectionWait, init_connection_wait_repository, publishConnectionWait, requireSessionConnection, reviseCurrentConnectionObjective } from "../../storage/sqlite/connection-wait-repository.js";
2
- import { listConnectorConnections } from "../../storage/sqlite/connector-repository.js";
3
3
  import { connectorPrincipalForSession } from "../../connectors/principal.js";
4
4
  import { connectionCandidates, resolveConnectionCandidate } from "../../connectors/connection-candidates.js";
5
5
  import { ExternalToolService } from "./service.js";
6
6
  import { EXTERNAL_TOOL_SOURCES } from "./types.js";
7
7
  import { Type } from "@sinclair/typebox";
8
8
  //#region src/agent/external-tools/gateway-tools.ts
9
+ init_connector_repository();
9
10
  init_connection_wait_repository();
10
11
  const EXTERNAL_TOOL_NAMES = {
11
12
  search: "xopc_tool_search",
@@ -24,6 +24,8 @@ export declare function buildTranscriptUserMessage(opts: {
24
24
  modelRef: string;
25
25
  config: Config | undefined;
26
26
  agentManager: AgentInstanceGateway;
27
+ /** Keep these attachments in transcript metadata without exposing read_media hints to the LLM. */
28
+ suppressMediaPromptUris?: ReadonlySet<string>;
27
29
  }): Promise<TranscriptUserMessage>;
28
30
  /** Hydrate images from media store for the current LLM prompt. */
29
31
  export declare function hydrateUserTurnForLlm(opts: {
@@ -58,8 +58,8 @@ async function readImageBase64FromRef(ref) {
58
58
  mimeType: prepared.mimeType
59
59
  };
60
60
  }
61
- function appendMediaAttachedLines(textParts, media) {
62
- for (const ref of media) if (!isImageInboundAttachment(ref)) textParts.push([
61
+ function appendMediaAttachedLines(textParts, media, suppressMediaPromptUris) {
62
+ for (const ref of media) if (!isImageInboundAttachment(ref) && !suppressMediaPromptUris?.has(ref.uri)) textParts.push([
63
63
  `[media attached: ${ref.name} (${ref.mimeType}, ${ref.size} bytes)]`,
64
64
  `xopc-media-uri:${ref.uri}`,
65
65
  `xopc-media-path:${ref.path}`,
@@ -85,7 +85,7 @@ async function buildTranscriptUserMessage(opts) {
85
85
  const textParts = [];
86
86
  if (expandedText) textParts.push(expandedText);
87
87
  const strategy = resolveImageHandlingStrategy(opts.modelRef);
88
- appendMediaAttachedLines(textParts, prepared.filter((m) => !isImageInboundAttachment(m)));
88
+ appendMediaAttachedLines(textParts, prepared.filter((m) => !isImageInboundAttachment(m)), opts.suppressMediaPromptUris);
89
89
  if (imageRefs.length > 0 && strategy !== "native") {
90
90
  const images = await Promise.all(imageRefs.map((ref) => readImageBase64FromRef(ref)));
91
91
  const agentId = opts.config ? extractProfileAgentId(opts.conversationId, opts.config) : void 0;
@@ -95,6 +95,7 @@ var InboundLoop = class {
95
95
  ...sessionMetadata?.transcriptId ? { transcriptId: sessionMetadata.transcriptId } : {}
96
96
  });
97
97
  await this.cfg.sessionContextManager.runWith(sessionContext, async () => {
98
+ await this.cfg.agentManager.ensureMemoryReadyForSession?.(sessionContext.conversationId);
98
99
  this.cfg.agentManager.getOrCreateAgent(sessionContext.conversationId);
99
100
  this.cfg.setupSessionEventHandling(sessionContext.conversationId);
100
101
  await this.cfg.sessionLifecycleManager.startSession(sessionContext);
@@ -106,13 +106,14 @@ var TurnDispatcher = class {
106
106
  sessionConfigStore: c.sessionConfigStore,
107
107
  commandHandler: c.commandHandler,
108
108
  prepareInboundAttachments: c.prepareInboundAttachments,
109
- buildTranscriptUserMessage: async (text, prepared, sk) => buildDirectUserMessageContent({
109
+ buildTranscriptUserMessage: async (text, prepared, sk, options) => buildDirectUserMessageContent({
110
110
  content: text,
111
111
  attachments: prepared,
112
112
  conversationId: sk,
113
113
  config: c.requireConfig(),
114
114
  agentManager: c.agentManager,
115
- modelManager: c.modelManager
115
+ modelManager: c.modelManager,
116
+ suppressMediaPromptUris: options?.suppressMediaPromptUris
116
117
  }),
117
118
  recordTaskReviewStreamHint: (sk, o) => c.sessionState.recordTaskReviewStreamHint(sk, o),
118
119
  enqueueProvisionalSessionTitle: (sk, userText) => {
@@ -128,7 +129,6 @@ var TurnDispatcher = class {
128
129
  sourceContextResolver: c.sourceContextResolver,
129
130
  maybeEmitWebchatTts: (sk, hadVoice) => maybeEmitWebchatTts({
130
131
  config: c.getConfig(),
131
- sessionStore: c.sessionStore,
132
132
  getLastAssistantPlainText: (conversationId) => c.sessionState.getLastAssistantText(conversationId) ?? c.agentManager.getLastAssistantContent(conversationId) ?? "",
133
133
  log: this.log
134
134
  }, sk, hadVoice),
@@ -2,9 +2,9 @@ import { init_global_singleton, resolveGlobalSingleton } from "../../utils/globa
2
2
  import { createLogger } from "../../utils/logger/index.js";
3
3
  import { init_logger } from "../../utils/logger.js";
4
4
  import { init_string_coerce, normalizeOptionalString } from "../../utils/string-coerce.js";
5
+ import { resolveConnectorSecretReferences } from "../../connectors/secret-store.js";
5
6
  import { redactSensitiveUrlLikeString } from "../../utils/redact-sensitive-url.js";
6
7
  import { loadEmbeddedMcpConfig } from "./embedded-mcp.js";
7
- import { resolveConnectorSecretReferences } from "../../connectors/secret-store.js";
8
8
  import { isMcpConfigRecord } from "./mcp-config-shared.js";
9
9
  import { resolveMcpTransport } from "./mcp-transport.js";
10
10
  import { sanitizeServerName } from "./bundle-mcp-names.js";
@@ -1,4 +1,4 @@
1
- import { killProcessTree } from "../../process/kill-tree.js";
1
+ import { terminateProcess } from "../../process/kill-tree.js";
2
2
  import { spawn } from "node:child_process";
3
3
  import { getDefaultEnvironment } from "@modelcontextprotocol/sdk/client/stdio.js";
4
4
  import process from "node:process";
@@ -87,7 +87,10 @@ var XopcStdioClientTransport = class {
87
87
  } catch {}
88
88
  await Promise.race([closePromise, delay(CLOSE_TIMEOUT_MS)]);
89
89
  if (processToClose.exitCode === null && processToClose.pid) {
90
- killProcessTree(processToClose.pid);
90
+ await terminateProcess(processToClose, {
91
+ tree: true,
92
+ detached: process.platform !== "win32"
93
+ });
91
94
  await Promise.race([closePromise, delay(CLOSE_TIMEOUT_MS)]);
92
95
  }
93
96
  }
@@ -1,8 +1,8 @@
1
1
  import { init_global_singleton, resolveGlobalSingleton } from "../../../utils/global-singleton.js";
2
2
  import { createLogger } from "../../../utils/logger/index.js";
3
3
  import { init_logger } from "../../../utils/logger.js";
4
- import { redactSensitiveUrlLikeString } from "../../../utils/redact-sensitive-url.js";
5
4
  import { resolveConnectorSecretReferences } from "../../../connectors/secret-store.js";
5
+ import { redactSensitiveUrlLikeString } from "../../../utils/redact-sensitive-url.js";
6
6
  import { resolveMcpTransportConfig } from "../mcp-transport-config.js";
7
7
  import { isMcpAuthorizationError } from "./mcp-oauth-errors.js";
8
8
  import { McpOAuthStore, canonicalMcpServerUrl } from "./mcp-oauth-store.js";
@@ -1,4 +1,4 @@
1
- import { listKnowledgeItems, setKnowledgeStatus, writeKnowledgeItem } from "../../knowledge-memory/repository.js";
1
+ import { listKnowledgeItems, transitionKnowledgeStatus, writeKnowledgeItem } from "../../knowledge-memory/repository.js";
2
2
  import "../../knowledge-memory/index.js";
3
3
  import { resolveMemorySessionKind } from "./turn-provenance.js";
4
4
  import { createHash } from "node:crypto";
@@ -146,7 +146,12 @@ function promoteCompactionLedger(input) {
146
146
  result.episodicRecordIds.push(episode.item.id);
147
147
  if (!(active && input.audit.status === "passed" && sessionKind === "interactive" && originClass === "agent" && !classified.derivedFromRecalledContext && DURABLE_KINDS.has(item.kind))) {
148
148
  const existingDurable = !active ? listKnowledgeItems({ limit: 2e3 }).find((entry) => entry.canonicalKey === `durable:${item.kind}:${stableId("fact", item.text)}`) : void 0;
149
- if (existingDurable?.sourceConversationId === input.conversationId) setKnowledgeStatus(existingDurable.id, "archived");
149
+ if (existingDurable?.sourceConversationId === input.conversationId) transitionKnowledgeStatus({
150
+ id: existingDurable.id,
151
+ status: "archived",
152
+ actor: "runtime",
153
+ reason: "The source session no longer supports this durable memory."
154
+ });
150
155
  result.rejectedRecordIds.push(episode.item.id);
151
156
  continue;
152
157
  }
@@ -19,6 +19,7 @@ function resolveMemoryManagerOptions(config) {
19
19
  const providerRouting = config.userContext.knowledgeMemory;
20
20
  return {
21
21
  searchStrategy: providerRouting.searchStrategy,
22
+ searchTimeoutMs: providerRouting.searchTimeoutMs,
22
23
  writeStrategy: providerRouting.writeStrategy,
23
24
  writePolicy: {
24
25
  allowExternalWrites: providerRouting.allowExternalWrites,
@@ -14,6 +14,7 @@ export interface MemoryManagerOptions extends MemoryRoutingOptions {
14
14
  loadProviders?: () => Promise<MemoryProvider[]>;
15
15
  writePolicy?: MemoryWritePolicy;
16
16
  memoryRuntime?: MemoryRuntime;
17
+ searchTimeoutMs?: number;
17
18
  }
18
19
  export interface MemoryWritePolicy {
19
20
  allowExternalWrites?: boolean;
@@ -27,7 +28,10 @@ export declare class MemoryManager {
27
28
  private readonly loadProviders?;
28
29
  private readonly writePolicy;
29
30
  private pluginProvidersLoaded;
31
+ private pluginProvidersPromise?;
32
+ private readonly sessionInitializations;
30
33
  private readonly memoryRuntime?;
34
+ private readonly searchTimeoutMs;
31
35
  private readonly sessionContexts;
32
36
  constructor(options?: MemoryManagerOptions);
33
37
  addProvider(provider: MemoryProvider): void;
@@ -48,6 +52,8 @@ export declare class MemoryManager {
48
52
  }>;
49
53
  handleToolCall(toolName: string, args: Record<string, unknown>): Promise<string>;
50
54
  search(request: MemorySearchRequest): Promise<MemorySearchResult[]>;
55
+ searchExternal(request: MemorySearchRequest): Promise<MemorySearchResult[]>;
56
+ private searchProviders;
51
57
  read(request: MemoryReadRequest): Promise<MemoryReadResult | null>;
52
58
  get(id: string): Promise<MemoryRecord | null>;
53
59
  list(request: MemoryListRequest): Promise<MemoryRecord[]>;
@@ -11,7 +11,10 @@ var MemoryManager = class {
11
11
  loadProviders;
12
12
  writePolicy;
13
13
  pluginProvidersLoaded = false;
14
+ pluginProvidersPromise;
15
+ sessionInitializations = /* @__PURE__ */ new Map();
14
16
  memoryRuntime;
17
+ searchTimeoutMs;
15
18
  sessionContexts = /* @__PURE__ */ new Map();
16
19
  constructor(options = {}) {
17
20
  this.routing = {
@@ -21,6 +24,7 @@ var MemoryManager = class {
21
24
  };
22
25
  this.loadProviders = options.loadProviders;
23
26
  this.memoryRuntime = options.memoryRuntime;
27
+ this.searchTimeoutMs = options.searchTimeoutMs ?? 2e3;
24
28
  this.writePolicy = {
25
29
  allowExternalWrites: options.writePolicy?.allowExternalWrites ?? false,
26
30
  allowedProviderIds: options.writePolicy?.allowedProviderIds,
@@ -142,21 +146,29 @@ var MemoryManager = class {
142
146
  return provider.handleToolCall(toolName, args);
143
147
  }
144
148
  async search(request) {
145
- const providers = this.providersForSearch();
146
- const results = [];
147
- for (const p of providers) {
148
- if (!p.capabilities.search || !p.search) continue;
149
+ return this.searchProviders(this.providersForSearch(), request);
150
+ }
151
+ async searchExternal(request) {
152
+ return this.searchProviders(this.providersForSearch().filter((provider) => !provider.capabilities.local), request);
153
+ }
154
+ async searchProviders(providers, request) {
155
+ const searchProvider = async (p) => {
156
+ if (!p.capabilities.search || !p.search) return [];
149
157
  const started = Date.now();
150
158
  try {
151
- const providerResults = await p.search(request);
159
+ let timeout;
160
+ const providerResults = await Promise.race([p.search(request), new Promise((_resolve, reject) => {
161
+ timeout = setTimeout(() => reject(/* @__PURE__ */ new Error(`Memory search timed out after ${this.searchTimeoutMs}ms`)), this.searchTimeoutMs);
162
+ })]).finally(() => {
163
+ if (timeout) clearTimeout(timeout);
164
+ });
152
165
  this.trace("search", p.id, request, {
153
166
  resultCount: providerResults.length,
154
167
  selectedRecordIds: providerResults.map((result) => result.record.id),
155
168
  durationMs: Date.now() - started,
156
169
  conversationId: request.scope?.conversationId
157
170
  });
158
- results.push(...providerResults);
159
- if (providerResults.length > 0 && this.routing.searchStrategy !== "fanout") break;
171
+ return providerResults;
160
172
  } catch (err) {
161
173
  this.trace("search", p.id, request, {
162
174
  error: err instanceof Error ? err.message : String(err),
@@ -167,7 +179,16 @@ var MemoryManager = class {
167
179
  err,
168
180
  id: p.id
169
181
  }, "memory search failed");
182
+ return [];
170
183
  }
184
+ };
185
+ const searchable = providers.filter((provider) => provider.capabilities.search && provider.search);
186
+ const results = [];
187
+ if (this.routing.searchStrategy === "fanout") results.push(...(await Promise.all(searchable.map(searchProvider))).flat());
188
+ else for (const provider of searchable) {
189
+ const providerResults = await searchProvider(provider);
190
+ results.push(...providerResults);
191
+ if (providerResults.length > 0) break;
171
192
  }
172
193
  const seen = /* @__PURE__ */ new Set();
173
194
  return results.sort((a, b) => b.score - a.score).filter((result) => this.canReadRecord(result.record, request.scope)).filter((result) => !request.trustedOnly || (result.record.provenance?.originClass === "owner" || result.record.provenance?.originClass === "agent") && result.record.provenance?.derivedFromRecalledContext === false).filter((result) => {
@@ -245,12 +266,14 @@ var MemoryManager = class {
245
266
  return this.writeWithStrategy("delete", request);
246
267
  }
247
268
  canReadRecord(record, scope) {
248
- if (record.providerId !== "local") return true;
249
- if (this.memoryRuntime && !this.memoryRuntime.canRead(memorySourceForRecord(record))) return false;
269
+ if (this.memoryRuntime) {
270
+ const { scope, source } = memoryAccessForRecord(record);
271
+ if (!this.memoryRuntime.canRead(scope, source)) return false;
272
+ }
250
273
  if (record.scope.userId && scope?.userId && record.scope.userId !== scope.userId) return false;
251
- if (record.scope.conversationId && record.scope.conversationId !== scope?.conversationId) return false;
252
- if (record.scope.projectId && record.scope.projectId !== scope?.projectId) return false;
253
- if (record.scope.workspaceId && record.scope.workspaceId !== scope?.workspaceId) return false;
274
+ if (record.scope.conversationId && scope?.conversationId && record.scope.conversationId !== scope.conversationId) return false;
275
+ if (record.scope.projectId && scope?.projectId && record.scope.projectId !== scope.projectId) return false;
276
+ if (record.scope.workspaceId && scope?.workspaceId && record.scope.workspaceId !== scope.workspaceId) return false;
254
277
  return true;
255
278
  }
256
279
  recordSignal(signal) {
@@ -286,36 +309,48 @@ var MemoryManager = class {
286
309
  }
287
310
  async initializeAll(sessionId, options) {
288
311
  if (options) this.sessionContexts.set(sessionId, { ...options });
289
- await this.loadPluginProvidersOnce();
290
- for (const p of this.providers) try {
291
- await p.initialize(sessionId, options);
292
- } catch (err) {
293
- log.warn({
294
- err,
295
- id: p.id
296
- }, "initialize failed");
297
- }
312
+ const existing = this.sessionInitializations.get(sessionId);
313
+ if (existing) return existing;
314
+ const initialization = (async () => {
315
+ await this.loadPluginProvidersOnce();
316
+ for (const p of this.providers) try {
317
+ await p.initialize(sessionId, options);
318
+ } catch (err) {
319
+ log.warn({
320
+ err,
321
+ id: p.id,
322
+ sessionId
323
+ }, "Memory provider initialization failed");
324
+ }
325
+ })();
326
+ this.sessionInitializations.set(sessionId, initialization);
327
+ return initialization;
298
328
  }
299
329
  async loadPluginProvidersOnce() {
300
330
  if (this.pluginProvidersLoaded || !this.loadProviders) return;
301
- this.pluginProvidersLoaded = true;
302
- try {
303
- const providers = await this.loadProviders();
304
- const existingIds = new Set(this.providers.map((p) => p.id));
305
- for (const provider of providers) {
306
- if (existingIds.has(provider.id)) {
307
- log.warn({ id: provider.id }, "Skipped duplicate memory provider");
308
- continue;
331
+ if (!this.pluginProvidersPromise) this.pluginProvidersPromise = (async () => {
332
+ try {
333
+ const providers = await this.loadProviders();
334
+ const existingIds = new Set(this.providers.map((p) => p.id));
335
+ for (const provider of providers) {
336
+ if (existingIds.has(provider.id)) {
337
+ log.warn({ id: provider.id }, "Skipped duplicate memory provider");
338
+ continue;
339
+ }
340
+ this.addProvider(provider);
341
+ existingIds.add(provider.id);
309
342
  }
310
- this.addProvider(provider);
311
- existingIds.add(provider.id);
343
+ } catch (err) {
344
+ log.warn({ err }, "Memory provider plugin loading failed");
345
+ } finally {
346
+ this.pluginProvidersLoaded = true;
312
347
  }
313
- } catch (err) {
314
- log.warn({ err }, "Memory provider plugin loading failed");
315
- }
348
+ })();
349
+ await this.pluginProvidersPromise;
316
350
  }
317
351
  async shutdownAll() {
318
352
  this.sessionContexts.clear();
353
+ this.sessionInitializations.clear();
319
354
  for (const p of [...this.providers].reverse()) try {
320
355
  await p.shutdown();
321
356
  } catch (err) {
@@ -425,11 +460,11 @@ var MemoryManager = class {
425
460
  }, "External memory provider operation");
426
461
  }
427
462
  };
428
- function memorySourceForRecord(record) {
429
- if (record.source.provider !== "builtin") return "connector";
430
- if (record.scope.conversationId) return "session";
431
- if (record.scope.projectId) return "project";
432
- return "workspace";
463
+ function memoryAccessForRecord(record) {
464
+ return {
465
+ scope: record.scope.conversationId ? "session" : record.scope.projectId ? "project" : record.scope.workspaceId ? "workspace" : "global",
466
+ source: record.source.provider === "builtin" ? "memory" : "connector"
467
+ };
433
468
  }
434
469
  function writeTargetForRecord(_request) {
435
470
  return "knowledge";
@@ -1,5 +1,5 @@
1
1
  import type { UserContextConfig } from '../../user-context/config.js';
2
- export type MemorySource = 'session' | 'workspace' | 'project' | 'connector';
2
+ import type { KnowledgeContentSource, KnowledgeReadPolicy, KnowledgeVisibilityScope } from '../../knowledge-memory/domain.js';
3
3
  export type MemoryWriteTarget = 'knowledge';
4
4
  export type MemoryWriteDecision = 'allow' | 'confirm' | 'deny';
5
5
  export interface MemoryCandidate {
@@ -14,8 +14,8 @@ export interface MemoryWriteCheckResult {
14
14
  reason: string;
15
15
  }
16
16
  export interface MemoryRuntime {
17
- readableSources: MemorySource[];
18
- canRead: (source: MemorySource) => boolean;
17
+ readPolicy: KnowledgeReadPolicy;
18
+ canRead: (scope: KnowledgeVisibilityScope, source: KnowledgeContentSource) => boolean;
19
19
  checkWrite: (candidate: MemoryCandidate) => MemoryWriteCheckResult;
20
20
  }
21
21
  export declare function buildMemoryRuntime(userContext: UserContextConfig): MemoryRuntime;
@@ -5,11 +5,18 @@ function normalizeConfidence(value) {
5
5
  }
6
6
  function buildMemoryRuntime(userContext) {
7
7
  const memory = userContext.knowledgeMemory;
8
- const readableSources = !userContext.enabled || !memory.enabled ? [] : [...memory.sources];
9
- const sourceSet = new Set(readableSources);
8
+ const readPolicy = !userContext.enabled || !memory.enabled ? {
9
+ scopes: [],
10
+ contentSources: []
11
+ } : {
12
+ scopes: memory.readScopes,
13
+ contentSources: memory.contentSources
14
+ };
15
+ const scopes = new Set(readPolicy.scopes);
16
+ const contentSources = new Set(readPolicy.contentSources);
10
17
  return {
11
- readableSources,
12
- canRead: (source) => sourceSet.has(source),
18
+ readPolicy,
19
+ canRead: (scope, source) => scopes.has(scope) && contentSources.has(source),
13
20
  checkWrite: (candidate) => {
14
21
  if (!userContext.enabled || !memory.enabled) return {
15
22
  decision: "deny",