@xopcai/xopc 0.0.211 → 0.0.213

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 (212) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{activity-store-BzjFoSr0.js → activity-store-Xw-pOm9A.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DTfjhfVE.js → agent-avatar-dicebear-Ca1bciiK.js} +1 -1
  5. package/dist/gateway/static/root/assets/agents-DD3TqNrC.js +68 -0
  6. package/dist/gateway/static/root/assets/{api-D269PnU9.js → api-CZK-lRew.js} +1 -1
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-BFpfQDWc.js → app-management-settings-panel-BLFIG09j.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-DLxFdqhY.js → appearance-settings-BsTWUq1i.js} +1 -1
  9. package/dist/gateway/static/root/assets/apps-page-cJkDKn72.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-DPlH4dnc.js → archive-plugin-B9LsFfEx.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-xqfLLd0I.js → attachment-load-CsWiFfmN.js} +1 -1
  12. package/dist/gateway/static/root/assets/automations-page-CbjU2e75.js +1 -0
  13. package/dist/gateway/static/root/assets/automations-workspace-C4xyo0c4.js +6 -0
  14. package/dist/gateway/static/root/assets/{binary-plugins-C0tuoPXk.js → binary-plugins-DbqhT_JB.js} +1 -1
  15. package/dist/gateway/static/root/assets/{block-editor-Deyphj1o.js → block-editor-BGpHwxZ5.js} +47 -47
  16. package/dist/gateway/static/root/assets/browser-settings-page-CrhpQl-e.js +8 -0
  17. package/dist/gateway/static/root/assets/{browser-workflow-inputs-CYEbXyRF.js → browser-workflow-inputs-BXlon_hL.js} +1 -1
  18. package/dist/gateway/static/root/assets/{browser-workflows-page-Bf0tPbGi.js → browser-workflows-page-B3BBDM_r.js} +2 -2
  19. package/dist/gateway/static/root/assets/capabilities-settings-panel-B9MoPW9u.js +7 -0
  20. package/dist/gateway/static/root/assets/{capability-presets-api-DPkFA_-R.js → capability-presets-api-BqvMm6UW.js} +1 -1
  21. package/dist/gateway/static/root/assets/capability-presets-settings-panel-BmwldV9R.js +3 -0
  22. package/dist/gateway/static/root/assets/{channel-recipient-api-DqKaAcnZ.js → channel-recipient-api-9uca5kDa.js} +1 -1
  23. package/dist/gateway/static/root/assets/channels-settings-CwLqWcy_.js +1 -0
  24. package/dist/gateway/static/root/assets/channels-status-swr-DeBw3du9.js +1 -0
  25. package/dist/gateway/static/root/assets/{chat-terminal-dock-CTDRZa7e.js → chat-terminal-dock-DJjYT3WX.js} +2 -2
  26. package/dist/gateway/static/root/assets/{chunk-KS7C4IRE-BMhrPKJC.js → chunk-KS7C4IRE-BaASWQor.js} +1 -1
  27. package/dist/gateway/static/root/assets/{connectors-api-Buu8fif8.js → connectors-api-XCLfuDrN.js} +1 -1
  28. package/dist/gateway/static/root/assets/connectors-page-CVkGtcMS.js +2 -0
  29. package/dist/gateway/static/root/assets/{cron-expression-DTLR82NB.js → cron-expression-DzQN7zBR.js} +1 -1
  30. package/dist/gateway/static/root/assets/{date-picker-DyNogHQH.js → date-picker-B-r5O5qd.js} +1 -1
  31. package/dist/gateway/static/root/assets/{dependency-picker-BpnCuo7B.js → dependency-picker-Ch2XBU2s.js} +1 -1
  32. package/dist/gateway/static/root/assets/{desktop-pet-CDKI4gVB.js → desktop-pet-BdjX8jde.js} +1 -1
  33. package/dist/gateway/static/root/assets/{desktop-pet-settings-DjT5C2a3.js → desktop-pet-settings-CzjjgMMn.js} +1 -1
  34. package/dist/gateway/static/root/assets/directory-picker-path-field-BCTgGTk4.js +1 -0
  35. package/dist/gateway/static/root/assets/{extension-debug-page-DWf2z7q5.js → extension-debug-page-6OGgOucD.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-page-Dorx0kf9.js → extension-page-Cf6MUfCF.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-settings-page-B1wU9ZOB.js → extension-settings-page-pSY_ZvQZ.js} +1 -1
  38. package/dist/gateway/static/root/assets/{gateway-config-api-B1lG4dNr.js → gateway-config-api-CFJMng9v.js} +1 -1
  39. package/dist/gateway/static/root/assets/{gateway-config-swr-BIxuwPQi.js → gateway-config-swr-DpiY6aub.js} +1 -1
  40. package/dist/gateway/static/root/assets/{gateway-settings-DqIOqJjM.js → gateway-settings-aQYxNePf.js} +1 -1
  41. package/dist/gateway/static/root/assets/{gateway-startup-retry-BpZgd4U-.js → gateway-startup-retry-BZ_6ChP4.js} +1 -1
  42. package/dist/gateway/static/root/assets/{heartbeat-settings-DG4Kmgkc.js → heartbeat-settings-CI33q9i1.js} +1 -1
  43. package/dist/gateway/static/root/assets/home-page-CAIaWs6r.js +1 -0
  44. package/dist/gateway/static/root/assets/{image-generation-api-PkhYohDa.js → image-generation-api-DPndEWOU.js} +1 -1
  45. package/dist/gateway/static/root/assets/index-BhstAl5i.js +108 -0
  46. package/dist/gateway/static/root/assets/index-DQzjgIkQ.css +2 -0
  47. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-6OQT3gQF.js → keyboard-shortcuts-settings-CbLJRGXR.js} +1 -1
  48. package/dist/gateway/static/root/assets/local-app-workbench-page-BqFnCaKT.js +2 -0
  49. package/dist/gateway/static/root/assets/{local-apps-page-DfruRAmE.js → local-apps-page-Crf6c3SK.js} +1 -1
  50. package/dist/gateway/static/root/assets/{locale-store-C5MK9WcP.js → locale-store-BYSRjM6g.js} +1 -1
  51. package/dist/gateway/static/root/assets/logs-page-BpfLQWex.js +2 -0
  52. package/dist/gateway/static/root/assets/{management-settings-L1VYkywO.js → management-settings-mxyYWKgM.js} +1 -1
  53. package/dist/gateway/static/root/assets/{markdown-split-oqgHbqt-.js → markdown-split-kZaPrUTM.js} +1 -1
  54. package/dist/gateway/static/root/assets/{markdown-view-V4rcPPH0.js → markdown-view-DlsczsQ1.js} +1 -1
  55. package/dist/gateway/static/root/assets/{media-plugins-Bb6gSX2o.js → media-plugins-Dk67jaG6.js} +1 -1
  56. package/dist/gateway/static/root/assets/messages-DyM8OOVG.js +3 -0
  57. package/dist/gateway/static/root/assets/notes-api-DaeeQw8A.js +1 -0
  58. package/dist/gateway/static/root/assets/{notes-page-B1rOXjpT.js → notes-page-CQDzw8fX.js} +1 -1
  59. package/dist/gateway/static/root/assets/notes-workbench-BYiROmRJ.js +4 -0
  60. package/dist/gateway/static/root/assets/{page-tabs-CBuCKeyy.js → page-tabs-C4UkhX2U.js} +1 -1
  61. package/dist/gateway/static/root/assets/{preview-open-alternatives-BQ0tLfPO.js → preview-open-alternatives-nzcjh6y0.js} +1 -1
  62. package/dist/gateway/static/root/assets/{product-open-page-DPeFn7Hu.js → product-open-page-3FvW5cHm.js} +1 -1
  63. package/dist/gateway/static/root/assets/project-detail-page-p45i1sMj.js +1 -0
  64. package/dist/gateway/static/root/assets/projects-page-Y9yXB4DX.js +1 -0
  65. package/dist/gateway/static/root/assets/registry-api-Bu6OGEY2.js +2 -0
  66. package/dist/gateway/static/root/assets/remote-access-hub-CNsGY0VS.js +1 -0
  67. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-BCfQNzjG.js → runtime-tools-settings-panel-CVqPSfUb.js} +2 -2
  68. package/dist/gateway/static/root/assets/{schema-form-Bo7YbHYN.js → schema-form-Dz6eZpqv.js} +1 -1
  69. package/dist/gateway/static/root/assets/sessions-page-BAtpgb1t.js +1 -0
  70. package/dist/gateway/static/root/assets/settings-advanced-gate-pgBQ21Oe.js +1 -0
  71. package/dist/gateway/static/root/assets/{settings-form-section-B9dnKr3M.js → settings-form-section-BaWFAZv4.js} +1 -1
  72. package/dist/gateway/static/root/assets/{settings-loading-skeleton-CYDV2JtY.js → settings-loading-skeleton-BWmdZfNg.js} +1 -1
  73. package/dist/gateway/static/root/assets/{settings-page-DbrIYfS9.js → settings-page-Btcb-Dc8.js} +1 -1
  74. package/dist/gateway/static/root/assets/setup-status-panel-BNllZUFP.js +1 -0
  75. package/dist/gateway/static/root/assets/{share-preview-page-olgr7LLN.js → share-preview-page-CGzY3S0N.js} +1 -1
  76. package/dist/gateway/static/root/assets/shares-settings-CncwbTHY.js +1 -0
  77. package/dist/gateway/static/root/assets/skill-reload-api-CcW2dhSW.js +1 -0
  78. package/dist/gateway/static/root/assets/{skills-page-PE16CNw5.js → skills-page-Bi2IWpU0.js} +1 -1
  79. package/dist/gateway/static/root/assets/{skills-page.utils-nXmBcBxt.js → skills-page.utils-BancvwN2.js} +1 -1
  80. package/dist/gateway/static/root/assets/{system-settings-panel-C3qPwAdY.js → system-settings-panel-CihjIzWx.js} +1 -1
  81. package/dist/gateway/static/root/assets/task-detail-page-SSNFtY-d.js +1 -0
  82. package/dist/gateway/static/root/assets/{theme-store-KR5Otp5w.js → theme-store-D1_t_31B.js} +1 -1
  83. package/dist/gateway/static/root/assets/{typed-models-lib-lMZodtDF.js → typed-models-lib-C2LhiQq5.js} +1 -1
  84. package/dist/gateway/static/root/assets/{use-autosave-CKpatP3S.js → use-autosave-tf_8rxAK.js} +1 -1
  85. package/dist/gateway/static/root/assets/user-context-page-BnPTFEar.js +1 -0
  86. package/dist/gateway/static/root/assets/{voice-api-key-field-CDcv0Wbh.js → voice-api-key-field-DN-y7Zfe.js} +1 -1
  87. package/dist/gateway/static/root/assets/work-discovery-overlay-bqqH4aZ9.js +1 -0
  88. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BAHYNlQt.js → workflow-run-setup-panel-2H33iXOB.js} +2 -2
  89. package/dist/gateway/static/root/assets/workflows-page-BnfxRf1q.js +5 -0
  90. package/dist/gateway/static/root/index.html +12 -10
  91. package/dist/package.js +1 -1
  92. package/dist/src/auth/oauth/xopc-cloud.js +1 -1
  93. package/dist/src/cli/commands/connectors.js +1 -1
  94. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  95. package/dist/src/cli/commands/tunnel.js +3 -3
  96. package/dist/src/config/agent-profile.js +1 -1
  97. package/dist/src/connectors/composio-managed-client.d.ts +60 -0
  98. package/dist/src/connectors/composio-managed-client.js +135 -0
  99. package/dist/src/connectors/composio-managed-events.d.ts +41 -0
  100. package/dist/src/connectors/composio-managed-events.js +105 -0
  101. package/dist/src/connectors/composio-sessions.d.ts +2 -1
  102. package/dist/src/connectors/composio-sessions.js +13 -7
  103. package/dist/src/connectors/composio.js +2 -1
  104. package/dist/src/connectors/connected-source-ingestion.js +67 -25
  105. package/dist/src/connectors/health.js +1 -1
  106. package/dist/src/connectors/learning-recipes.js +2 -0
  107. package/dist/src/connectors/runtime-adapter-registry.js +2 -2
  108. package/dist/src/discussions/sealer.js +2 -2
  109. package/dist/src/discussions/service.js +6 -2
  110. package/dist/src/discussions/transcript.d.ts +2 -0
  111. package/dist/src/discussions/transcript.js +16 -3
  112. package/dist/src/extensions/install.d.ts +10 -0
  113. package/dist/src/extensions/install.js +111 -14
  114. package/dist/src/extensions/loader.js +22 -18
  115. package/dist/src/gateway/agents-admin.js +1 -1
  116. package/dist/src/gateway/heartbeat/service.js +1 -1
  117. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  118. package/dist/src/gateway/hono/middleware/auth.js +2 -2
  119. package/dist/src/gateway/hono/middleware/logger.js +1 -1
  120. package/dist/src/gateway/hono/middleware/strict-rate-limit.js +1 -1
  121. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  122. package/dist/src/gateway/hono/routes/connectors.js +11 -4
  123. package/dist/src/gateway/hono/routes/exposure.js +1 -1
  124. package/dist/src/gateway/hono/routes/home.d.ts +1 -1
  125. package/dist/src/gateway/hono/routes/home.js +2 -2
  126. package/dist/src/gateway/hono/routes/mcp.js +1 -1
  127. package/dist/src/gateway/hono/routes/shares.js +1 -1
  128. package/dist/src/gateway/hono/routes/tunnel.js +3 -3
  129. package/dist/src/gateway/hono/routes/workflows.js +69 -0
  130. package/dist/src/gateway/index.js +2 -2
  131. package/dist/src/gateway/runtime-config.js +2 -2
  132. package/dist/src/gateway/security/audit.js +2 -2
  133. package/dist/src/gateway/service/config-coordinator.js +1 -1
  134. package/dist/src/gateway/service.d.ts +1 -0
  135. package/dist/src/gateway/service.js +25 -10
  136. package/dist/src/heartbeat/index.js +1 -1
  137. package/dist/src/notes/note-attachment-sync.js +1 -1
  138. package/dist/src/notes/service.d.ts +1 -0
  139. package/dist/src/notes/service.js +2 -1
  140. package/dist/src/notes/types.d.ts +2 -0
  141. package/dist/src/providers/model-catalog-persistence.d.ts +1 -1
  142. package/dist/src/providers/model-catalog-store.d.ts +2 -60
  143. package/dist/src/providers/model-catalog-types.d.ts +60 -0
  144. package/dist/src/providers/model-catalog-types.js +1 -0
  145. package/dist/src/providers/provider-disconnect-core.d.ts +11 -0
  146. package/dist/src/providers/provider-disconnect-core.js +35 -0
  147. package/dist/src/providers/provider-disconnect.d.ts +2 -10
  148. package/dist/src/providers/provider-disconnect.js +4 -26
  149. package/dist/src/providers/xopc-cloud-catalog-coordinator.js +2 -2
  150. package/dist/src/storage/sqlite/migrations/124_workflow_context_snapshots.sql +15 -0
  151. package/dist/src/storage/sqlite/migrations/125_project_workflow_presets.sql +12 -0
  152. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  153. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  154. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  155. package/dist/src/storage/sqlite/schema.js +1 -1
  156. package/dist/src/tasks/home-query-service.d.ts +12 -127
  157. package/dist/src/tasks/home-query-service.js +73 -271
  158. package/dist/src/tasks/index.js +2 -2
  159. package/dist/src/tui/tui-startup-resources.js +1 -1
  160. package/dist/src/tui/xopc-tui-keybindings.d.ts +2 -2
  161. package/dist/src/tunnel/index.js +2 -2
  162. package/dist/src/voice/audio/normalize.d.ts +1 -0
  163. package/dist/src/voice/audio/normalize.js +24 -4
  164. package/dist/src/voice/local/wav.d.ts +3 -0
  165. package/dist/src/voice/local/wav.js +10 -4
  166. package/dist/src/work-discovery/service.js +6 -8
  167. package/dist/src/work-discovery/types.d.ts +2 -0
  168. package/dist/src/workflows/context/workflow-context-snapshot-repository.d.ts +21 -0
  169. package/dist/src/workflows/context/workflow-context-snapshot-repository.js +40 -0
  170. package/dist/src/workflows/context/workflow-context.d.ts +18 -0
  171. package/dist/src/workflows/context/workflow-context.js +159 -0
  172. package/dist/src/workflows/domain/run.d.ts +10 -1
  173. package/dist/src/workflows/engine/workflow-engine.d.ts +1 -0
  174. package/dist/src/workflows/engine/workflow-engine.js +2 -0
  175. package/dist/src/workflows/project-presets/project-workflow-preset-repository.d.ts +20 -0
  176. package/dist/src/workflows/project-presets/project-workflow-preset-repository.js +38 -0
  177. package/dist/src/workflows/service/workflow-run-service.d.ts +1 -0
  178. package/dist/src/workflows/service/workflow-run-service.js +107 -22
  179. package/dist/src/workflows/service/workflow-run-service.types.d.ts +1 -0
  180. package/dist/src/workflows/service/workflow-writeback-service.d.ts +9 -0
  181. package/dist/src/workflows/service/workflow-writeback-service.js +106 -0
  182. package/package.json +6 -6
  183. package/dist/gateway/static/root/assets/agents-CjhgfuVJ.js +0 -68
  184. package/dist/gateway/static/root/assets/apps-page-CjmlGB5V.js +0 -1
  185. package/dist/gateway/static/root/assets/automations-page-4m6Ey6wG.js +0 -6
  186. package/dist/gateway/static/root/assets/browser-settings-page-CAGCYx8U.js +0 -8
  187. package/dist/gateway/static/root/assets/capabilities-settings-panel-CKfLsxTI.js +0 -7
  188. package/dist/gateway/static/root/assets/capability-presets-settings-panel-CpipKNqX.js +0 -3
  189. package/dist/gateway/static/root/assets/channels-settings-Bvq-O4pt.js +0 -1
  190. package/dist/gateway/static/root/assets/channels-status-swr-CrMld2l7.js +0 -1
  191. package/dist/gateway/static/root/assets/connectors-page-CSQRzaVn.js +0 -2
  192. package/dist/gateway/static/root/assets/directory-picker-path-field-DlJY90TM.js +0 -1
  193. package/dist/gateway/static/root/assets/home-page-BhqItS_s.js +0 -1
  194. package/dist/gateway/static/root/assets/index-DLhvsU9B.css +0 -2
  195. package/dist/gateway/static/root/assets/index-_cuTcWjB.js +0 -107
  196. package/dist/gateway/static/root/assets/local-app-workbench-page-DWjTmzxw.js +0 -2
  197. package/dist/gateway/static/root/assets/logs-page-BA5efZ8B.js +0 -2
  198. package/dist/gateway/static/root/assets/messages-ctG2e-ix.js +0 -3
  199. package/dist/gateway/static/root/assets/notes-workbench-CkHXVmKP.js +0 -4
  200. package/dist/gateway/static/root/assets/project-detail-page-DCqet9-L.js +0 -1
  201. package/dist/gateway/static/root/assets/projects-page-D0t_AjzG.js +0 -1
  202. package/dist/gateway/static/root/assets/remote-access-hub-BUWPoBvw.js +0 -1
  203. package/dist/gateway/static/root/assets/sessions-page-vLhrrM3m.js +0 -1
  204. package/dist/gateway/static/root/assets/settings-advanced-gate-OP1y0Y8M.js +0 -1
  205. package/dist/gateway/static/root/assets/setup-status-panel-Cxc-Ejl5.js +0 -1
  206. package/dist/gateway/static/root/assets/shares-settings-ZOqC6-aA.js +0 -1
  207. package/dist/gateway/static/root/assets/skill-reload-api-DwvC3Iuf.js +0 -1
  208. package/dist/gateway/static/root/assets/task-detail-page-DCRB-5q-.js +0 -1
  209. package/dist/gateway/static/root/assets/user-context-page-CoiedRuA.js +0 -1
  210. package/dist/gateway/static/root/assets/work-discovery-overlay-CGdT22un.js +0 -1
  211. package/dist/gateway/static/root/assets/work-discovery-page-BwaU1RqI.js +0 -1
  212. package/dist/gateway/static/root/assets/workflows-page-DHYmh9G7.js +0 -5
@@ -0,0 +1,135 @@
1
+ import { init_xopc_cloud_config, resolveXopcModelRouterUrl } from "../providers/xopc-cloud-config.js";
2
+ import { getProviderAuthService, init_provider_auth_service } from "../providers/provider-auth-service.js";
3
+ import { randomUUID } from "node:crypto";
4
+ //#region src/connectors/composio-managed-client.ts
5
+ init_provider_auth_service();
6
+ init_xopc_cloud_config();
7
+ var ManagedComposioError = class extends Error {
8
+ constructor(message, status, code) {
9
+ super(message);
10
+ this.status = status;
11
+ this.code = code;
12
+ this.name = "ManagedComposioError";
13
+ }
14
+ };
15
+ var ManagedComposioClient = class {
16
+ mode = "managed";
17
+ fetchImpl;
18
+ routerUrl;
19
+ credentials;
20
+ constructor(options = {}) {
21
+ this.fetchImpl = options.fetchImpl ?? fetch;
22
+ this.routerUrl = resolveXopcModelRouterUrl(options.routerUrl);
23
+ this.credentials = options.credentials ?? getProviderAuthService();
24
+ }
25
+ sessions = { create: async (_userId, config = {}) => {
26
+ if (config.authConfigs && Object.keys(config.authConfigs).length > 0) throw new Error("Custom Composio auth configs require BYOK mode.");
27
+ const enabledToolkits = Array.isArray(config.toolkits) ? config.toolkits : config.toolkits && "enable" in config.toolkits ? config.toolkits.enable : [];
28
+ const connectedAccounts = Object.fromEntries(Object.entries(config.connectedAccounts ?? {}).map(([toolkit, value]) => [toolkit, Array.isArray(value) ? value : [value]]));
29
+ return this.session(enabledToolkits, connectedAccounts);
30
+ } };
31
+ connectedAccounts = {
32
+ list: async () => this.request({ path: "/connectors/composio/connections" }),
33
+ delete: async (id) => this.request({
34
+ path: `/connectors/composio/connections/${encodeURIComponent(id)}`,
35
+ method: "DELETE"
36
+ }),
37
+ refresh: async (id) => this.request({
38
+ path: `/connectors/composio/connections/${encodeURIComponent(id)}/refresh`,
39
+ method: "POST"
40
+ })
41
+ };
42
+ authConfigs = { list: async () => ({ items: [] }) };
43
+ toolkits = { get: async (slug) => {
44
+ const response = await this.request({ path: `/connectors/composio/toolkits/${encodeURIComponent(slug)}/auth` });
45
+ return {
46
+ composioManagedAuthSchemes: response.auth.managedAuthAvailable ? ["OAUTH2"] : [],
47
+ authConfigDetails: response.auth.requiresCustomAuthConfig ? [{}] : []
48
+ };
49
+ } };
50
+ async status() {
51
+ return this.request({ path: "/connectors/composio/status" });
52
+ }
53
+ async events(after = 0, limit = 50) {
54
+ return this.request({ path: `/connectors/composio/events?after=${after}&limit=${limit}` });
55
+ }
56
+ session(toolkits, connectedAccounts) {
57
+ const toolkit = () => {
58
+ if (toolkits.length !== 1 || !toolkits[0]) throw new Error("Managed Composio sessions require exactly one toolkit for this operation.");
59
+ return toolkits[0];
60
+ };
61
+ return {
62
+ sessionId: "managed",
63
+ toolkits: async () => {
64
+ return { items: (await this.request({ path: "/connectors/composio/toolkits" })).items };
65
+ },
66
+ authorize: async (requestedToolkit, options) => {
67
+ return (await this.request({
68
+ path: "/connectors/composio/authorizations",
69
+ method: "POST",
70
+ body: {
71
+ toolkit: requestedToolkit,
72
+ alias: options?.alias
73
+ }
74
+ })).item;
75
+ },
76
+ search: async () => {
77
+ return (await this.request({ path: `/connectors/composio/toolkits/${encodeURIComponent(toolkit())}/tools` })).result;
78
+ },
79
+ execute: async (toolSlug, args = {}, options) => {
80
+ const selected = options?.account ?? connectedAccounts[toolkit()]?.[0];
81
+ return (await this.request({
82
+ path: "/connectors/composio/execute",
83
+ method: "POST",
84
+ body: {
85
+ toolkit: toolkit(),
86
+ toolSlug,
87
+ args,
88
+ ...selected ? { accountId: selected } : {}
89
+ },
90
+ headers: { "idempotency-key": randomUUID() }
91
+ })).result;
92
+ }
93
+ };
94
+ }
95
+ async request(input) {
96
+ const accessToken = await this.credentials.resolveApiKey("xopc-cloud");
97
+ if (!accessToken) throw new ManagedComposioError("Sign in to XOPC Cloud to use managed app connections.", 401, "xopc_cloud_not_configured");
98
+ const response = await this.fetchImpl(`${this.routerUrl}${input.path}`, {
99
+ method: input.method ?? "GET",
100
+ headers: {
101
+ authorization: `Bearer ${accessToken}`,
102
+ accept: "application/json",
103
+ ...input.body === void 0 ? {} : { "content-type": "application/json" },
104
+ ...input.headers
105
+ },
106
+ ...input.body === void 0 ? {} : { body: JSON.stringify(input.body) },
107
+ signal: AbortSignal.timeout(6e4)
108
+ });
109
+ const body = await response.json().catch(() => null);
110
+ if (!response.ok) {
111
+ const code = typeof body?.error?.code === "string" ? body.error.code : void 0;
112
+ const fallback = response.status === 403 && code === "insufficient_scope" ? "Reconnect XOPC Cloud to grant app connection permissions." : `Managed Composio request failed (${response.status})`;
113
+ throw new ManagedComposioError(typeof body?.error?.message === "string" ? body.error.message : fallback, response.status, code);
114
+ }
115
+ return body;
116
+ }
117
+ };
118
+ async function inspectManagedComposioStatus(options = {}) {
119
+ try {
120
+ const status = await new ManagedComposioClient(options).status();
121
+ return {
122
+ configured: status.configured,
123
+ mode: "managed",
124
+ ...!status.configured ? { reason: "service_unavailable" } : {}
125
+ };
126
+ } catch (error) {
127
+ return {
128
+ configured: false,
129
+ mode: "managed",
130
+ reason: error instanceof ManagedComposioError && error.code === "insufficient_scope" ? "reauthorization_required" : error instanceof ManagedComposioError && error.status === 401 ? "signin_required" : "service_unavailable"
131
+ };
132
+ }
133
+ }
134
+ //#endregion
135
+ export { ManagedComposioClient, inspectManagedComposioStatus };
@@ -0,0 +1,41 @@
1
+ import type { Config } from '../config/schema.js';
2
+ type ManagedEvent = {
3
+ sequence: number;
4
+ id: string;
5
+ type: string;
6
+ toolkit?: string;
7
+ connectionId?: string;
8
+ payload: unknown;
9
+ createdAt: string;
10
+ };
11
+ type ManagedEventClient = {
12
+ events(after?: number, limit?: number): Promise<{
13
+ items: ManagedEvent[];
14
+ nextCursor: number;
15
+ }>;
16
+ };
17
+ export declare class ManagedComposioEventPoller {
18
+ private readonly input;
19
+ private timer?;
20
+ private cursor;
21
+ private syncing?;
22
+ constructor(input: {
23
+ getConfig: () => Config;
24
+ triggerAutomation: (event: {
25
+ type: string;
26
+ source: string;
27
+ payload: Record<string, unknown>;
28
+ }) => Promise<unknown>;
29
+ requestLearning: (toolkit: string) => void;
30
+ setLearningPaused: (connectionId: string, paused: boolean) => void;
31
+ client?: ManagedEventClient;
32
+ hasByok?: () => Promise<boolean>;
33
+ intervalMs?: number;
34
+ });
35
+ start(): void;
36
+ stop(): void;
37
+ sync(): Promise<void>;
38
+ private runSync;
39
+ private process;
40
+ }
41
+ export {};
@@ -0,0 +1,105 @@
1
+ import { createLogger } from "../utils/logger/index.js";
2
+ import { init_logger } from "../utils/logger.js";
3
+ import { claimConnectorWebhookDelivery, completeConnectorWebhookDelivery, releaseConnectorWebhookDelivery } from "../storage/sqlite/connector-repository.js";
4
+ import "../storage/sqlite/index.js";
5
+ import { resolveComposioApiKey } from "./composio-sessions.js";
6
+ import { ManagedComposioClient } from "./composio-managed-client.js";
7
+ import { appendComposioTriggerEvent, applyComposioConnectionLifecycleEvent, normalizeComposioTriggerPayload } from "./composio-triggers.js";
8
+ import { createHash } from "node:crypto";
9
+ //#region src/connectors/composio-managed-events.ts
10
+ init_logger();
11
+ const log = createLogger("Connectors:ComposioManagedEvents");
12
+ function hasInstalledComposioToolkit(config) {
13
+ return Object.values(config.connectors?.instances ?? {}).some((value) => {
14
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
15
+ const runtime = value.runtime;
16
+ return Boolean(runtime && typeof runtime === "object" && !Array.isArray(runtime) && runtime.type === "composio" && runtime.role === "toolkit");
17
+ });
18
+ }
19
+ var ManagedComposioEventPoller = class {
20
+ timer;
21
+ cursor = 0;
22
+ syncing;
23
+ constructor(input) {
24
+ this.input = input;
25
+ }
26
+ start() {
27
+ if (this.timer) return;
28
+ this.sync().catch(() => {});
29
+ this.timer = setInterval(() => {
30
+ this.sync().catch(() => {});
31
+ }, this.input.intervalMs ?? 15e3);
32
+ this.timer.unref?.();
33
+ }
34
+ stop() {
35
+ if (this.timer) clearInterval(this.timer);
36
+ this.timer = void 0;
37
+ }
38
+ sync() {
39
+ this.syncing ??= this.runSync().finally(() => {
40
+ this.syncing = void 0;
41
+ });
42
+ return this.syncing;
43
+ }
44
+ async runSync() {
45
+ const config = this.input.getConfig();
46
+ const hasByok = this.input.hasByok ?? (async () => Boolean(await resolveComposioApiKey()));
47
+ if (!hasInstalledComposioToolkit(config) || await hasByok()) return;
48
+ const client = this.input.client ?? new ManagedComposioClient();
49
+ try {
50
+ for (let page = 0; page < 20; page += 1) {
51
+ const response = await client.events(this.cursor, 100);
52
+ for (const event of response.items) await this.process(config, event);
53
+ const next = Math.max(this.cursor, response.nextCursor);
54
+ if (next === this.cursor || response.items.length === 0) break;
55
+ this.cursor = next;
56
+ if (response.items.length < 100) break;
57
+ }
58
+ } catch (error) {
59
+ log.debug({
60
+ err: error,
61
+ phase: "event_poll"
62
+ }, "Managed Composio event poll skipped");
63
+ throw error;
64
+ }
65
+ }
66
+ async process(config, event) {
67
+ const payload = event.payload && typeof event.payload === "object" && !Array.isArray(event.payload) ? {
68
+ ...event.payload,
69
+ id: event.id
70
+ } : {
71
+ id: event.id,
72
+ type: event.type,
73
+ data: event.payload
74
+ };
75
+ const hash = createHash("sha256").update(JSON.stringify(payload)).digest("hex");
76
+ if (claimConnectorWebhookDelivery({
77
+ id: event.id,
78
+ provider: "composio",
79
+ payloadHash: hash
80
+ }) !== "claimed") return;
81
+ try {
82
+ const normalized = normalizeComposioTriggerPayload(payload, event.id);
83
+ const inactiveConnectionId = applyComposioConnectionLifecycleEvent(payload);
84
+ if (inactiveConnectionId) this.input.setLearningPaused(inactiveConnectionId, true);
85
+ await appendComposioTriggerEvent(config, payload);
86
+ const toolkit = normalized.toolkit ?? event.toolkit;
87
+ if (toolkit) this.input.requestLearning(toolkit);
88
+ await this.input.triggerAutomation({
89
+ type: `connector.${normalized.trigger ?? normalized.type}`,
90
+ source: toolkit ? `composio:${toolkit}` : "composio",
91
+ payload: {
92
+ ...normalized.data,
93
+ connectorId: toolkit ? `composio-${toolkit}` : "composio",
94
+ webhookId: event.id
95
+ }
96
+ });
97
+ completeConnectorWebhookDelivery(event.id);
98
+ } catch (error) {
99
+ releaseConnectorWebhookDelivery(event.id, error);
100
+ throw error;
101
+ }
102
+ }
103
+ };
104
+ //#endregion
105
+ export { ManagedComposioEventPoller };
@@ -2,7 +2,7 @@ import type { ToolRouterCreateSessionConfig } from '@composio/core';
2
2
  import { CredentialResolver } from '../auth/credentials.js';
3
3
  import type { ConnectorActionMetadata, ConnectorConnection, ConnectorInstallationPolicy } from './types.js';
4
4
  export declare function resolveComposioApiKey(resolver?: CredentialResolver): Promise<string | null>;
5
- export declare function assertComposioApiKeyConfigured(resolver?: CredentialResolver): Promise<string>;
5
+ export declare function assertComposioAccessConfigured(resolver?: CredentialResolver): Promise<'byok' | 'managed'>;
6
6
  export type ComposioToolkitCatalogItem = {
7
7
  slug: string;
8
8
  name: string;
@@ -72,6 +72,7 @@ export type ComposioSessionLike = {
72
72
  }): Promise<unknown>;
73
73
  };
74
74
  export type ComposioSessionsClient = {
75
+ mode?: 'managed' | 'byok';
75
76
  sessions: {
76
77
  create(userId: string, config?: ToolRouterCreateSessionConfig): Promise<ComposioSessionLike>;
77
78
  };
@@ -17,10 +17,10 @@ const COMPOSIO_API_KEY_PROVIDER = "connector-composio-api-key";
17
17
  async function resolveComposioApiKey(resolver = new CredentialResolver()) {
18
18
  return (await resolver.resolveApiKey(COMPOSIO_API_KEY_PROVIDER).catch(() => void 0))?.trim() || process.env.XOPC_COMPOSIO_API_KEY?.trim() || process.env.COMPOSIO_API_KEY?.trim() || null;
19
19
  }
20
- async function assertComposioApiKeyConfigured(resolver = new CredentialResolver()) {
21
- const apiKey = await resolveComposioApiKey(resolver);
22
- if (!apiKey) throw new Error("Composio API key is not configured. Install the \"Composio API Key\" connector first.");
23
- return apiKey;
20
+ async function assertComposioAccessConfigured(resolver = new CredentialResolver()) {
21
+ if (await resolveComposioApiKey(resolver)) return "byok";
22
+ if ((await resolver.resolveApiKey("xopc-cloud").catch(() => null))?.trim()) return "managed";
23
+ throw new Error("Composio API key is not configured and XOPC Cloud is not signed in. Install the \"Composio API Key\" connector first or sign in to XOPC Cloud.");
24
24
  }
25
25
  function stableHash(value) {
26
26
  return createHash("sha256").update(value).digest("hex").slice(0, 24);
@@ -91,7 +91,11 @@ var ComposioSessionsAdapter = class {
91
91
  }
92
92
  const resolver = options.resolver ?? new CredentialResolver();
93
93
  this.createClient = async () => {
94
- const apiKey = await assertComposioApiKeyConfigured(resolver);
94
+ const apiKey = await resolveComposioApiKey(resolver);
95
+ if (!apiKey) {
96
+ const { ManagedComposioClient } = await import("./composio-managed-client.js");
97
+ return new ManagedComposioClient();
98
+ }
95
99
  let Composio;
96
100
  let PiProvider;
97
101
  try {
@@ -99,7 +103,7 @@ var ComposioSessionsAdapter = class {
99
103
  } catch (cause) {
100
104
  throw new Error("The xopc installation is missing the bundled Composio runtime. Reinstall @xopcai/xopc and restart the gateway.", { cause });
101
105
  }
102
- return new Composio({
106
+ const client = new Composio({
103
107
  apiKey,
104
108
  baseURL: process.env.XOPC_COMPOSIO_BASE_URL?.trim() || void 0,
105
109
  allowTracking: false,
@@ -109,6 +113,8 @@ var ComposioSessionsAdapter = class {
109
113
  provider: new PiProvider(),
110
114
  host: "xopc"
111
115
  });
116
+ client.mode = "byok";
117
+ return client;
112
118
  };
113
119
  }
114
120
  async createSession(context) {
@@ -375,4 +381,4 @@ var ComposioSessionsAdapter = class {
375
381
  }
376
382
  };
377
383
  //#endregion
378
- export { ComposioSessionsAdapter, assertComposioApiKeyConfigured, createComposioPrincipalId, resolveComposioApiKey };
384
+ export { ComposioSessionsAdapter, assertComposioAccessConfigured, createComposioPrincipalId, resolveComposioApiKey };
@@ -2,7 +2,7 @@ import { getConnectorConnection, getConnectorInstallation, listConnectorConnecti
2
2
  import { getConnectorAccount, refreshConnectorAccountCurrent } from "../storage/sqlite/connector-account-repository.js";
3
3
  import { CredentialResolver, init_credentials } from "../auth/credentials.js";
4
4
  import { connectorIdentityKey } from "./connector-identity.js";
5
- import { ComposioSessionsAdapter } from "./composio-sessions.js";
5
+ import { ComposioSessionsAdapter, assertComposioAccessConfigured } from "./composio-sessions.js";
6
6
  import { COMPOSIO_AGENT_READY_TOOLKITS, COMPOSIO_TOOLKIT_DISPLAY_NAMES, connectorDefinitionFromComposioToolkit } from "./composio-catalog.js";
7
7
  import { consumeConnectorSetupSecretRef } from "./setup-secrets.js";
8
8
  //#region src/connectors/composio.ts
@@ -370,6 +370,7 @@ async function listComposioConnections(resolver = new CredentialResolver()) {
370
370
  async function inspectComposioConnectorHealth(toolkit, resolver = new CredentialResolver()) {
371
371
  const normalizedToolkit = normalizeToolkit(toolkit);
372
372
  try {
373
+ await assertComposioAccessConfigured(resolver);
373
374
  const connections = (await listComposioConnections(resolver)).filter((connection) => connection.toolkit.toLowerCase() === normalizedToolkit);
374
375
  const byAccount = /* @__PURE__ */ new Map();
375
376
  for (const connection of connections) {
@@ -1,11 +1,13 @@
1
+ import { createLogger } from "../utils/logger/index.js";
2
+ import { init_logger } from "../utils/logger.js";
1
3
  import { getConnectorInstallation, listConnectorConnections } from "../storage/sqlite/connector-repository.js";
2
4
  import "../storage/sqlite/index.js";
3
5
  import { ComposioSessionsAdapter } from "./composio-sessions.js";
4
6
  import { decodeConnectedSourceCursor, encodeConnectedSourceCursor } from "./connected-source-cursor.js";
5
7
  import { scopeForComposioAction } from "./composio.js";
6
8
  import { getConnectorDefinition } from "./catalog.js";
7
- import { getWorkspacePath } from "../config/workspace-path-helpers.js";
8
9
  import { getConnectorInstance } from "./instances.js";
10
+ import { getWorkspacePath } from "../config/workspace-path-helpers.js";
9
11
  import { KnowledgeIngestionService } from "../knowledge/ingestion-service.js";
10
12
  import { ConnectedKnowledgePipeline } from "../knowledge/connected-knowledge-pipeline.js";
11
13
  import { LocalFolderKnowledgeSourceAdapter } from "../knowledge/local-folder-adapter.js";
@@ -14,6 +16,8 @@ import { normalizeConnectedSourceResult } from "./connected-source-normalizers.j
14
16
  import { sanitizeConnectedSourceValue } from "./connected-source-sanitization.js";
15
17
  import { createHash } from "node:crypto";
16
18
  //#region src/connectors/connected-source-ingestion.ts
19
+ init_logger();
20
+ const log = createLogger("ConnectedSourceIngestion");
17
21
  const COMPOSIO_CONNECTED_SOURCE_TOOLKITS = new Set([
18
22
  "gmail",
19
23
  "googlecalendar",
@@ -99,6 +103,17 @@ function paginationValue(result, ...keys) {
99
103
  if (typeof value === "string" && value.trim()) return value.trim();
100
104
  }
101
105
  }
106
+ function isPayloadTooLargeError(error) {
107
+ const details = asRecord(error);
108
+ const status = details?.status ?? details?.statusCode;
109
+ const code = details?.code;
110
+ const message = error instanceof Error ? error.message : String(error);
111
+ return String(status) === "413" || String(code) === "4345" || /\b413\b|ToolRouterV2_PayloadTooLarge|payload is too large/i.test(message);
112
+ }
113
+ function maxResultsValue(args) {
114
+ const value = args.max_results;
115
+ return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : void 0;
116
+ }
102
117
  function resultToSourceItems(input) {
103
118
  return normalizeConnectedSourceResult(input).slice(0, 200).map((entity) => {
104
119
  const record = entity.value;
@@ -142,6 +157,7 @@ function resultToSourceItems(input) {
142
157
  }
143
158
  var ComposioKnowledgeSourceAdapter = class {
144
159
  kind = "composio";
160
+ adaptiveMaxResults;
145
161
  constructor(input) {
146
162
  this.input = input;
147
163
  }
@@ -149,32 +165,58 @@ var ComposioKnowledgeSourceAdapter = class {
149
165
  const cursor = decodeConnectedSourceCursor(pull.cursor);
150
166
  const scanStartedAt = cursor?.scanStartedAt ?? (/* @__PURE__ */ new Date()).toISOString();
151
167
  const warnings = pull.cursor && !cursor ? ["Stored connected-source cursor was invalid and was replaced."] : [];
152
- const execute = (cursorValue) => this.input.adapter.executeWithPolicy({
153
- context: {
154
- principalId: "local-owner",
155
- toolkits: [this.input.toolkit]
156
- },
157
- installation: {
158
- ...this.input.installation,
159
- maxScope: "read",
160
- confirmationPolicy: "never"
161
- },
162
- connection: this.input.connection,
163
- agentId: this.input.agentId,
164
- action: {
165
- connectorId: this.input.connectorId,
166
- actionId: this.input.actionId,
167
- toolkit: this.input.toolkit,
168
- scope: "read",
169
- curated: true,
170
- cachedAt: (/* @__PURE__ */ new Date()).toISOString()
171
- },
172
- args: this.input.buildArguments?.({
168
+ const execute = async (cursorValue) => {
169
+ const configuredArgs = this.input.buildArguments?.({
173
170
  ...pull,
174
171
  cursor: cursorValue
175
- }) ?? this.input.arguments,
176
- confirmed: true
177
- });
172
+ }) ?? this.input.arguments;
173
+ const configuredMaxResults = maxResultsValue(configuredArgs);
174
+ let args = this.adaptiveMaxResults && configuredMaxResults && configuredMaxResults > this.adaptiveMaxResults ? {
175
+ ...configuredArgs,
176
+ max_results: this.adaptiveMaxResults
177
+ } : configuredArgs;
178
+ for (;;) try {
179
+ return await this.input.adapter.executeWithPolicy({
180
+ context: {
181
+ principalId: "local-owner",
182
+ toolkits: [this.input.toolkit]
183
+ },
184
+ installation: {
185
+ ...this.input.installation,
186
+ maxScope: "read",
187
+ confirmationPolicy: "never"
188
+ },
189
+ connection: this.input.connection,
190
+ agentId: this.input.agentId,
191
+ action: {
192
+ connectorId: this.input.connectorId,
193
+ actionId: this.input.actionId,
194
+ toolkit: this.input.toolkit,
195
+ scope: "read",
196
+ curated: true,
197
+ cachedAt: (/* @__PURE__ */ new Date()).toISOString()
198
+ },
199
+ args,
200
+ confirmed: true
201
+ });
202
+ } catch (error) {
203
+ const currentMaxResults = maxResultsValue(args);
204
+ if (!isPayloadTooLargeError(error) || !currentMaxResults || currentMaxResults <= 1) throw error;
205
+ const reducedMaxResults = Math.max(1, Math.floor(currentMaxResults / 2));
206
+ this.adaptiveMaxResults = reducedMaxResults;
207
+ log.info({
208
+ connectorId: this.input.connectorId,
209
+ actionId: this.input.actionId,
210
+ previousMaxResults: currentMaxResults,
211
+ maxResults: reducedMaxResults,
212
+ phase: "payload_too_large_retry"
213
+ }, `Retrying connector action with page size ${reducedMaxResults}`);
214
+ args = {
215
+ ...args,
216
+ max_results: reducedMaxResults
217
+ };
218
+ }
219
+ };
178
220
  let execution;
179
221
  try {
180
222
  execution = await execute(pull.cursor);
@@ -1,6 +1,6 @@
1
- import { getWorkspacePath } from "../config/workspace-path-helpers.js";
2
1
  import { materializeConnectorMcpServer } from "./materialize.js";
3
2
  import { getConnectorInstance } from "./instances.js";
3
+ import { getWorkspacePath } from "../config/workspace-path-helpers.js";
4
4
  import { listBundleMcpServerCapabilitiesForGateway } from "../agent/mcp/bundle-mcp-gateway.js";
5
5
  //#region src/connectors/health.ts
6
6
  function classifyConnectorHealthError(error) {
@@ -44,6 +44,8 @@ const PLANS = {
44
44
  kind: "activity",
45
45
  arguments: {
46
46
  max_results: 100,
47
+ include_payload: false,
48
+ verbose: false,
47
49
  query: "newer_than:30d -in:spam -in:trash"
48
50
  }
49
51
  }],
@@ -1,7 +1,7 @@
1
1
  import { isXopcDatabaseOpen } from "../storage/sqlite/connection.js";
2
2
  import { deleteConnectorInstallation, getConnectorInstallation, upsertConnectorInstallation } from "../storage/sqlite/connector-repository.js";
3
3
  import "../storage/sqlite/index.js";
4
- import { assertComposioApiKeyConfigured } from "./composio-sessions.js";
4
+ import { assertComposioAccessConfigured } from "./composio-sessions.js";
5
5
  import { saveComposioApiKey } from "./composio.js";
6
6
  import { saveConnectorSecrets } from "./secret-store.js";
7
7
  import { isManagedConnectorServer, materializeConnectorMcpServer } from "./materialize.js";
@@ -106,7 +106,7 @@ registerConnectorRuntimeAdapter({
106
106
  async install({ config, definition, input, resolver }) {
107
107
  if (definition.runtime.type !== "composio") throw new Error(`Invalid Composio connector definition: ${definition.id}`);
108
108
  if (definition.runtime.role === "credential") await saveComposioApiKey(input, resolver);
109
- if (definition.runtime.role === "toolkit") await assertComposioApiKeyConfigured(resolver);
109
+ if (definition.runtime.role === "toolkit") await assertComposioAccessConfigured(resolver);
110
110
  const instance = installRecord(config, definition, definition.runtime.role === "toolkit" ? { scope: "read" } : {}, definition.runtime.role === "toolkit" ? { config: input.config ?? {} } : {});
111
111
  if (definition.runtime.role === "toolkit" && isXopcDatabaseOpen()) {
112
112
  const installationId = `${definition.id}-local-owner`;
@@ -6,7 +6,7 @@ import { isSTTAvailable } from "../voice/stt/availability.js";
6
6
  import { mergeSttConfigFromAppConfig } from "../voice/stt/config.js";
7
7
  import "../voice/stt/index.js";
8
8
  import { getDiscussionCapture, listDiscussionCaptures, listDiscussionTranscriptSegments, updateDiscussionCapture } from "./repository.js";
9
- import { appendTranscriptWithoutOverlap, assembleDiscussionTranscript } from "./transcript.js";
9
+ import { appendSequentialTranscript, assembleDiscussionTranscript } from "./transcript.js";
10
10
  import { createHash } from "node:crypto";
11
11
  //#region src/discussions/sealer.ts
12
12
  init_logger();
@@ -96,7 +96,7 @@ var DiscussionSealer = class {
96
96
  mime: "audio/wav",
97
97
  fileName: `discussion-recovery-${index}.wav`
98
98
  });
99
- text = appendTranscriptWithoutOverlap(text, result.text);
99
+ text = appendSequentialTranscript(text, result.text);
100
100
  language ??= result.language;
101
101
  });
102
102
  return {
@@ -153,13 +153,16 @@ var DiscussionService = class {
153
153
  uploadSegment(input) {
154
154
  const capture = getDiscussionCapture(input.discussionId);
155
155
  if (!capture) throw new DiscussionServiceError("not_found", "Discussion not found");
156
- if (capture.status !== "recording" && capture.status !== "stopping") throw new DiscussionServiceError("conflict", "Discussion no longer accepts transcript segments");
156
+ const acceptsSegments = capture.status === "recording" || capture.status === "stopping";
157
+ const originalRecordingSupersedesSegment = capture.audioAttachmentId && (capture.status === "sealing" || capture.status === "organizing" || capture.status === "completed");
158
+ if (!acceptsSegments && !originalRecordingSupersedesSegment) throw new DiscussionServiceError("conflict", "Discussion no longer accepts transcript segments");
157
159
  if (!Number.isInteger(input.sequence) || input.sequence < 0 || input.sequence > 2e3) throw new DiscussionServiceError("invalid_input", "Invalid segment sequence");
158
160
  if (input.file.mimeType !== "audio/wav" && input.file.mimeType !== "audio/x-wav") throw new DiscussionServiceError("invalid_input", "Live transcript segments must be WAV audio");
159
161
  if (input.file.buffer.length === 0 || input.file.buffer.length > 2097152) throw new DiscussionServiceError("invalid_input", "Live transcript segment is empty or too large");
160
162
  if (!Number.isFinite(input.startedAtMs) || !Number.isFinite(input.endedAtMs) || input.startedAtMs < 0 || input.endedAtMs <= input.startedAtMs || input.endedAtMs - input.startedAtMs > 25e3) throw new DiscussionServiceError("invalid_input", "Invalid live transcript segment timing");
161
163
  const actualSha256 = createHash("sha256").update(input.file.buffer).digest("hex");
162
164
  if (input.sha256 !== actualSha256) throw new DiscussionServiceError("invalid_input", "Segment checksum mismatch");
165
+ if (originalRecordingSupersedesSegment) return this.transcript(input.discussionId);
163
166
  const existing = getDiscussionTranscriptSegment(input.discussionId, input.sequence);
164
167
  if (existing && existing.audioSha256 !== actualSha256) throw new DiscussionServiceError("conflict", "Segment sequence already contains different audio");
165
168
  if (!existing) {
@@ -219,7 +222,8 @@ var DiscussionService = class {
219
222
  name: file.name.trim().slice(0, 200) || `discussion-${id}.webm`,
220
223
  buffer: file.buffer,
221
224
  mimeType: file.mimeType,
222
- duration: Math.round(durationMs / 1e3)
225
+ duration: Math.round(durationMs / 1e3),
226
+ retainWithoutReference: true
223
227
  });
224
228
  if (!attachment) throw new DiscussionServiceError("not_found", "Discussion note not found");
225
229
  try {
@@ -1,3 +1,5 @@
1
1
  import type { DiscussionTranscriptSegment } from './types.js';
2
+ /** Joins transcripts from adjacent audio chunks that have no audio overlap. */
3
+ export declare function appendSequentialTranscript(existing: string, next: string): string;
2
4
  export declare function appendTranscriptWithoutOverlap(existing: string, next: string): string;
3
5
  export declare function assembleDiscussionTranscript(segments: DiscussionTranscriptSegment[]): string;
@@ -15,7 +15,20 @@ function searchableCharacters(value) {
15
15
  };
16
16
  }
17
17
  function joinOverlap(left, remainder) {
18
- return `${left}${/[\p{P}\p{S}]$/u.test(left) ? remainder.replace(/^[\s\p{P}\p{S}]+/u, "") : remainder}`.trim();
18
+ const next = /\p{P}$/u.test(left) ? remainder.replace(/^\p{P}+/u, "") : remainder;
19
+ if (!next || /^\s/u.test(next)) return `${left}${next}`.trim();
20
+ const leftCharacter = Array.from(left).findLast((character) => /[\p{L}\p{N}\p{S}]/u.test(character));
21
+ const rightCharacter = Array.from(next).find((character) => /[\p{L}\p{N}\p{S}]/u.test(character));
22
+ const compactScript = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]/u;
23
+ return `${left}${leftCharacter && rightCharacter && !compactScript.test(leftCharacter) && !compactScript.test(rightCharacter) ? " " : ""}${next}`.trim();
24
+ }
25
+ /** Joins transcripts from adjacent audio chunks that have no audio overlap. */
26
+ function appendSequentialTranscript(existing, next) {
27
+ const left = existing.trim();
28
+ const right = next.trim();
29
+ if (!left) return right;
30
+ if (!right) return left;
31
+ return `${left}\n${right}`;
19
32
  }
20
33
  function appendTranscriptWithoutOverlap(existing, next) {
21
34
  const left = existing.trim();
@@ -32,10 +45,10 @@ function appendTranscriptWithoutOverlap(existing, next) {
32
45
  const sourceEnd = rightSearchable.sourceEnds[size - 1];
33
46
  return joinOverlap(left, right.slice(sourceEnd));
34
47
  }
35
- return `${left}\n${right}`;
48
+ return appendSequentialTranscript(left, right);
36
49
  }
37
50
  function assembleDiscussionTranscript(segments) {
38
51
  return segments.reduce((text, segment) => appendTranscriptWithoutOverlap(text, segment.displayText ?? ""), "");
39
52
  }
40
53
  //#endregion
41
- export { appendTranscriptWithoutOverlap, assembleDiscussionTranscript };
54
+ export { appendSequentialTranscript, appendTranscriptWithoutOverlap, assembleDiscussionTranscript };
@@ -3,6 +3,16 @@
3
3
  * Supports installing from npm packages, local directories, and xopc-store zips
4
4
  * Supports three-tier storage: workspace, global, bundled
5
5
  */
6
+ export type ValidatedNpmPackageSpec = {
7
+ ok: true;
8
+ packageName: string;
9
+ version?: string;
10
+ } | {
11
+ ok: false;
12
+ error: string;
13
+ };
14
+ /** Accept registry package names with an optional exact semver; reject URLs, paths, tags, and ranges. */
15
+ export declare function validateNpmPackageSpec(packageSpec: string): ValidatedNpmPackageSpec;
6
16
  export interface InstallOptions {
7
17
  source: 'npm' | 'local';
8
18
  targetDir: string;