@xopcai/xopc 0.0.389 → 0.0.390

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 (302) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/src/plugin.js +1 -1
  3. package/dist/extensions/telegram/xopc.extension.json +1 -1
  4. package/dist/gateway/static/root/assets/{activity-store-dvik6t7Z.js → activity-store-DGMAYkw8.js} +1 -1
  5. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-bWMd5TDC.js → agent-avatar-dicebear-B4AsZzJR.js} +1 -1
  6. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-9NUY1sO3.js +1 -0
  7. package/dist/gateway/static/root/assets/agent-plugin-dialog-CNc6ntzP.js +1 -0
  8. package/dist/gateway/static/root/assets/agents-QNY9Vkrf.js +77 -0
  9. package/dist/gateway/static/root/assets/{agents-admin-api-BlNGyXpm.js → agents-admin-api-DxdaiFWn.js} +1 -1
  10. package/dist/gateway/static/root/assets/app-management-settings-panel-DHRfLkYD.js +1 -0
  11. package/dist/gateway/static/root/assets/{appearance-settings-CUAdx44v.js → appearance-settings-DtKSapgb.js} +1 -1
  12. package/dist/gateway/static/root/assets/{apps-page-D5zDB6gp.js → apps-page-B9kuRt_z.js} +1 -1
  13. package/dist/gateway/static/root/assets/{archive-plugin-Du6dJNcl.js → archive-plugin-AgySTXp_.js} +1 -1
  14. package/dist/gateway/static/root/assets/{automations-page-BO8Ig5Z4.js → automations-page-D1o7ZtUW.js} +1 -1
  15. package/dist/gateway/static/root/assets/automations-workspace-BJenz0P1.js +6 -0
  16. package/dist/gateway/static/root/assets/{binary-plugins-D7VJjwnr.js → binary-plugins-A1AXOsO6.js} +1 -1
  17. package/dist/gateway/static/root/assets/{block-editor-CaJlWTAn.js → block-editor-DUNLkLKF.js} +3 -3
  18. package/dist/gateway/static/root/assets/{browser-automation-inputs-iyMBJmQX.js → browser-automation-inputs-BvUC6OiW.js} +1 -1
  19. package/dist/gateway/static/root/assets/browser-automations-page-Dq2LlVMh.js +3 -0
  20. package/dist/gateway/static/root/assets/browser-settings-page-BOZ-1g51.js +3 -0
  21. package/dist/gateway/static/root/assets/{capabilities-MCKRMZDK.js → capabilities-BkCutK0V.js} +1 -1
  22. package/dist/gateway/static/root/assets/{capabilities-CEH1AnXc.js → capabilities-D61uSJPy.js} +1 -1
  23. package/dist/gateway/static/root/assets/capabilities-page-BDP6gzlv.js +2 -0
  24. package/dist/gateway/static/root/assets/capabilities-settings-panel-D6PL3Mfl.js +8 -0
  25. package/dist/gateway/static/root/assets/{capability-header-actions-BIA0Lwt5.js → capability-header-actions-D9uGs4Pw.js} +1 -1
  26. package/dist/gateway/static/root/assets/channels-xb7n8rwF.js +1 -0
  27. package/dist/gateway/static/root/assets/chat-terminal-dock-Dgn09YDs.js +36 -0
  28. package/dist/gateway/static/root/assets/{computer-settings-page-DvY3zgyY.js → computer-settings-page-C66P4ifT.js} +1 -1
  29. package/dist/gateway/static/root/assets/{connector-service-page-St2-Fj3y.js → connector-service-page-Dp35XdYf.js} +1 -1
  30. package/dist/gateway/static/root/assets/connectors-page-BHcRxYib.js +1 -0
  31. package/dist/gateway/static/root/assets/{date-picker-C0-D80ny.js → date-picker-CddHY982.js} +1 -1
  32. package/dist/gateway/static/root/assets/{dependency-picker-CNd7mwMU.js → dependency-picker-Ob6BZTqv.js} +1 -1
  33. package/dist/gateway/static/root/assets/{desktop-pet-C-2wDANn.js → desktop-pet-dmwCV-I4.js} +1 -1
  34. package/dist/gateway/static/root/assets/{desktop-pet-settings-DyhxLrdJ.js → desktop-pet-settings-B-TBkZAZ.js} +1 -1
  35. package/dist/gateway/static/root/assets/device-pairing-wizard-SWHwRgG3.js +1 -0
  36. package/dist/gateway/static/root/assets/{directory-picker-path-field-CNivVIPT.js → directory-picker-path-field-6VZa4fT1.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-debug-page-CGYO3JPw.js → extension-debug-page-C0_njMva.js} +1 -1
  38. package/dist/gateway/static/root/assets/{extension-page-Dc51ALAg.js → extension-page-BeBLMFmW.js} +1 -1
  39. package/dist/gateway/static/root/assets/{extension-provider-BXPILdlw.js → extension-provider-DWI0KAKT.js} +1 -1
  40. package/dist/gateway/static/root/assets/extension-settings-page-BiLUwoKx.js +1 -0
  41. package/dist/gateway/static/root/assets/{gateway-config-swr-Bc2MytsF.js → gateway-config-swr-CmYcOqhb.js} +1 -1
  42. package/dist/gateway/static/root/assets/{gateway-realtime-BFK-vlME.js → gateway-realtime-Ci1Jst5g.js} +1 -1
  43. package/dist/gateway/static/root/assets/gateway-realtime-store-BMUiUQMk.js +1 -0
  44. package/dist/gateway/static/root/assets/gateway-settings-CzWT_v09.js +1 -0
  45. package/dist/gateway/static/root/assets/{gateway-startup-retry-BDPMttPx.js → gateway-startup-retry-C-BG5M7H.js} +1 -1
  46. package/dist/gateway/static/root/assets/{highlighted-body-KQOG7T2V-DAlRGMge.js → highlighted-body-KQOG7T2V-CsA7lCVc.js} +1 -1
  47. package/dist/gateway/static/root/assets/home-page-BeXJfxsg.js +2 -0
  48. package/dist/gateway/static/root/assets/image-generation-api-B_DqCwtV.js +1 -0
  49. package/dist/gateway/static/root/assets/imports-page-oAvAF9QS.js +1 -0
  50. package/dist/gateway/static/root/assets/index-W9ls-0Yd.css +1 -0
  51. package/dist/gateway/static/root/assets/index-xTL-vb51.js +260 -0
  52. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BYYC9Qmw.js → keyboard-shortcuts-settings--MjYe-Pb.js} +1 -1
  53. package/dist/gateway/static/root/assets/{local-app-workbench-page-BKZfn-MS.js → local-app-workbench-page-DL33dtd7.js} +1 -1
  54. package/dist/gateway/static/root/assets/{local-apps-page-BU8pUsVM.js → local-apps-page-DOa7mxjB.js} +1 -1
  55. package/dist/gateway/static/root/assets/{local-session-drafts-kFc_MAA9.js → local-session-drafts-DAtLkTPg.js} +1 -1
  56. package/dist/gateway/static/root/assets/{locale-store-Dr43FCty.js → locale-store-DMy9W6IG.js} +1 -1
  57. package/dist/gateway/static/root/assets/logs-page-C-GbTYsM.js +2 -0
  58. package/dist/gateway/static/root/assets/management-settings-C0TzuD3-.js +1 -0
  59. package/dist/gateway/static/root/assets/{markdown-view-CdKlPjJM.js → markdown-view-wyOHdXEg.js} +1 -1
  60. package/dist/gateway/static/root/assets/{media-plugins-DE9zt88i.js → media-plugins-Pb2zr_-L.js} +1 -1
  61. package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-BxyGGa4D.js +1 -0
  62. package/dist/gateway/static/root/assets/messages-O0BEUKnx.js +3 -0
  63. package/dist/gateway/static/root/assets/models-hub-cache-DdH1MODX.js +1 -0
  64. package/dist/gateway/static/root/assets/note-detail-panel-BFpEqskQ.js +5 -0
  65. package/dist/gateway/static/root/assets/{notes-api-BHouNL6-.js → notes-api-CYt2pGsm.js} +1 -1
  66. package/dist/gateway/static/root/assets/notes-page-h-qqFJ6Z.js +8 -0
  67. package/dist/gateway/static/root/assets/{page-context-capture-button-TQr8NnSc.js → page-context-capture-button-3uj5EcQC.js} +1 -1
  68. package/dist/gateway/static/root/assets/personal-page-BGyW6cdt.js +1 -0
  69. package/dist/gateway/static/root/assets/{product-open-page-BEl6syFp.js → product-open-page-hI13tPS1.js} +1 -1
  70. package/dist/gateway/static/root/assets/{product-preview-content-BxSHnbqz.js → product-preview-content-lT_in0-Q.js} +1 -1
  71. package/dist/gateway/static/root/assets/project-detail-page-Baj7fQ7N.js +1 -0
  72. package/dist/gateway/static/root/assets/projects-page-D7DyQFU3.js +1 -0
  73. package/dist/gateway/static/root/assets/{registry-api-BD5IgDOA.js → registry-api-CgQrCqL6.js} +1 -1
  74. package/dist/gateway/static/root/assets/remote-access-hub-DU_d93Tm.js +1 -0
  75. package/dist/gateway/static/root/assets/{runtime-tools-api-CjTRoQWT.js → runtime-tools-api-D12qVKeC.js} +1 -1
  76. package/dist/gateway/static/root/assets/runtime-tools-settings-panel-DOSPOfCU.js +1 -0
  77. package/dist/gateway/static/root/assets/scenes-page-swyUIF5A.js +2 -0
  78. package/dist/gateway/static/root/assets/{schema-form-ByG-R6N2.js → schema-form-CwOFgsyh.js} +1 -1
  79. package/dist/gateway/static/root/assets/{send-session-input-UAVStisp.js → send-session-input-nH8Cw0US.js} +1 -1
  80. package/dist/gateway/static/root/assets/{session-api-DvgEiNRS.js → session-api-B9HrwF-c.js} +1 -1
  81. package/dist/gateway/static/root/assets/{session-manager-BOb1tC_Z.js → session-manager-aXqXuqDX.js} +1 -1
  82. package/dist/gateway/static/root/assets/sessions-page-CI_PJmlX.js +1 -0
  83. package/dist/gateway/static/root/assets/settings-advanced-gate-DCVaeBLW.js +1 -0
  84. package/dist/gateway/static/root/assets/{settings-page-C1e9m23j.js → settings-page-BN70wE6R.js} +1 -1
  85. package/dist/gateway/static/root/assets/setup-status-panel-CHzcVRi-.js +1 -0
  86. package/dist/gateway/static/root/assets/{share-link-dialog-kE_6v5Dp.js → share-link-dialog-B1TDyhPt.js} +1 -1
  87. package/dist/gateway/static/root/assets/{share-preview-page-BT-_yR1h.js → share-preview-page-Br-eAZaP.js} +1 -1
  88. package/dist/gateway/static/root/assets/{shares-api-Dg_SqHQE.js → shares-api-Bl1ZBh5S.js} +1 -1
  89. package/dist/gateway/static/root/assets/shares-settings-jgCC_E4Y.js +1 -0
  90. package/dist/gateway/static/root/assets/{skill-api-BslUYMnX.js → skill-api-ClUw3SRC.js} +1 -1
  91. package/dist/gateway/static/root/assets/{skill-reload-api-BQ2rTOP1.js → skill-reload-api--1BfIPzb.js} +1 -1
  92. package/dist/gateway/static/root/assets/skills-page-C9oRZSuL.js +2 -0
  93. package/dist/gateway/static/root/assets/{system-settings-panel-GpbPfWwo.js → system-settings-panel-tWrqu7ai.js} +1 -1
  94. package/dist/gateway/static/root/assets/{task-detail-page-5B5ZVAu0.js → task-detail-page-BYRW7Rrr.js} +2 -2
  95. package/dist/gateway/static/root/assets/{task-expandable-content-DJrrEBB4.js → task-expandable-content-D2t4ahzR.js} +1 -1
  96. package/dist/gateway/static/root/assets/{theme-store-BKpYnggg.js → theme-store-BBLjE0fi.js} +1 -1
  97. package/dist/gateway/static/root/assets/{tracing-settings-page-D71w7dwV.js → tracing-settings-page-5ATxQH5c.js} +1 -1
  98. package/dist/gateway/static/root/assets/{tunnel-api-BV46CvS8.js → tunnel-api-CF1Qh4wU.js} +1 -1
  99. package/dist/gateway/static/root/assets/{usage-page-rMuwNpJi.js → usage-page-CuEHzXil.js} +1 -1
  100. package/dist/gateway/static/root/assets/{use-autosave-CzyqRffr.js → use-autosave-tY3keIbm.js} +1 -1
  101. package/dist/gateway/static/root/assets/{use-composer-attachments-Dviq-1f6.js → use-composer-attachments-CXsocZjt.js} +1 -1
  102. package/dist/gateway/static/root/assets/{use-file-preview-expanded-D5Kk7Hon.js → use-file-preview-expanded-CEsxnDnQ.js} +2 -2
  103. package/dist/gateway/static/root/assets/user-model-page-Dvt5TIZ6.js +2 -0
  104. package/dist/gateway/static/root/assets/{voice-api-key-field-DWtbmacd.js → voice-api-key-field-COTNLUU3.js} +1 -1
  105. package/dist/gateway/static/root/assets/{voice-config-api-DnIjZm_9.js → voice-config-api-DrxBjSja.js} +1 -1
  106. package/dist/gateway/static/root/assets/voice-transcribe-api-B47j0_xA.js +1 -0
  107. package/dist/gateway/static/root/assets/{work-discovery-overlay-ChEG71hz.js → work-discovery-overlay-PByMJrhV.js} +1 -1
  108. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-pdiRKLxP.js → workflow-run-setup-panel-CSUkMo63.js} +2 -2
  109. package/dist/gateway/static/root/assets/{workflows-page-D9LMxINt.js → workflows-page-BUDvFo3R.js} +3 -3
  110. package/dist/gateway/static/root/assets/{workspace-api-CZDvu7uA.js → workspace-api-Bmx1O449.js} +2 -2
  111. package/dist/gateway/static/root/assets/{xopc-cloud-account-card-CbUgg1SK.js → xopc-cloud-account-card-DVsAbvwP.js} +1 -1
  112. package/dist/gateway/static/root/index.html +28 -27
  113. package/dist/package.js +1 -1
  114. package/dist/packages/gateway-contract/src/discussions.js +3 -2
  115. package/dist/packages/gateway-contract/src/index.js +4 -0
  116. package/dist/packages/gateway-contract/src/provider-setup.js +6 -0
  117. package/dist/packages/gateway-contract/src/recording-outcome.js +6 -0
  118. package/dist/packages/image-providers/src/catalog.js +10 -0
  119. package/dist/packages/image-providers/src/execute.js +5 -1
  120. package/dist/packages/image-providers/src/validation.js +19 -1
  121. package/dist/src/agent/background-review/run-background-review.d.ts +0 -1
  122. package/dist/src/agent/background-review/run-background-review.js +10 -2
  123. package/dist/src/agent/embedded/run-for-session.js +26 -3
  124. package/dist/src/agent/embedded/run-turn.js +12 -0
  125. package/dist/src/agent/embedded/xopc-stream-bridge.js +3 -0
  126. package/dist/src/agent/image/generation/runtime.js +12 -14
  127. package/dist/src/agent/image/understanding/runtime.js +5 -0
  128. package/dist/src/agent/inbound/inbound-loop.d.ts +1 -15
  129. package/dist/src/agent/inbound/inbound-loop.js +5 -0
  130. package/dist/src/agent/mcp/connection-errors.d.ts +3 -0
  131. package/dist/src/agent/mcp/connection-errors.js +32 -0
  132. package/dist/src/agent/mcp/connection-setup.d.ts +2 -0
  133. package/dist/src/agent/mcp/connection-setup.js +38 -18
  134. package/dist/src/agent/memory/compaction.js +5 -1
  135. package/dist/src/agent/memory/idle-compaction-scheduler.js +3 -1
  136. package/dist/src/agent/models/manager.d.ts +1 -0
  137. package/dist/src/agent/models/manager.js +4 -2
  138. package/dist/src/agent/orchestration/agent-orchestrator.d.ts +1 -6
  139. package/dist/src/agent/orchestration/agent-orchestrator.js +5 -0
  140. package/dist/src/agent/service/process-direct-one-shot.js +5 -0
  141. package/dist/src/agent/service/process-direct-streaming.d.ts +1 -0
  142. package/dist/src/agent/service/process-direct-streaming.js +17 -1
  143. package/dist/src/agent/tools/image-generate-tool.js +5 -1
  144. package/dist/src/agent-config/resolver.js +5 -0
  145. package/dist/src/agent-config/schema.d.ts +26 -6
  146. package/dist/src/agent-config/schema.js +2 -0
  147. package/dist/src/ai-assist/text-assist.js +5 -16
  148. package/dist/src/automations/service/action-executor.js +3 -1
  149. package/dist/src/channels/index.js +1 -1
  150. package/dist/src/channels/manager.js +1 -1
  151. package/dist/src/cli/commands/channels.js +1 -1
  152. package/dist/src/cli/commands/connectors.js +1 -1
  153. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  154. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  155. package/dist/src/cli/commands/models.js +1 -1
  156. package/dist/src/cli/commands/onboard.js +1 -1
  157. package/dist/src/config/agent-model-intents.js +4 -1
  158. package/dist/src/config/schema.d.ts +11 -5
  159. package/dist/src/config/schema.js +11 -3
  160. package/dist/src/discussions/analyzer.d.ts +2 -0
  161. package/dist/src/discussions/analyzer.js +38 -9
  162. package/dist/src/discussions/audio-clip.d.ts +3 -0
  163. package/dist/src/discussions/audio-clip.js +72 -0
  164. package/dist/src/discussions/live-worker.js +3 -1
  165. package/dist/src/discussions/long-review.d.ts +17 -0
  166. package/dist/src/discussions/long-review.js +278 -0
  167. package/dist/src/discussions/media-timeline.d.ts +21 -0
  168. package/dist/src/discussions/media-timeline.js +134 -0
  169. package/dist/src/discussions/organizer-worker.d.ts +4 -1
  170. package/dist/src/discussions/organizer-worker.js +17 -12
  171. package/dist/src/discussions/organizer.js +2 -0
  172. package/dist/src/discussions/processing.d.ts +43 -0
  173. package/dist/src/discussions/processing.js +125 -0
  174. package/dist/src/discussions/recording.js +202 -42
  175. package/dist/src/discussions/recordingJobs.js +2 -0
  176. package/dist/src/discussions/repository.js +4 -2
  177. package/dist/src/discussions/review.d.ts +8 -0
  178. package/dist/src/discussions/review.js +183 -0
  179. package/dist/src/discussions/sealer.d.ts +7 -1
  180. package/dist/src/discussions/sealer.js +163 -87
  181. package/dist/src/discussions/service.d.ts +7 -1
  182. package/dist/src/discussions/service.js +51 -15
  183. package/dist/src/discussions/types.d.ts +2 -1
  184. package/dist/src/extensions/sdk/index.js +1 -1
  185. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  186. package/dist/src/gateway/global-defaults-admin.d.ts +3 -1
  187. package/dist/src/gateway/global-defaults-admin.js +14 -2
  188. package/dist/src/gateway/hono/lib/config-payload.d.ts +11 -2
  189. package/dist/src/gateway/hono/lib/config-payload.js +2 -0
  190. package/dist/src/gateway/hono/lib/voice-settings-revisions.d.ts +5 -0
  191. package/dist/src/gateway/hono/lib/voice-settings-revisions.js +23 -0
  192. package/dist/src/gateway/hono/routes/config-patch/misc.js +8 -1
  193. package/dist/src/gateway/hono/routes/config.js +12 -0
  194. package/dist/src/gateway/hono/routes/discussions.js +63 -1
  195. package/dist/src/gateway/hono/routes/global-defaults.js +8 -1
  196. package/dist/src/gateway/hono/routes/models.js +12 -4
  197. package/dist/src/gateway/hono/routes/provider-setup.d.ts +3 -0
  198. package/dist/src/gateway/hono/routes/provider-setup.js +106 -0
  199. package/dist/src/gateway/hono/routes/status.js +2 -0
  200. package/dist/src/gateway/hono/routes/voice.js +23 -10
  201. package/dist/src/gateway/provider-model-setup.d.ts +4 -0
  202. package/dist/src/gateway/provider-model-setup.js +56 -0
  203. package/dist/src/gateway/service/config-coordinator.d.ts +2 -2
  204. package/dist/src/gateway/service.js +7 -7
  205. package/dist/src/home-intelligence/host.js +2 -2
  206. package/dist/src/media-shared/http/provider-http.d.ts +0 -6
  207. package/dist/src/media-shared/http/provider-http.js +5 -4
  208. package/dist/src/media-understanding/runner.d.ts +0 -28
  209. package/dist/src/media-understanding/runner.js +4 -0
  210. package/dist/src/platform/client.d.ts +1 -1
  211. package/dist/src/platform/contracts.d.ts +1 -1
  212. package/dist/src/providers/env-keys.js +3 -0
  213. package/dist/src/providers/extension-stream-bridge.js +3 -0
  214. package/dist/src/providers/index.js +15 -0
  215. package/dist/src/providers/model-call.d.ts +5 -2
  216. package/dist/src/providers/model-call.js +13 -2
  217. package/dist/src/providers/model-reference-auditor.js +1 -0
  218. package/dist/src/providers/model-response.js +1 -1
  219. package/dist/src/providers/model-usage.d.ts +15 -0
  220. package/dist/src/providers/model-usage.js +50 -0
  221. package/dist/src/providers/presentation.js +8 -0
  222. package/dist/src/providers/setup/engine.d.ts +37 -0
  223. package/dist/src/providers/setup/engine.js +177 -0
  224. package/dist/src/providers/setup/profiles.d.ts +4 -0
  225. package/dist/src/providers/setup/profiles.js +94 -0
  226. package/dist/src/providers/setup/voice.d.ts +23 -0
  227. package/dist/src/providers/setup/voice.js +234 -0
  228. package/dist/src/scenes/agentExecutor.d.ts +1 -0
  229. package/dist/src/scenes/agentExecutor.js +5 -0
  230. package/dist/src/storage/sqlite/migrations/253_discussion_processing_recovery.sql +20 -0
  231. package/dist/src/storage/sqlite/migrations/254_discussion_annotations.sql +17 -0
  232. package/dist/src/storage/sqlite/migrations/255_discussion_chapter_progress.sql +10 -0
  233. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  234. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  235. package/dist/src/storage/sqlite/schema.js +1 -1
  236. package/dist/src/usage/recorder.js +2 -1
  237. package/dist/src/usage/scenario-registry.js +128 -123
  238. package/dist/src/voice/dashscope/streaming-stt-session.js +3 -0
  239. package/dist/src/voice/dashscope/streaming-tts-stream.js +3 -0
  240. package/dist/src/voice/dictation.d.ts +12 -0
  241. package/dist/src/voice/dictation.js +22 -0
  242. package/dist/src/voice/metadata/builtin.js +54 -0
  243. package/dist/src/voice/platform-streams.js +3 -0
  244. package/dist/src/voice/realtime/omniEngine.js +3 -0
  245. package/dist/src/voice/realtime/omniRoute.js +3 -2
  246. package/dist/src/voice/realtime/runtime.js +4 -2
  247. package/dist/src/voice/stt/factory.js +9 -3
  248. package/dist/src/voice/stt/providers/bailian-plan-transcription.d.ts +2 -0
  249. package/dist/src/voice/stt/providers/bailian-plan-transcription.js +32 -0
  250. package/dist/src/voice/stt/providers/index.d.ts +1 -0
  251. package/dist/src/voice/stt/providers/index.js +2 -1
  252. package/dist/src/voice/token-plan.d.ts +8 -0
  253. package/dist/src/voice/token-plan.js +11 -0
  254. package/dist/src/voice/tts/factory.js +4 -1
  255. package/dist/src/voice/tts/providers/bailian-plan-speech.d.ts +2 -0
  256. package/dist/src/voice/tts/providers/bailian-plan-speech.js +84 -0
  257. package/dist/src/voice/tts/providers/index.d.ts +1 -0
  258. package/dist/src/voice/tts/providers/index.js +2 -1
  259. package/dist/src/voice/tts/speak-core.js +10 -1
  260. package/package.json +4 -4
  261. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-Ds0Ue2FB.js +0 -1
  262. package/dist/gateway/static/root/assets/agent-plugin-dialog-UunIxc1q.js +0 -1
  263. package/dist/gateway/static/root/assets/agents-BLRM4o-U.js +0 -77
  264. package/dist/gateway/static/root/assets/app-management-settings-panel-Dmy828Pe.js +0 -1
  265. package/dist/gateway/static/root/assets/automations-workspace-UcCneEs3.js +0 -6
  266. package/dist/gateway/static/root/assets/browser-automations-page-BjvQnYfO.js +0 -3
  267. package/dist/gateway/static/root/assets/browser-settings-page-D5ZghI28.js +0 -3
  268. package/dist/gateway/static/root/assets/capabilities-page-MC8qIrXo.js +0 -2
  269. package/dist/gateway/static/root/assets/capabilities-settings-panel-Blz3hEzp.js +0 -8
  270. package/dist/gateway/static/root/assets/channels-DSg_iCVC.js +0 -1
  271. package/dist/gateway/static/root/assets/chat-terminal-dock-C97SJEwd.js +0 -36
  272. package/dist/gateway/static/root/assets/connectors-page-DXk-GAsd.js +0 -1
  273. package/dist/gateway/static/root/assets/device-pairing-wizard-BeSuq__I.js +0 -1
  274. package/dist/gateway/static/root/assets/extension-settings-page-jYu6qpY2.js +0 -1
  275. package/dist/gateway/static/root/assets/fallback-models-CoyzvDo7.js +0 -1
  276. package/dist/gateway/static/root/assets/gateway-realtime-store-C3vH-Iup.js +0 -1
  277. package/dist/gateway/static/root/assets/gateway-settings-JlT1dlSj.js +0 -1
  278. package/dist/gateway/static/root/assets/home-page-DOVl8s-1.js +0 -2
  279. package/dist/gateway/static/root/assets/image-generation-api-BZBiYDmV.js +0 -1
  280. package/dist/gateway/static/root/assets/imports-page-DgdBTp_0.js +0 -1
  281. package/dist/gateway/static/root/assets/index-CmC8JkSM.js +0 -260
  282. package/dist/gateway/static/root/assets/index-Dgzc0oBu.css +0 -1
  283. package/dist/gateway/static/root/assets/logs-page-BSepiACn.js +0 -2
  284. package/dist/gateway/static/root/assets/management-settings-dE_ykPNY.js +0 -1
  285. package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-65SE6j-_.js +0 -1
  286. package/dist/gateway/static/root/assets/messages-DlTNQI92.js +0 -3
  287. package/dist/gateway/static/root/assets/models-hub-cache-C7FAsEe_.js +0 -1
  288. package/dist/gateway/static/root/assets/note-detail-panel-D9oqhdyk.js +0 -5
  289. package/dist/gateway/static/root/assets/notes-page-Bd4_7ph8.js +0 -8
  290. package/dist/gateway/static/root/assets/personal-page-BvWzq4Wp.js +0 -1
  291. package/dist/gateway/static/root/assets/project-detail-page-D-qkIXVT.js +0 -1
  292. package/dist/gateway/static/root/assets/projects-page-BQtw1Dfn.js +0 -1
  293. package/dist/gateway/static/root/assets/remote-access-hub-CYFNz0Jc.js +0 -1
  294. package/dist/gateway/static/root/assets/runtime-tools-settings-panel-Qq_NyYx_.js +0 -1
  295. package/dist/gateway/static/root/assets/scenes-page-hGr-ppYk.js +0 -2
  296. package/dist/gateway/static/root/assets/sessions-page-CpX1Rluw.js +0 -1
  297. package/dist/gateway/static/root/assets/settings-advanced-gate-D2s_MlxR.js +0 -1
  298. package/dist/gateway/static/root/assets/settings-loading-skeleton-BTqvr_Fw.js +0 -1
  299. package/dist/gateway/static/root/assets/setup-status-panel-BiHRYDHq.js +0 -1
  300. package/dist/gateway/static/root/assets/shares-settings-DfcAu08T.js +0 -1
  301. package/dist/gateway/static/root/assets/skills-page-CvKc5nBN.js +0 -2
  302. package/dist/gateway/static/root/assets/user-model-page-Dhqw3v_u.js +0 -2
@@ -1,5 +1,6 @@
1
1
  import type { Config } from '../config/schema.js';
2
2
  import type { NotesService } from '../notes/service.js';
3
+ import type { STTResult } from '../voice/stt/types.js';
3
4
  import type { DiscussionCapture } from './types.js';
4
5
  export interface DiscussionSealerDeps {
5
6
  processRecordingJob?: () => Promise<void>;
@@ -9,18 +10,23 @@ export interface DiscussionSealerDeps {
9
10
  text: string;
10
11
  language?: string;
11
12
  }>;
13
+ transcribeSegment?: (audio: Buffer, signal: AbortSignal) => Promise<STTResult>;
14
+ requestTimeoutMs?: number;
12
15
  onUpdated?: (capture: DiscussionCapture) => void;
13
16
  }
14
17
  export declare class DiscussionSealer {
15
18
  private readonly deps;
16
19
  private readonly intervalMs;
20
+ private readonly owner;
17
21
  private timer?;
18
22
  private running;
23
+ private recordingRunning;
24
+ private stopping;
25
+ private controller?;
19
26
  constructor(deps: DiscussionSealerDeps, intervalMs?: number);
20
27
  start(): void;
21
28
  stop(): Promise<void>;
22
29
  tick(now?: number): Promise<void>;
23
30
  private sealWhenReady;
24
31
  private transcribeFullRecording;
25
- private fail;
26
32
  }
@@ -1,113 +1,189 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
+ import { init_transaction, runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
4
+ import { DISCUSSION_MAX_SAVED_DURATION_MS } from "../../packages/gateway-contract/src/discussions.js";
5
+ import { init_src } from "../../packages/gateway-contract/src/index.js";
6
+ import { init_model_usage, withModelUsageOrigin } from "../providers/model-usage.js";
3
7
  import { transcribe } from "../voice/stt/transcribe-core.js";
4
8
  import { isSTTAvailable } from "../voice/stt/availability.js";
5
9
  import { mergeSttConfigFromAppConfig } from "../voice/stt/config.js";
6
10
  import "../voice/stt/index.js";
7
- import { getDiscussionCapture, listDiscussionCaptures, listDiscussionTranscriptSegments, updateDiscussionCapture } from "./repository.js";
8
- import { assembleDiscussionTranscript } from "./transcript.js";
11
+ import { listDiscussionTranscriptSegments, updateDiscussionCapture } from "./repository.js";
12
+ import { appendTranscriptWithoutOverlap, assembleDiscussionTranscript } from "./transcript.js";
9
13
  import { replaceTranscriptSegments, saveTranscriptRevision } from "./revisions.js";
14
+ import { assertProcessingRun, claimSealingCapture, ensureProcessingRun, failOrRetryProcessing, getProcessingRun, readCheckpoint, releaseSealingLease, renewSealingLease, resetProcessingRetry, saveCheckpoint, withProcessingDeadline } from "./processing.js";
10
15
  import { missingAudioRanges, slicePcmWav } from "./audio-repair.js";
11
16
  import { decodeWavToMonoFloat32 } from "../voice/audio/wav.js";
12
17
  import { forEachNormalizedAudioSegment } from "../voice/audio/normalize.js";
13
18
  import { getRecordingJob } from "./recordingJobs.js";
14
- import { createHash } from "node:crypto";
19
+ import { createReadStream } from "node:fs";
20
+ import { createHash, randomUUID } from "node:crypto";
15
21
  //#region src/discussions/sealer.ts
22
+ init_src();
23
+ init_model_usage();
24
+ init_transaction();
16
25
  init_logger();
17
26
  const log = createLogger("DiscussionSealer");
18
27
  const UPLOAD_GRACE_MS = 2 * 6e4;
19
28
  var DiscussionSealer = class {
29
+ owner = randomUUID();
20
30
  timer;
21
31
  running = false;
32
+ recordingRunning = false;
33
+ stopping = false;
34
+ controller;
22
35
  constructor(deps, intervalMs = 1e3) {
23
36
  this.deps = deps;
24
37
  this.intervalMs = intervalMs;
25
38
  }
26
39
  start() {
27
40
  if (this.timer) return;
28
- this.timer = setInterval(() => void this.tick(), this.intervalMs);
41
+ this.stopping = false;
42
+ this.timer = setInterval(() => void this.tick().catch((error) => log.error({ err: error }, "Discussion processing tick failed")), this.intervalMs);
29
43
  this.timer.unref();
30
- this.tick();
44
+ this.tick().catch((error) => log.error({ err: error }, "Discussion processing tick failed"));
31
45
  }
32
46
  async stop() {
47
+ this.stopping = true;
33
48
  if (this.timer) clearInterval(this.timer);
34
49
  this.timer = void 0;
35
- while (this.running) await new Promise((resolve) => setTimeout(resolve, 10));
50
+ this.controller?.abort(/* @__PURE__ */ new Error("Discussion processing stopped"));
51
+ while (this.running || this.recordingRunning) await new Promise((resolve) => setTimeout(resolve, 10));
36
52
  }
37
53
  async tick(now = Date.now()) {
38
- if (this.running) return;
54
+ if (this.stopping) return;
55
+ if (!this.recordingRunning) {
56
+ this.recordingRunning = true;
57
+ try {
58
+ await this.deps.processRecordingJob?.();
59
+ } finally {
60
+ this.recordingRunning = false;
61
+ }
62
+ }
63
+ if (this.running || this.stopping) return;
39
64
  this.running = true;
65
+ const controller = new AbortController();
66
+ this.controller = controller;
67
+ let capture = null;
68
+ let renewal;
40
69
  try {
41
- await this.deps.processRecordingJob?.();
42
- const capture = [...listDiscussionCaptures({
43
- status: "sealing",
44
- limit: 1
45
- }).items, ...listDiscussionCaptures({
46
- status: "stopping",
47
- limit: 1
48
- }).items][0];
70
+ capture = claimSealingCapture(this.owner, now);
49
71
  if (!capture) return;
50
- await this.sealWhenReady(capture, now);
72
+ const id = capture.id;
73
+ renewal = setInterval(() => {
74
+ if (!renewSealingLease(id, this.owner)) controller.abort(/* @__PURE__ */ new Error("Transcription lease lost"));
75
+ }, 15e3);
76
+ renewal.unref();
77
+ await this.sealWhenReady(capture, now, controller.signal);
51
78
  } finally {
79
+ if (renewal) clearInterval(renewal);
80
+ if (capture) releaseSealingLease(capture.id, this.owner);
81
+ this.controller = void 0;
52
82
  this.running = false;
53
83
  }
54
84
  }
55
- async sealWhenReady(capture, now) {
85
+ async sealWhenReady(capture, now, signal) {
56
86
  const ageMs = now - (capture.recordingStoppedAt ?? now);
57
87
  if (!capture.audioAttachmentId) {
58
88
  const job = getRecordingJob(capture.id);
59
89
  if (job && (job.state === "queued" || job.state === "running")) return;
60
- if (ageMs >= UPLOAD_GRACE_MS) this.fail(capture, "audio_upload", "recording_missing", "Original recording was not uploaded");
90
+ if (ageMs >= UPLOAD_GRACE_MS) {
91
+ const updated = updateDiscussionCapture(capture.id, {
92
+ status: "needs_attention",
93
+ failureStage: "audio_upload",
94
+ failureCode: "recording_missing",
95
+ failureMessage: "Original recording was not uploaded"
96
+ }, ["stopping", "sealing"]);
97
+ if (updated) this.deps.onUpdated?.(updated);
98
+ }
99
+ if (ageMs < UPLOAD_GRACE_MS) updateDiscussionCapture(capture.id, { updatedAt: Date.now() }, [capture.status]);
61
100
  return;
62
101
  }
63
102
  const segments = listDiscussionTranscriptSegments(capture.id);
64
103
  const expected = capture.expectedLastSequence ?? -1;
65
- const bySequence = new Map(segments.map((segment) => [segment.sequence, segment]));
66
- const missing = Array.from({ length: expected + 1 }, (_, sequence) => sequence).filter((sequence) => !bySequence.has(sequence));
104
+ const missing = expected >= 0 && Array.from({ length: expected + 1 }, (_, sequence) => sequence).some((sequence) => !segments.some((segment) => segment.sequence === sequence));
67
105
  const pending = segments.some((segment) => segment.status === "uploaded" || segment.status === "transcribing");
68
- if ((missing.length > 0 || pending) && ageMs < UPLOAD_GRACE_MS) return;
106
+ const run = ensureProcessingRun(capture);
107
+ if (!run.force_audio && (missing || pending) && ageMs < UPLOAD_GRACE_MS) {
108
+ updateDiscussionCapture(capture.id, { updatedAt: Date.now() }, [capture.status]);
109
+ return;
110
+ }
69
111
  const sealing = capture.status === "sealing" ? capture : updateDiscussionCapture(capture.id, { status: "sealing" }, ["stopping"]);
70
112
  if (!sealing) return;
71
113
  try {
72
114
  const confirmed = segments.filter((segment) => segment.status === "confirmed");
73
- const result = expected >= 0 && missing.length === 0 && !pending && confirmed.length === expected + 1 ? { text: assembleDiscussionTranscript(confirmed) } : await this.transcribeFullRecording(sealing);
115
+ const result = !run.force_audio && expected >= 0 && !missing && !pending && confirmed.length === expected + 1 ? { text: assembleDiscussionTranscript(confirmed) } : await withModelUsageOrigin("interactive", () => this.transcribeFullRecording(sealing, run, signal));
74
116
  const text = result.text.trim();
75
- saveTranscriptRevision(capture.id);
76
117
  if (!text) throw new Error("Discussion transcription produced no text");
77
- const updated = updateDiscussionCapture(capture.id, {
78
- status: "organizing",
79
- canonicalTranscript: text,
80
- canonicalTranscriptSha256: createHash("sha256").update(text).digest("hex"),
81
- transcriptLanguage: result.language,
82
- failureStage: void 0,
83
- failureCode: void 0,
84
- failureMessage: void 0
85
- }, ["sealing"]);
86
- if (!updated) throw new Error("Discussion changed while sealing transcript");
87
- this.deps.onUpdated?.(updated);
118
+ const updated = runSqliteWriteTransaction(() => {
119
+ assertProcessingRun(run, this.owner, signal);
120
+ if (result.segments) replaceTranscriptSegments(capture.id, result.segments);
121
+ saveTranscriptRevision(capture.id);
122
+ resetProcessingRetry(capture.id);
123
+ return updateDiscussionCapture(capture.id, {
124
+ status: "organizing",
125
+ canonicalTranscript: text,
126
+ canonicalTranscriptSha256: createHash("sha256").update(text).digest("hex"),
127
+ transcriptLanguage: result.language,
128
+ failureStage: void 0,
129
+ failureCode: void 0,
130
+ failureMessage: void 0
131
+ }, ["sealing"]);
132
+ });
133
+ if (updated) this.deps.onUpdated?.(updated);
88
134
  } catch (error) {
89
- const message = error instanceof Error ? error.message : String(error);
90
- this.fail(sealing, "transcript_sealing", "transcript_sealing_failed", message);
135
+ if (signal.aborted) return;
136
+ if (getProcessingRun(capture.id)?.run_id !== run.run_id || !renewSealingLease(capture.id, this.owner)) return;
137
+ const updated = failOrRetryProcessing(sealing, "transcript_sealing", error);
138
+ if (updated) this.deps.onUpdated?.(updated);
139
+ log.warn({
140
+ err: error,
141
+ discussionId: capture.id,
142
+ phase: "transcript_sealing"
143
+ }, "Discussion transcription failed; saved original retained");
91
144
  }
92
145
  }
93
- async transcribeFullRecording(capture) {
146
+ async transcribeFullRecording(capture, run, signal) {
94
147
  const attachment = await this.deps.notes.getAttachmentPath(capture.noteId, capture.audioAttachmentId);
95
148
  if (!attachment) throw new Error("Discussion audio file is missing");
149
+ const assertCurrent = () => assertProcessingRun(run, this.owner, signal);
150
+ assertCurrent();
151
+ if (capture.audioSha256) {
152
+ const hash = createHash("sha256");
153
+ for await (const chunk of createReadStream(attachment.filePath)) {
154
+ signal.throwIfAborted();
155
+ hash.update(chunk);
156
+ }
157
+ if (hash.digest("hex") !== capture.audioSha256) throw new Error("Saved original audio checksum mismatch");
158
+ }
159
+ assertCurrent();
96
160
  if (this.deps.transcribeRecording) {
97
- const result = await this.deps.transcribeRecording(attachment.filePath, capture);
98
- replaceTranscriptSegments(capture.id, [{
99
- text: result.text,
100
- startedAtMs: 0,
101
- endedAtMs: capture.durationMs ?? 1e3
102
- }]);
103
- return result;
161
+ if (listDiscussionTranscriptSegments(capture.id).some((segment) => segment.correctedByUser)) throw new Error("Segment transcription is required to preserve manual corrections");
162
+ const cached = readCheckpoint(run.run_id, 0, capture.durationMs ?? 1e3);
163
+ const result = cached ?? await withProcessingDeadline(async (requestSignal) => {
164
+ const response = await this.deps.transcribeRecording(attachment.filePath, capture, requestSignal);
165
+ return {
166
+ segments: [{
167
+ text: response.text,
168
+ startedAtMs: 0,
169
+ endedAtMs: capture.durationMs ?? 1e3
170
+ }],
171
+ language: response.language
172
+ };
173
+ }, signal, this.deps.requestTimeoutMs ?? 12e4);
174
+ assertCurrent();
175
+ if (!cached) saveCheckpoint(run.run_id, 0, capture.durationMs ?? 1e3, result);
176
+ return {
177
+ text: result.segments.map((segment) => segment.text).join("\n"),
178
+ language: result.language,
179
+ segments: result.segments
180
+ };
104
181
  }
105
182
  const config = this.deps.getConfig();
106
183
  const sttConfig = mergeSttConfigFromAppConfig(config.tools?.media?.audio, config.tools?.media);
107
- if (!isSTTAvailable(sttConfig)) throw new Error("STT is not configured");
108
- let offset = 0;
109
- const confirmed = listDiscussionTranscriptSegments(capture.id).filter((segment) => segment.status === "confirmed");
110
- const segments = confirmed.map((segment) => ({
184
+ if (!this.deps.transcribeSegment && !isSTTAvailable(sttConfig)) throw new Error("STT is not configured");
185
+ const confirmed = listDiscussionTranscriptSegments(capture.id).filter((segment) => segment.status === "confirmed" && (!run.force_audio || segment.correctedByUser));
186
+ const output = confirmed.map((segment) => ({
111
187
  text: segment.displayText ?? segment.rawText ?? "",
112
188
  rawText: segment.rawText,
113
189
  startedAtMs: segment.startedAtMs,
@@ -115,61 +191,61 @@ var DiscussionSealer = class {
115
191
  speakerLabel: segment.speakerLabel,
116
192
  correctedByUser: segment.correctedByUser
117
193
  }));
194
+ let offset = 0;
118
195
  let language;
119
196
  await forEachNormalizedAudioSegment({
120
197
  filePath: attachment.filePath,
121
- maxDurationSeconds: 7200
198
+ maxDurationSeconds: DISCUSSION_MAX_SAVED_DURATION_MS / 1e3,
199
+ signal
122
200
  }, async (buffer, index) => {
201
+ assertCurrent();
123
202
  const decoded = decodeWavToMonoFloat32(buffer);
124
203
  const durationMs = decoded.durationSeconds * 1e3;
125
204
  const gaps = missingAudioRanges(offset, offset + durationMs, confirmed);
126
205
  for (const [gapIndex, gap] of gaps.entries()) {
127
- const audio = gaps.length === 1 && gap.startedAtMs === offset && gap.endedAtMs === offset + durationMs ? buffer : slicePcmWav(decoded, gap.startedAtMs - offset, gap.endedAtMs - offset);
128
- if (audio.length <= 44) continue;
129
- const result = await transcribe(audio, sttConfig, {
130
- mime: "audio/wav",
131
- fileName: `discussion-recovery-${index}-${gapIndex}.wav`
132
- });
133
- if (result.segments?.length) for (const part of result.segments) {
134
- if (!Number.isFinite(part.startMs) || !Number.isFinite(part.endMs) || part.startMs < 0 || part.endMs <= part.startMs || part.endMs > gap.endedAtMs - gap.startedAtMs + 100) throw new Error("Provider returned an invalid transcript time range");
135
- segments.push({
136
- text: part.text,
137
- startedAtMs: gap.startedAtMs + part.startMs,
138
- endedAtMs: Math.min(gap.endedAtMs, gap.startedAtMs + part.endMs),
139
- ...part.speaker ? { speakerLabel: `${index + 1}:${gapIndex + 1}:${part.speaker}` } : {}
206
+ assertCurrent();
207
+ let checkpoint = readCheckpoint(run.run_id, gap.startedAtMs, gap.endedAtMs);
208
+ if (!checkpoint) {
209
+ const audio = gaps.length === 1 && gap.startedAtMs === offset && gap.endedAtMs === offset + durationMs ? buffer : slicePcmWav(decoded, gap.startedAtMs - offset, gap.endedAtMs - offset);
210
+ if (audio.length <= 44) continue;
211
+ const result = await withProcessingDeadline((requestSignal) => this.deps.transcribeSegment ? this.deps.transcribeSegment(audio, requestSignal) : transcribe(audio, sttConfig, {
212
+ mime: "audio/wav",
213
+ fileName: `discussion-recovery-${index}-${gapIndex}.wav`,
214
+ signal: requestSignal
215
+ }), signal, this.deps.requestTimeoutMs ?? 12e4);
216
+ const recovered = [];
217
+ if (result.segments?.length) for (const part of result.segments) {
218
+ if (!Number.isFinite(part.startMs) || !Number.isFinite(part.endMs) || part.startMs < 0 || part.endMs <= part.startMs || part.endMs > gap.endedAtMs - gap.startedAtMs + 100) throw new Error("Provider returned an invalid transcript time range");
219
+ recovered.push({
220
+ text: part.text,
221
+ startedAtMs: gap.startedAtMs + part.startMs,
222
+ endedAtMs: Math.min(gap.endedAtMs, gap.startedAtMs + part.endMs),
223
+ ...part.speaker ? { speakerLabel: `${index + 1}:${gapIndex + 1}:${part.speaker}` } : {}
224
+ });
225
+ }
226
+ else if (result.text.trim()) recovered.push({
227
+ text: result.text,
228
+ ...gap
140
229
  });
230
+ checkpoint = {
231
+ segments: recovered,
232
+ language: result.language
233
+ };
234
+ assertCurrent();
235
+ saveCheckpoint(run.run_id, gap.startedAtMs, gap.endedAtMs, checkpoint);
141
236
  }
142
- else if (result.text.trim()) segments.push({
143
- text: result.text,
144
- ...gap
145
- });
146
- language ??= result.language;
237
+ output.push(...checkpoint.segments);
238
+ language ??= checkpoint.language;
147
239
  }
148
240
  offset += durationMs;
149
241
  });
150
- segments.sort((a, b) => a.startedAtMs - b.startedAtMs);
151
- replaceTranscriptSegments(capture.id, segments);
242
+ output.sort((a, b) => a.startedAtMs - b.startedAtMs);
152
243
  return {
153
- text: assembleDiscussionTranscript(listDiscussionTranscriptSegments(capture.id)),
154
- ...language ? { language } : {}
244
+ text: output.reduce((text, segment) => appendTranscriptWithoutOverlap(text, segment.text), ""),
245
+ language,
246
+ segments: output
155
247
  };
156
248
  }
157
- fail(capture, stage, code, message) {
158
- const current = getDiscussionCapture(capture.id);
159
- if (!current || current.status !== "stopping" && current.status !== "sealing") return;
160
- const updated = updateDiscussionCapture(capture.id, {
161
- status: "needs_attention",
162
- failureStage: stage,
163
- failureCode: code,
164
- failureMessage: message.slice(0, 1e3)
165
- }, [current.status]);
166
- if (updated) this.deps.onUpdated?.(updated);
167
- log.warn({
168
- discussionId: capture.id,
169
- stage,
170
- code
171
- }, `Discussion sealing failed: ${message}`);
172
- }
173
249
  };
174
250
  //#endregion
175
251
  export { DiscussionSealer };
@@ -1,3 +1,4 @@
1
+ import { longRecordingReview } from './long-review.js';
1
2
  import { type DiscussionRecordingManifest } from '@xopcai/gateway-contract';
2
3
  import type { NotesService } from '../notes/service.js';
3
4
  import type { ProjectService } from '../projects/project-service.js';
@@ -15,6 +16,10 @@ export declare class DiscussionService {
15
16
  private readonly recordingOwner;
16
17
  private readonly recordingControllers;
17
18
  constructor(notes: NotesService, projects: ProjectService, emit?: (type: string, payload: unknown) => void);
19
+ audioClip(id: string, start: number, end: number, signal: AbortSignal): Promise<Buffer<ArrayBufferLike>>;
20
+ annotations(id: string): Promise<import("@xopcai/gateway-contract").DiscussionResolvedAnnotation[]>;
21
+ saveAnnotation(id: string, input: import('@xopcai/gateway-contract').DiscussionAnnotationInput): import("@xopcai/gateway-contract").DiscussionAnnotation;
22
+ evidence(id: string, revision: number, ids: number[]): Promise<import("@xopcai/gateway-contract").DiscussionEvidence>;
18
23
  settings(): DiscussionCaptureSettings;
19
24
  acknowledgeConsent(policyVersion: number): DiscussionCaptureSettings;
20
25
  create(input: CreateDiscussionInput): Promise<DiscussionDetail>;
@@ -44,10 +49,11 @@ export declare class DiscussionService {
44
49
  sealRecording(id: string, input: DiscussionRecordingManifest): Promise<import("@xopcai/gateway-contract").DiscussionRecordingJob>;
45
50
  /** Runs inside the existing sealer lifecycle; unfinished leases survive process restart. */
46
51
  processRecordingJob(): Promise<void>;
47
- retry(id: string): Promise<DiscussionDetail | null>;
52
+ retry(id: string, mode?: import('./types.js').DiscussionRetryMode): Promise<DiscussionDetail | null>;
48
53
  cancel(id: string): Promise<DiscussionDetail | null>;
49
54
  deleteAudio(id: string): Promise<DiscussionDetail | null>;
50
55
  unlinkInferredProject(id: string): Promise<DiscussionDetail | null>;
56
+ review(id: string, options?: Parameters<typeof longRecordingReview>[2]): Promise<import("@xopcai/gateway-contract").DiscussionReview>;
51
57
  private detail;
52
58
  private enqueueMutation;
53
59
  }
@@ -8,6 +8,10 @@ import { DiscussionServiceError } from "./errors.js";
8
8
  import { acknowledgeDiscussionCaptureConsent, correctDiscussionTranscriptSegment, createDiscussionCapture, createDiscussionTranscriptSegment, deleteDiscussionSegmentAudio, getDiscussionCapture, getDiscussionCaptureByClientRequestId, getDiscussionCaptureByNoteId, getDiscussionCaptureSettings, getDiscussionMetrics, getDiscussionTranscriptSegment, getLatestDiscussionOrganization, listDiscussionCaptures, listDiscussionTranscriptSegments, updateDiscussionCapture } from "./repository.js";
9
9
  import { assembleDiscussionTranscript } from "./transcript.js";
10
10
  import { readTranscriptRevision, refreshCanonicalTranscript, saveTranscriptRevision } from "./revisions.js";
11
+ import { createProcessingRun, processingProgress, resetProcessingRetry } from "./processing.js";
12
+ import { evidenceFor, putAnnotation, resolvedAnnotations } from "./review.js";
13
+ import { longRecordingReview } from "./long-review.js";
14
+ import { discussionAudioClip } from "./audio-clip.js";
11
15
  import { editMeeting } from "./edits.js";
12
16
  import { completeRecording, listRecordingChunks, removeRecordingChunks, saveRecordingChunk, validateRecordingManifest } from "./recording.js";
13
17
  import { cancelRecordingJob, claimRecordingJob, finishRecordingJob, getRecordingJob, getRecordingJobInput, renewRecordingJob, submitRecordingJob } from "./recordingJobs.js";
@@ -31,6 +35,18 @@ var DiscussionService = class {
31
35
  this.projects = projects;
32
36
  this.emit = emit;
33
37
  }
38
+ audioClip(id, start, end, signal) {
39
+ return discussionAudioClip(id, start, end, this.notes, signal);
40
+ }
41
+ annotations(id) {
42
+ return resolvedAnnotations(id, this.notes);
43
+ }
44
+ saveAnnotation(id, input) {
45
+ return putAnnotation(id, input);
46
+ }
47
+ evidence(id, revision, ids) {
48
+ return evidenceFor(id, revision, ids, this.notes);
49
+ }
34
50
  settings() {
35
51
  return getDiscussionCaptureSettings();
36
52
  }
@@ -238,6 +254,7 @@ var DiscussionService = class {
238
254
  const capture = getDiscussionCapture(id);
239
255
  if (!capture) throw new DiscussionServiceError("not_found", "Discussion not found");
240
256
  if (!["completed", "needs_attention"].includes(capture.status) || !capture.canonicalTranscript) throw new DiscussionServiceError("conflict", "Transcript is not ready");
257
+ resetProcessingRetry(id);
241
258
  const updated = updateDiscussionCapture(id, {
242
259
  status: "organizing",
243
260
  template,
@@ -338,24 +355,37 @@ var DiscussionService = class {
338
355
  }
339
356
  });
340
357
  }
341
- async retry(id) {
342
- const capture = getDiscussionCapture(id);
343
- if (!capture) return null;
344
- if (capture.status !== "needs_attention") throw new DiscussionServiceError("conflict", "Only discussions needing attention can be retried");
345
- if (getRecordingJob(id)?.state === "failed") {
358
+ async retry(id, mode = "resume") {
359
+ if (mode !== "resume" && mode !== "from_audio") throw new DiscussionServiceError("invalid_input", "Invalid retry mode");
360
+ if (mode === "resume" && getRecordingJob(id)?.state === "failed") {
346
361
  await this.sealRecording(id, getRecordingJobInput(id));
347
362
  return this.get(id);
348
363
  }
349
- const updated = updateDiscussionCapture(id, {
350
- status: capture.canonicalTranscript ? "organizing" : "stopping",
351
- ...!capture.canonicalTranscript ? { recordingStoppedAt: Date.now() } : {},
352
- failureStage: void 0,
353
- failureCode: void 0,
354
- failureMessage: void 0
355
- }, ["needs_attention"]);
356
- if (!updated) throw new DiscussionServiceError("conflict", "Discussion changed while retrying");
357
- this.emit?.("discussion.updated", updated);
358
- return this.detail(updated);
364
+ return this.enqueueMutation(id, async () => {
365
+ const capture = getDiscussionCapture(id);
366
+ if (!capture) return null;
367
+ if (mode === "from_audio") {
368
+ if (!["completed", "needs_attention"].includes(capture.status)) throw new DiscussionServiceError("conflict", "Wait for current processing to finish");
369
+ if (!capture.audioAttachmentId || capture.audioDeletedAt || !await this.notes.getAttachmentPath(capture.noteId, capture.audioAttachmentId)) throw new DiscussionServiceError("conflict", "Saved original audio is unavailable");
370
+ } else if (capture.status !== "needs_attention") throw new DiscussionServiceError("conflict", "Only discussions needing attention can be retried");
371
+ const updated = runSqliteWriteTransaction(() => {
372
+ if (mode === "from_audio") {
373
+ saveTranscriptRevision(id);
374
+ createProcessingRun(capture, true);
375
+ } else resetProcessingRetry(id);
376
+ const status = mode === "from_audio" || capture.failureStage === "transcript_sealing" ? "sealing" : capture.canonicalTranscript ? "organizing" : "stopping";
377
+ return updateDiscussionCapture(id, {
378
+ status,
379
+ ...status === "stopping" ? { recordingStoppedAt: Date.now() } : {},
380
+ failureStage: void 0,
381
+ failureCode: void 0,
382
+ failureMessage: void 0
383
+ }, [capture.status]);
384
+ });
385
+ if (!updated) throw new DiscussionServiceError("conflict", "Discussion changed while retrying");
386
+ this.emit?.("discussion.updated", updated);
387
+ return this.detail(updated);
388
+ });
359
389
  }
360
390
  async cancel(id) {
361
391
  const active = getDiscussionCapture(id);
@@ -389,6 +419,8 @@ var DiscussionService = class {
389
419
  await removeRecordingChunks(capture);
390
420
  cancelRecordingJob(id);
391
421
  if (capture.audioAttachmentId) await this.notes.removeAttachment(capture.noteId, capture.audioAttachmentId);
422
+ const sourceNote = await this.notes.getNote(capture.noteId);
423
+ for (const attachment of sourceNote?.attachments ?? []) if (attachment.retainWithoutReference && (attachment.fileName.startsWith(`recording-part-${capture.id}-`) || attachment.fileName === `recording-sources-${capture.id}.json` || attachment.fileName === `recording-events-${capture.id}.json`)) await this.notes.removeAttachment(capture.noteId, attachment.id);
392
424
  deleteDiscussionSegmentAudio(id);
393
425
  const updated = updateDiscussionCapture(id, {
394
426
  audioAttachmentId: void 0,
@@ -413,12 +445,16 @@ var DiscussionService = class {
413
445
  this.emit?.("discussion.updated", updated);
414
446
  return this.detail(updated);
415
447
  }
448
+ review(id, options = {}) {
449
+ return longRecordingReview(id, this.notes, options);
450
+ }
416
451
  async detail(capture) {
417
452
  const note = await this.notes.getNote(capture.noteId);
418
453
  if (!note) throw new DiscussionServiceError("not_found", "Discussion note not found");
419
454
  const recordingJob = getRecordingJob(capture.id);
420
455
  return {
421
456
  discussion: capture,
457
+ processing: processingProgress(capture.id),
422
458
  note,
423
459
  transcript: this.transcript(capture.id),
424
460
  ...recordingJob ? { recordingJob } : {},
@@ -1,10 +1,11 @@
1
1
  export { DISCUSSION_STATUSES } from '@xopcai/gateway-contract';
2
- export type { DiscussionStatus, DiscussionSource, DiscussionProjectInferenceSource, DiscussionFailureStage, DiscussionFact, DiscussionChapter, DiscussionTemplate, DiscussionActionItem, DiscussionOrganization, DiscussionCapture, DiscussionTranscriptSegmentStatus, DiscussionTranscriptSegment, DiscussionTranscriptStats, DiscussionTranscript, DiscussionOrganizationRecord, DiscussionCaptureSettings, CreateDiscussionInput, ListDiscussionsQuery, DiscussionListResult, DiscussionMetrics, } from '@xopcai/gateway-contract';
2
+ export type { DiscussionStatus, DiscussionSource, DiscussionProjectInferenceSource, DiscussionFailureStage, DiscussionFact, DiscussionChapter, DiscussionTemplate, DiscussionActionItem, DiscussionOrganization, DiscussionCapture, DiscussionTranscriptSegmentStatus, DiscussionTranscriptSegment, DiscussionTranscriptStats, DiscussionTranscript, DiscussionOrganizationRecord, DiscussionCaptureSettings, CreateDiscussionInput, ListDiscussionsQuery, DiscussionListResult, DiscussionMetrics, DiscussionProcessingProgress, DiscussionRetryMode, } from '@xopcai/gateway-contract';
3
3
  import type { DiscussionCapture, DiscussionTranscript, DiscussionOrganizationRecord } from '@xopcai/gateway-contract';
4
4
  export interface DiscussionDetail {
5
5
  discussion: DiscussionCapture;
6
6
  note: import('../notes/types.js').Note;
7
7
  transcript: DiscussionTranscript;
8
8
  organization?: DiscussionOrganizationRecord;
9
+ processing?: import('@xopcai/gateway-contract').DiscussionProcessingProgress;
9
10
  recordingJob?: import('@xopcai/gateway-contract').DiscussionRecordingJob;
10
11
  }
@@ -7,8 +7,8 @@ import { DEFAULT_SECURITY_CONFIG, checkExtensionDirSafety, checkExtensionPathSaf
7
7
  import { SlotRegistry, getSlotRegistry, registerSlotType } from "../slots.js";
8
8
  import { ExtensionDiagnostics, ExtensionLoaderCacheImpl, getExtensionCache, getExtensionDiagnostics } from "../diagnostics.js";
9
9
  import { ExtensionHookRunner, createHookContext, isHookEvent } from "../hooks.js";
10
- import { defineChannelPluginEntry } from "./channel-entry.js";
11
10
  import { registerExtensionCliProgram } from "./channel-helpers.js";
11
+ import { defineChannelPluginEntry } from "./channel-entry.js";
12
12
  import { lazyFunction, lazyModule } from "./lazy.js";
13
13
  import { createMockExtensionApi, createTestGateway } from "./testing.js";
14
14
  //#region src/extensions/sdk/index.ts
@@ -277,4 +277,4 @@ export declare const GATEWAY_BUILTIN_TOOLS: readonly [{
277
277
  readonly zh: "使用已验证的参数执行选定的外部工具。";
278
278
  };
279
279
  }];
280
- export declare const GATEWAY_BUILTIN_TOOL_IDS: ("automation" | "workflow" | "find" | "image" | "knowledge_search" | "knowledge_get" | "knowledge_write" | "user_context_search" | "user_context_get" | "user_context_update" | "web_search" | "web_fetch" | "browser_use" | "grep" | "session_search" | "read_file" | "list_dir" | "write_file" | "apply_patch" | "exec_command" | "update_plan" | "todo" | "clarify" | "xopc_tool_execute" | "web_extract" | "tool_manual" | "session_status" | "read_media" | "xopc_tool_search" | "xopc_tool_describe" | "image_generate" | "skills_list" | "skill_view" | "skill_manage" | "skills_marketplace_search" | "computer_use" | "send_message" | "text_to_speech" | "execute_code" | "send_media" | "create_share" | "memory_maintenance" | "delegate_task" | "skill_install" | "create_desktop_pet")[];
280
+ export declare const GATEWAY_BUILTIN_TOOL_IDS: ("automation" | "workflow" | "find" | "image" | "knowledge_search" | "knowledge_get" | "knowledge_write" | "user_context_search" | "user_context_get" | "user_context_update" | "web_search" | "web_fetch" | "browser_use" | "grep" | "session_search" | "read_file" | "list_dir" | "write_file" | "apply_patch" | "exec_command" | "update_plan" | "todo" | "web_extract" | "clarify" | "xopc_tool_execute" | "tool_manual" | "session_status" | "read_media" | "xopc_tool_search" | "xopc_tool_describe" | "image_generate" | "skills_list" | "skill_view" | "skill_manage" | "skills_marketplace_search" | "computer_use" | "send_message" | "text_to_speech" | "execute_code" | "send_media" | "create_share" | "memory_maintenance" | "delegate_task" | "skill_install" | "create_desktop_pet")[];
@@ -6,6 +6,8 @@ export type GlobalDefaultsPayload = {
6
6
  };
7
7
  export type UpdateGlobalDefaultsBody = {
8
8
  defaults: AgentDefaults;
9
+ scope?: 'models' | 'agent';
10
+ expectedModels?: AgentDefaults['models'];
9
11
  };
10
12
  export type GlobalDefaultsAdminResult<T> = {
11
13
  ok: true;
@@ -13,7 +15,7 @@ export type GlobalDefaultsAdminResult<T> = {
13
15
  } | {
14
16
  ok: false;
15
17
  error: string;
16
- status?: 400 | 404 | 500;
18
+ status?: 400 | 404 | 409 | 500;
17
19
  };
18
20
  export declare function listGlobalDefaults(): GlobalDefaultsPayload;
19
21
  export declare function prepareUpdateGlobalDefaults(body: UpdateGlobalDefaultsBody): GlobalDefaultsAdminResult<{
@@ -18,13 +18,25 @@ function listGlobalDefaults() {
18
18
  };
19
19
  }
20
20
  function prepareUpdateGlobalDefaults(body) {
21
- const parsed = AgentDefaultsSchema.safeParse(body.defaults);
21
+ const current = new AgentCatalogRepository().getSettings().defaults;
22
+ if (body.expectedModels && !isDeepStrictEqual(current.models, body.expectedModels)) return {
23
+ ok: false,
24
+ error: "Model settings changed. Refresh before retrying.",
25
+ status: 409
26
+ };
27
+ const requested = body.scope === "models" ? {
28
+ ...current,
29
+ models: body.defaults.models
30
+ } : body.scope === "agent" ? {
31
+ ...body.defaults,
32
+ models: current.models
33
+ } : body.defaults;
34
+ const parsed = AgentDefaultsSchema.safeParse(requested);
22
35
  if (!parsed.success) return {
23
36
  ok: false,
24
37
  error: `defaults ${parsed.error.issues[0]?.message ?? "is invalid"}`,
25
38
  status: 400
26
39
  };
27
- const current = new AgentCatalogRepository().getSettings().defaults;
28
40
  try {
29
41
  validateComputerModelChange(parsed.data.models.computerUse, current.models.computerUse);
30
42
  } catch (error) {
@@ -27,7 +27,11 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
27
27
  primary: string;
28
28
  fallbacks: string[];
29
29
  };
30
- intents?: Partial<Record<"review" | "coding" | "fast" | "reasoning" | "vision" | "understanding", {
30
+ background?: {
31
+ primary: string;
32
+ fallbacks: string[];
33
+ };
34
+ intents?: Partial<Record<"review" | "coding" | "vision" | "fast" | "reasoning" | "understanding", {
31
35
  primary: string;
32
36
  fallbacks: string[];
33
37
  }>>;
@@ -71,10 +75,14 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
71
75
  primary: string;
72
76
  fallbacks: string[];
73
77
  };
74
- intents: Partial<Record<"review" | "coding" | "fast" | "reasoning" | "vision" | "understanding", {
78
+ intents: Partial<Record<"review" | "coding" | "vision" | "fast" | "reasoning" | "understanding", {
75
79
  primary: string;
76
80
  fallbacks: string[];
77
81
  }>>;
82
+ background?: {
83
+ primary: string;
84
+ fallbacks: string[];
85
+ };
78
86
  imageUnderstanding?: {
79
87
  primary: string;
80
88
  fallbacks: string[];
@@ -320,6 +328,7 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
320
328
  betaCheckIntervalHours: number;
321
329
  };
322
330
  };
331
+ voiceSettingsRevisions: Record<"conversation" | "transcription" | "speech", string>;
323
332
  stt: unknown;
324
333
  tts: unknown;
325
334
  voice: unknown;