@xopcai/xopc 0.0.208 → 0.0.211

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 (316) 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-D0mYZqhc.js → activity-store-BzjFoSr0.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-MWLQWL_i.js → agent-avatar-dicebear-DTfjhfVE.js} +1 -1
  5. package/dist/gateway/static/root/assets/agents-CjhgfuVJ.js +68 -0
  6. package/dist/gateway/static/root/assets/{api-DZA1yVzM.js → api-D269PnU9.js} +1 -1
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-B2X6quAF.js → app-management-settings-panel-BFpfQDWc.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-BZW-c38q.js → appearance-settings-DLxFdqhY.js} +1 -1
  9. package/dist/gateway/static/root/assets/apps-page-CjmlGB5V.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-CK-gsjsJ.js → archive-plugin-DPlH4dnc.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-EJGP4rCw.js → attachment-load-xqfLLd0I.js} +1 -1
  12. package/dist/gateway/static/root/assets/automations-page-4m6Ey6wG.js +6 -0
  13. package/dist/gateway/static/root/assets/{binary-plugins-Tbss_4P-.js → binary-plugins-C0tuoPXk.js} +1 -1
  14. package/dist/gateway/static/root/assets/{block-editor-C-dOWigw.js → block-editor-Deyphj1o.js} +6 -6
  15. package/dist/gateway/static/root/assets/browser-settings-page-CAGCYx8U.js +8 -0
  16. package/dist/gateway/static/root/assets/{browser-workflow-inputs-DW06Zo1N.js → browser-workflow-inputs-CYEbXyRF.js} +1 -1
  17. package/dist/gateway/static/root/assets/{browser-workflows-page-B6RnRGwm.js → browser-workflows-page-Bf0tPbGi.js} +2 -2
  18. package/dist/gateway/static/root/assets/capabilities-settings-panel-CKfLsxTI.js +7 -0
  19. package/dist/gateway/static/root/assets/{capability-presets-api-Cc3BtQar.js → capability-presets-api-DPkFA_-R.js} +1 -1
  20. package/dist/gateway/static/root/assets/capability-presets-settings-panel-CpipKNqX.js +3 -0
  21. package/dist/gateway/static/root/assets/{channel-recipient-api-BvZO5FaO.js → channel-recipient-api-DqKaAcnZ.js} +1 -1
  22. package/dist/gateway/static/root/assets/channels-settings-Bvq-O4pt.js +1 -0
  23. package/dist/gateway/static/root/assets/channels-status-swr-CrMld2l7.js +1 -0
  24. package/dist/gateway/static/root/assets/chat-terminal-dock-CTDRZa7e.js +36 -0
  25. package/dist/gateway/static/root/assets/{connectors-api-CUl6_EQJ.js → connectors-api-Buu8fif8.js} +1 -1
  26. package/dist/gateway/static/root/assets/connectors-page-CSQRzaVn.js +2 -0
  27. package/dist/gateway/static/root/assets/{cron-expression-BD9MgoE_.js → cron-expression-DTLR82NB.js} +1 -1
  28. package/dist/gateway/static/root/assets/{date-picker-ChqNmoxw.js → date-picker-DyNogHQH.js} +1 -1
  29. package/dist/gateway/static/root/assets/{dependency-picker-CDUmFs6H.js → dependency-picker-BpnCuo7B.js} +1 -1
  30. package/dist/gateway/static/root/assets/{desktop-pet-D61gqxaD.js → desktop-pet-CDKI4gVB.js} +1 -1
  31. package/dist/gateway/static/root/assets/{desktop-pet-settings-QvuJvIX_.js → desktop-pet-settings-DjT5C2a3.js} +1 -1
  32. package/dist/gateway/static/root/assets/{directory-picker-path-field-DvXMvDNY.js → directory-picker-path-field-DlJY90TM.js} +1 -1
  33. package/dist/gateway/static/root/assets/{extension-debug-page-DMdVTAQ3.js → extension-debug-page-DWf2z7q5.js} +1 -1
  34. package/dist/gateway/static/root/assets/{extension-page-BNzxZtaK.js → extension-page-Dorx0kf9.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-settings-page-DoEfyizU.js → extension-settings-page-B1wU9ZOB.js} +1 -1
  36. package/dist/gateway/static/root/assets/{gateway-config-api-o7AKvthC.js → gateway-config-api-B1lG4dNr.js} +1 -1
  37. package/dist/gateway/static/root/assets/{gateway-config-swr-BQbkUP5X.js → gateway-config-swr-BIxuwPQi.js} +1 -1
  38. package/dist/gateway/static/root/assets/{gateway-settings-TO5YYZ9a.js → gateway-settings-DqIOqJjM.js} +1 -1
  39. package/dist/gateway/static/root/assets/{gateway-startup-retry-DIgdpHgk.js → gateway-startup-retry-BpZgd4U-.js} +1 -1
  40. package/dist/gateway/static/root/assets/heartbeat-settings-DG4Kmgkc.js +1 -0
  41. package/dist/gateway/static/root/assets/home-page-BhqItS_s.js +1 -0
  42. package/dist/gateway/static/root/assets/image-generation-api-PkhYohDa.js +1 -0
  43. package/dist/gateway/static/root/assets/index-DLhvsU9B.css +2 -0
  44. package/dist/gateway/static/root/assets/index-_cuTcWjB.js +107 -0
  45. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-4xaM3jjU.js → keyboard-shortcuts-settings-6OQT3gQF.js} +1 -1
  46. package/dist/gateway/static/root/assets/local-app-workbench-page-DWjTmzxw.js +2 -0
  47. package/dist/gateway/static/root/assets/{local-apps-page-C1xDicdr.js → local-apps-page-DfruRAmE.js} +1 -1
  48. package/dist/gateway/static/root/assets/{locale-store-pByvK12G.js → locale-store-C5MK9WcP.js} +1 -1
  49. package/dist/gateway/static/root/assets/logs-page-BA5efZ8B.js +2 -0
  50. package/dist/gateway/static/root/assets/{management-settings-D1XdHm7v.js → management-settings-L1VYkywO.js} +1 -1
  51. package/dist/gateway/static/root/assets/{markdown-split-B_Ijq1Fr.js → markdown-split-oqgHbqt-.js} +1 -1
  52. package/dist/gateway/static/root/assets/markdown-view-DD_PgVue.css +1 -0
  53. package/dist/gateway/static/root/assets/{markdown-view-CyJlGUxB.js → markdown-view-V4rcPPH0.js} +1 -1
  54. package/dist/gateway/static/root/assets/{media-plugins-CXXNRROJ.js → media-plugins-Bb6gSX2o.js} +1 -1
  55. package/dist/gateway/static/root/assets/messages-ctG2e-ix.js +3 -0
  56. package/dist/gateway/static/root/assets/{notes-page-rkePB4CB.js → notes-page-B1rOXjpT.js} +1 -1
  57. package/dist/gateway/static/root/assets/notes-workbench-CkHXVmKP.js +4 -0
  58. package/dist/gateway/static/root/assets/{page-tabs-gw-RMQCV.js → page-tabs-CBuCKeyy.js} +1 -1
  59. package/dist/gateway/static/root/assets/{preview-open-alternatives-B8aMScJ2.js → preview-open-alternatives-BQ0tLfPO.js} +1 -1
  60. package/dist/gateway/static/root/assets/{product-open-page-CjcpkWAz.js → product-open-page-DPeFn7Hu.js} +1 -1
  61. package/dist/gateway/static/root/assets/project-detail-page-DCqet9-L.js +1 -0
  62. package/dist/gateway/static/root/assets/projects-page-D0t_AjzG.js +1 -0
  63. package/dist/gateway/static/root/assets/remote-access-hub-BUWPoBvw.js +1 -0
  64. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-Ch5qq86o.js → runtime-tools-settings-panel-BCfQNzjG.js} +2 -2
  65. package/dist/gateway/static/root/assets/{schema-form-DHYWYUFt.js → schema-form-Bo7YbHYN.js} +1 -1
  66. package/dist/gateway/static/root/assets/sessions-page-vLhrrM3m.js +1 -0
  67. package/dist/gateway/static/root/assets/settings-advanced-gate-OP1y0Y8M.js +1 -0
  68. package/dist/gateway/static/root/assets/{settings-form-section-DlzZx0-i.js → settings-form-section-B9dnKr3M.js} +1 -1
  69. package/dist/gateway/static/root/assets/{settings-loading-skeleton-BVLhreQi.js → settings-loading-skeleton-CYDV2JtY.js} +1 -1
  70. package/dist/gateway/static/root/assets/{settings-page-BJU-kUnN.js → settings-page-DbrIYfS9.js} +1 -1
  71. package/dist/gateway/static/root/assets/setup-status-panel-Cxc-Ejl5.js +1 -0
  72. package/dist/gateway/static/root/assets/{share-preview-page-hvIuZXMe.js → share-preview-page-olgr7LLN.js} +1 -1
  73. package/dist/gateway/static/root/assets/shares-settings-ZOqC6-aA.js +1 -0
  74. package/dist/gateway/static/root/assets/skill-reload-api-DwvC3Iuf.js +1 -0
  75. package/dist/gateway/static/root/assets/{skills-page-Dlvuh7D-.js → skills-page-PE16CNw5.js} +1 -1
  76. package/dist/gateway/static/root/assets/{skills-page.utils-B6ddOpnf.js → skills-page.utils-nXmBcBxt.js} +1 -1
  77. package/dist/gateway/static/root/assets/{system-settings-panel-BdbCAyoA.js → system-settings-panel-C3qPwAdY.js} +1 -1
  78. package/dist/gateway/static/root/assets/task-detail-page-DCRB-5q-.js +1 -0
  79. package/dist/gateway/static/root/assets/{theme-store-BtdGacMI.js → theme-store-KR5Otp5w.js} +1 -1
  80. package/dist/gateway/static/root/assets/{typed-models-lib-CL6qHYJA.js → typed-models-lib-lMZodtDF.js} +1 -1
  81. package/dist/gateway/static/root/assets/{use-autosave-DysNnqCS.js → use-autosave-CKpatP3S.js} +1 -1
  82. package/dist/gateway/static/root/assets/user-context-page-CoiedRuA.js +1 -0
  83. package/dist/gateway/static/root/assets/{voice-api-key-field-UEsO9Jr-.js → voice-api-key-field-CDcv0Wbh.js} +1 -1
  84. package/dist/gateway/static/root/assets/{work-discovery-overlay-B9disASf.js → work-discovery-overlay-CGdT22un.js} +1 -1
  85. package/dist/gateway/static/root/assets/work-discovery-page-BwaU1RqI.js +1 -0
  86. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-A0zTQHFQ.js → workflow-run-setup-panel-BAHYNlQt.js} +2 -2
  87. package/dist/gateway/static/root/assets/workflows-page-DHYmh9G7.js +5 -0
  88. package/dist/gateway/static/root/index.html +10 -10
  89. package/dist/package.js +1 -1
  90. package/dist/src/agent/agent-manager.js +1 -1
  91. package/dist/src/agent/background-review/coordinator.d.ts +1 -1
  92. package/dist/src/agent/background-review/coordinator.js +4 -5
  93. package/dist/src/agent/background-review/run-background-review.js +0 -1
  94. package/dist/src/agent/background-review/settings.d.ts +1 -2
  95. package/dist/src/agent/background-review/settings.js +3 -4
  96. package/dist/src/agent/external-tools/composio-provider.js +8 -4
  97. package/dist/src/agent/image/generation/providers/xopc-cloud.js +2 -1
  98. package/dist/src/agent/image/tool-model-config.js +15 -9
  99. package/dist/src/agent/memory/builtin-provider.js +1 -2
  100. package/dist/src/agent/memory/manager.js +2 -0
  101. package/dist/src/agent/memory/sensitivity.js +1 -1
  102. package/dist/src/agent/memory/understanding/service.js +43 -19
  103. package/dist/src/agent/memory/user-context-coordinator.js +1 -1
  104. package/dist/src/agent/tools/image-generate-tool.js +23 -7
  105. package/dist/src/automations/domain/validation.d.ts +7 -7
  106. package/dist/src/automations/draft/automation-draft-validator.d.ts +2 -2
  107. package/dist/src/capabilities/readiness/from-config.d.ts +10 -0
  108. package/dist/src/capabilities/readiness/from-config.js +128 -0
  109. package/dist/src/capabilities/readiness/index.d.ts +3 -0
  110. package/dist/src/capabilities/readiness/index.js +3 -0
  111. package/dist/src/capabilities/readiness/planner.d.ts +3 -0
  112. package/dist/src/capabilities/readiness/planner.js +56 -0
  113. package/dist/src/capabilities/readiness/types.d.ts +35 -0
  114. package/dist/src/capabilities/readiness/types.js +1 -0
  115. package/dist/src/cli/commands/agent.js +9 -0
  116. package/dist/src/cli/commands/auth.js +4 -3
  117. package/dist/src/cli/commands/connectors.js +1 -1
  118. package/dist/src/cli/commands/models.js +2 -1
  119. package/dist/src/cli/commands/onboard/model.d.ts +3 -21
  120. package/dist/src/cli/commands/onboard/model.js +10 -86
  121. package/dist/src/cli/utils/oauth-login.d.ts +2 -0
  122. package/dist/src/cli/utils/oauth-login.js +9 -1
  123. package/dist/src/config/agent-profile.js +1 -1
  124. package/dist/src/config/index.js +2 -2
  125. package/dist/src/config/paths-state.d.ts +2 -0
  126. package/dist/src/config/paths-state.js +5 -1
  127. package/dist/src/config/paths.d.ts +1 -1
  128. package/dist/src/config/paths.js +2 -2
  129. package/dist/src/config/schema.js +1 -1
  130. package/dist/src/connectors/auth-provider-registry.d.ts +2 -1
  131. package/dist/src/connectors/auth-provider-registry.js +5 -2
  132. package/dist/src/connectors/composio-sessions.d.ts +39 -0
  133. package/dist/src/connectors/composio-sessions.js +66 -7
  134. package/dist/src/connectors/composio.d.ts +4 -1
  135. package/dist/src/connectors/composio.js +34 -7
  136. package/dist/src/connectors/connected-source-cursor.d.ts +9 -0
  137. package/dist/src/connectors/connected-source-cursor.js +30 -0
  138. package/dist/src/connectors/connected-source-ingestion.js +67 -46
  139. package/dist/src/connectors/connected-source-normalizers.d.ts +1 -0
  140. package/dist/src/connectors/connected-source-normalizers.js +33 -2
  141. package/dist/src/connectors/connected-source-sanitization.d.ts +1 -0
  142. package/dist/src/connectors/connected-source-sanitization.js +21 -0
  143. package/dist/src/connectors/connector-identity.js +10 -2
  144. package/dist/src/connectors/content-enrichment.d.ts +29 -0
  145. package/dist/src/connectors/content-enrichment.js +273 -0
  146. package/dist/src/connectors/health.js +1 -1
  147. package/dist/src/connectors/learning-coordinator.js +1 -2
  148. package/dist/src/connectors/learning-recipes.js +28 -33
  149. package/dist/src/connectors/runtime-adapter-registry.js +14 -1
  150. package/dist/src/discussions/live-worker.d.ts +1 -0
  151. package/dist/src/discussions/live-worker.js +7 -1
  152. package/dist/src/discussions/repository.js +11 -1
  153. package/dist/src/discussions/sealer.d.ts +1 -1
  154. package/dist/src/discussions/sealer.js +16 -7
  155. package/dist/src/discussions/transcript.js +27 -1
  156. package/dist/src/discussions/types.d.ts +4 -0
  157. package/dist/src/gateway/agents-admin.js +1 -1
  158. package/dist/src/gateway/hono/app.js +8 -3
  159. package/dist/src/gateway/hono/middleware/strict-rate-limit.d.ts +4 -0
  160. package/dist/src/gateway/hono/middleware/strict-rate-limit.js +8 -1
  161. package/dist/src/gateway/hono/oauth-async.d.ts +11 -5
  162. package/dist/src/gateway/hono/oauth-async.js +29 -16
  163. package/dist/src/gateway/hono/oauth.d.ts +1 -3
  164. package/dist/src/gateway/hono/oauth.js +22 -22
  165. package/dist/src/gateway/hono/routes/agent-stream.js +4 -1
  166. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  167. package/dist/src/gateway/hono/routes/connectors.js +16 -3
  168. package/dist/src/gateway/hono/routes/deps.d.ts +1 -0
  169. package/dist/src/gateway/hono/routes/discussions.js +2 -1
  170. package/dist/src/gateway/hono/routes/lazy-bundles.js +2 -1
  171. package/dist/src/gateway/hono/routes/mcp.js +1 -1
  172. package/dist/src/gateway/hono/routes/models.js +59 -5
  173. package/dist/src/gateway/hono/routes/session-input-handler.d.ts +60 -0
  174. package/dist/src/gateway/hono/routes/session-input-handler.js +75 -1
  175. package/dist/src/gateway/hono/routes/understanding-sources.js +29 -0
  176. package/dist/src/gateway/hono/routes/voice.d.ts +1 -2
  177. package/dist/src/gateway/hono/routes/voice.js +16 -35
  178. package/dist/src/gateway/rate-limit/buckets.d.ts +3 -0
  179. package/dist/src/gateway/rate-limit/buckets.js +12 -0
  180. package/dist/src/gateway/service/agent-runner.d.ts +9 -1
  181. package/dist/src/gateway/service/agent-runner.js +9 -0
  182. package/dist/src/gateway/service/session-input-coordinator.d.ts +12 -0
  183. package/dist/src/gateway/service/session-input-coordinator.js +63 -6
  184. package/dist/src/gateway/service.d.ts +8 -0
  185. package/dist/src/gateway/service.js +18 -0
  186. package/dist/src/knowledge/connected-understanding-pipeline.d.ts +1 -1
  187. package/dist/src/knowledge/connected-understanding-pipeline.js +74 -25
  188. package/dist/src/knowledge/ingestion-service.js +33 -15
  189. package/dist/src/knowledge/types.d.ts +2 -0
  190. package/dist/src/media-understanding/audio-transcription-runner.d.ts +2 -0
  191. package/dist/src/media-understanding/audio-transcription-runner.js +3 -1
  192. package/dist/src/media-understanding/runner.js +3 -1
  193. package/dist/src/media-understanding/types.d.ts +2 -0
  194. package/dist/src/providers/model-catalog-persistence.d.ts +9 -0
  195. package/dist/src/providers/model-catalog-persistence.js +172 -0
  196. package/dist/src/providers/model-catalog-ranking.d.ts +2 -0
  197. package/dist/src/providers/model-catalog-ranking.js +17 -0
  198. package/dist/src/providers/model-catalog-store.d.ts +13 -3
  199. package/dist/src/providers/model-catalog-store.js +24 -5
  200. package/dist/src/providers/model-catalog-sync-service.d.ts +3 -3
  201. package/dist/src/providers/model-catalog-sync-service.js +12 -7
  202. package/dist/src/providers/provider-auth-service.d.ts +1 -0
  203. package/dist/src/providers/provider-auth-service.js +3 -0
  204. package/dist/src/providers/provider-disconnect.d.ts +11 -0
  205. package/dist/src/providers/provider-disconnect.js +33 -0
  206. package/dist/src/providers/xopc-cloud-catalog-coordinator.d.ts +56 -0
  207. package/dist/src/providers/xopc-cloud-catalog-coordinator.js +182 -0
  208. package/dist/src/providers/xopc-cloud-model-source.d.ts +6 -10
  209. package/dist/src/providers/xopc-cloud-model-source.js +49 -27
  210. package/dist/src/retrieval/audit.d.ts +1 -0
  211. package/dist/src/retrieval/audit.js +8 -0
  212. package/dist/src/retrieval/candidateFusion.d.ts +5 -0
  213. package/dist/src/retrieval/candidateFusion.js +20 -0
  214. package/dist/src/retrieval/queryProfile.d.ts +16 -0
  215. package/dist/src/retrieval/queryProfile.js +66 -0
  216. package/dist/src/retrieval/textFeatures.d.ts +5 -0
  217. package/dist/src/retrieval/textFeatures.js +71 -0
  218. package/dist/src/session/client-history.d.ts +1 -0
  219. package/dist/src/session/client-history.js +4 -0
  220. package/dist/src/session/index.js +1 -1
  221. package/dist/src/session/store.js +1 -1
  222. package/dist/src/storage/sqlite/fts.d.ts +0 -4
  223. package/dist/src/storage/sqlite/fts.js +2 -49
  224. package/dist/src/storage/sqlite/index.d.ts +3 -2
  225. package/dist/src/storage/sqlite/index.js +6 -5
  226. package/dist/src/storage/sqlite/knowledge-repository.d.ts +1 -0
  227. package/dist/src/storage/sqlite/knowledge-repository.js +4 -0
  228. package/dist/src/storage/sqlite/memory-records-repository.js +60 -38
  229. package/dist/src/storage/sqlite/row-mappers.js +2 -2
  230. package/dist/src/storage/sqlite/session-repository.js +2 -2
  231. package/dist/src/storage/sqlite/session-turn-replace-repository.d.ts +34 -0
  232. package/dist/src/storage/sqlite/session-turn-replace-repository.js +110 -0
  233. package/dist/src/storage/sqlite/transcript-repository.js +1 -1
  234. package/dist/src/storage/sqlite/user-context-quality-repository.d.ts +15 -0
  235. package/dist/src/storage/sqlite/user-context-quality-repository.js +46 -2
  236. package/dist/src/storage/sqlite/user-context-repository.d.ts +4 -0
  237. package/dist/src/storage/sqlite/user-context-repository.js +29 -3
  238. package/dist/src/tasks/home-query-service.d.ts +3 -1
  239. package/dist/src/tasks/home-query-service.js +73 -70
  240. package/dist/src/tui/backends/embedded-backend.js +12 -4
  241. package/dist/src/tui/tui-oauth-login.js +5 -0
  242. package/dist/src/tui/tui-startup-resources.js +1 -1
  243. package/dist/src/user-context/planner.d.ts +1 -0
  244. package/dist/src/user-context/planner.js +16 -29
  245. package/dist/src/user-context/retriever.d.ts +15 -0
  246. package/dist/src/user-context/retriever.js +65 -0
  247. package/dist/src/user-context/scope.d.ts +7 -0
  248. package/dist/src/user-context/scope.js +9 -0
  249. package/dist/src/user-context/sources/activity-clustering.js +30 -117
  250. package/dist/src/user-context/sources/index.d.ts +1 -0
  251. package/dist/src/user-context/sources/index.js +2 -1
  252. package/dist/src/user-context/sources/signal-clustering.d.ts +18 -0
  253. package/dist/src/user-context/sources/signal-clustering.js +131 -0
  254. package/dist/src/voice/audio/normalize.d.ts +17 -0
  255. package/dist/src/voice/audio/normalize.js +155 -0
  256. package/dist/src/voice/language-profile.d.ts +1 -4
  257. package/dist/src/voice/language-profile.js +2 -25
  258. package/dist/src/voice/local/runtime-client.d.ts +2 -0
  259. package/dist/src/voice/local/runtime-client.js +20 -1
  260. package/dist/src/voice/local/runtime-worker.js +7 -13
  261. package/dist/src/voice/local/wav.js +1 -1
  262. package/dist/src/voice/stt/availability.d.ts +1 -4
  263. package/dist/src/voice/stt/availability.js +3 -15
  264. package/dist/src/voice/stt/config.js +1 -0
  265. package/dist/src/voice/stt/factory.js +23 -0
  266. package/dist/src/voice/stt/index.d.ts +1 -0
  267. package/dist/src/voice/stt/index.js +2 -2
  268. package/dist/src/voice/stt/list-providers.js +1 -1
  269. package/dist/src/voice/stt/providers/local-transcription.js +7 -3
  270. package/dist/src/voice/stt/providers/xopc-cloud-transcription.js +3 -1
  271. package/dist/src/voice/stt/transcribe-core.d.ts +5 -1
  272. package/dist/src/voice/stt/transcribe-core.js +13 -5
  273. package/dist/src/voice/stt/types.d.ts +2 -0
  274. package/dist/src/voice/tts/factory.d.ts +1 -1
  275. package/dist/src/voice/tts/factory.js +23 -1
  276. package/dist/src/voice/tts/merge-config.js +5 -3
  277. package/dist/src/voice/tts/providers/xopc-cloud-speech.js +3 -1
  278. package/dist/src/voice/tts/types.d.ts +2 -0
  279. package/dist/src/voice/tts/types.js +4 -2
  280. package/dist/src/work-discovery/evaluation.d.ts +23 -0
  281. package/dist/src/work-discovery/evaluation.js +18 -1
  282. package/dist/src/work-discovery/index.js +2 -2
  283. package/package.json +4 -3
  284. package/dist/gateway/static/root/assets/agents-Bl8FQZxW.js +0 -68
  285. package/dist/gateway/static/root/assets/apps-page-CRUgTO10.js +0 -1
  286. package/dist/gateway/static/root/assets/automations-page-DrSwolhG.js +0 -6
  287. package/dist/gateway/static/root/assets/browser-settings-page-NlvDyMwD.js +0 -8
  288. package/dist/gateway/static/root/assets/capabilities-settings-panel-BWXUznw5.js +0 -7
  289. package/dist/gateway/static/root/assets/capability-presets-settings-panel-D0loEbzq.js +0 -3
  290. package/dist/gateway/static/root/assets/channels-settings-CcivCw8U.js +0 -1
  291. package/dist/gateway/static/root/assets/channels-status-swr-DkHAD2Zn.js +0 -1
  292. package/dist/gateway/static/root/assets/chat-terminal-dock-DVedGAeX.js +0 -36
  293. package/dist/gateway/static/root/assets/connectors-page-DlBSlfkv.js +0 -2
  294. package/dist/gateway/static/root/assets/heartbeat-settings-UZAn1aAQ.js +0 -1
  295. package/dist/gateway/static/root/assets/home-page-CRJDpy5E.js +0 -3
  296. package/dist/gateway/static/root/assets/index-BSjP0Wsx.css +0 -2
  297. package/dist/gateway/static/root/assets/index-C2ZYFBGL.js +0 -85
  298. package/dist/gateway/static/root/assets/local-app-workbench-page-D9bguWRo.js +0 -2
  299. package/dist/gateway/static/root/assets/logs-page-Gr-nE4nW.js +0 -2
  300. package/dist/gateway/static/root/assets/markdown-view-B12xeflb.css +0 -1
  301. package/dist/gateway/static/root/assets/messages-yG5P43Q9.js +0 -3
  302. package/dist/gateway/static/root/assets/notes-workbench-CpbD4XG2.js +0 -4
  303. package/dist/gateway/static/root/assets/project-detail-page-GvSYDbjR.js +0 -1
  304. package/dist/gateway/static/root/assets/projects-page-DPRxKGbs.js +0 -1
  305. package/dist/gateway/static/root/assets/remote-access-hub-WIzeu-gB.js +0 -1
  306. package/dist/gateway/static/root/assets/sessions-page-2XEJM0YE.js +0 -1
  307. package/dist/gateway/static/root/assets/settings-advanced-gate-g1GThZ0O.js +0 -1
  308. package/dist/gateway/static/root/assets/setup-status-panel-C6qj2L-q.js +0 -1
  309. package/dist/gateway/static/root/assets/shares-settings-BBpE1bep.js +0 -1
  310. package/dist/gateway/static/root/assets/skill-reload-api-DXORBJNk.js +0 -1
  311. package/dist/gateway/static/root/assets/task-detail-page-DC0hc8hp.js +0 -1
  312. package/dist/gateway/static/root/assets/user-context-page-Bwg4KV8B.js +0 -1
  313. package/dist/gateway/static/root/assets/work-discovery-page-CmPfOfHl.js +0 -1
  314. package/dist/gateway/static/root/assets/workflows-page-DhQNh7W6.js +0 -5
  315. package/dist/src/voice/local/runtime-dispatcher.d.ts +0 -9
  316. package/dist/src/voice/local/runtime-dispatcher.js +0 -20
@@ -0,0 +1,65 @@
1
+ import { summarizeUnderstandingFeedback } from "../storage/sqlite/user-context-quality-repository.js";
2
+ import { listUnderstandings, searchActiveUnderstandings } from "../storage/sqlite/user-context-repository.js";
3
+ import { normalizeRetrievalText, retrievalLexicalSimilarity } from "../retrieval/textFeatures.js";
4
+ import { buildRetrievalQueryProfile } from "../retrieval/queryProfile.js";
5
+ import "../storage/sqlite/index.js";
6
+ import { matchesUserContextScope } from "./scope.js";
7
+ //#region src/user-context/retriever.ts
8
+ function authorityBonus(item) {
9
+ if (item.explicitness === "explicit") return .1;
10
+ if (item.explicitness === "observed") return .05;
11
+ return 0;
12
+ }
13
+ function baseline(item) {
14
+ if (item.kind === "boundary" && item.explicitness === "explicit") return .8;
15
+ if (item.kind === "preference" && item.explicitness === "explicit") return .35;
16
+ return 0;
17
+ }
18
+ function feedbackAdjustment(summary) {
19
+ if (!summary || summary.total < 3) return 0;
20
+ const helpfulRate = (summary.helpful + 1) / (summary.total + 2);
21
+ const relevancePenalty = summary.irrelevant >= 3 ? .05 : 0;
22
+ return Math.max(-.1, Math.min(.05, (helpfulRate - .5) * .1 - relevancePenalty));
23
+ }
24
+ var UserUnderstandingRetriever = class {
25
+ retrieve(params) {
26
+ const profile = buildRetrievalQueryProfile(params.query, {
27
+ sessionKey: params.sessionKey,
28
+ workspaceId: params.workspaceId,
29
+ ...params.projectId ? { projectId: params.projectId } : {}
30
+ });
31
+ if (!profile.normalized) return [];
32
+ const maxCandidates = Math.max(1, Math.min(200, Math.floor(params.maxCandidates)));
33
+ const fts = searchActiveUnderstandings(profile.normalized, Math.max(50, maxCandidates));
34
+ const ftsScores = new Map(fts.map((result) => [result.understanding.id, result.score]));
35
+ const recentLimit = Math.max(200, Math.min(500, maxCandidates * 5));
36
+ const recent = listUnderstandings(["active"]).slice(0, recentLimit);
37
+ const candidates = /* @__PURE__ */ new Map();
38
+ for (const result of fts) candidates.set(result.understanding.id, result.understanding);
39
+ for (const item of recent) candidates.set(item.id, item);
40
+ const feedback = new Map(summarizeUnderstandingFeedback([...candidates.keys()]).map((summary) => [summary.understandingId, summary]));
41
+ return [...candidates.values()].map((item) => {
42
+ const lexical = retrievalLexicalSimilarity(profile.normalized, item.statement);
43
+ const ftsScore = ftsScores.get(item.id) ?? 0;
44
+ const textScore = Math.max(lexical, ftsScore);
45
+ const kindMatched = profile.intentKinds.includes(item.kind);
46
+ const normalizedStatement = normalizeRetrievalText(item.statement);
47
+ const identifierMatched = profile.identifiers.some((identifier) => normalizedStatement.includes(identifier));
48
+ const feedbackScore = feedbackAdjustment(feedback.get(item.id));
49
+ return {
50
+ understanding: item,
51
+ score: Math.min(1, Math.max(0, Math.max(baseline(item), textScore * .7 + lexical * .1 + item.confidence * .1 + authorityBonus(item) + (kindMatched ? .08 : 0) + (identifierMatched ? .12 : 0) + (matchesUserContextScope(item.scope, params) && item.scope.type !== "global" ? .05 : 0)) + feedbackScore)),
52
+ reasons: [
53
+ ftsScore > 0 ? "fts" : "",
54
+ lexical > 0 ? "lexical" : "",
55
+ identifierMatched ? "identifier" : "",
56
+ kindMatched ? "kind" : "",
57
+ item.explicitness === "explicit" ? "explicit" : "",
58
+ feedbackScore !== 0 ? "feedback" : ""
59
+ ].filter(Boolean)
60
+ };
61
+ }).sort((left, right) => Number(matchesUserContextScope(right.understanding.scope, params)) - Number(matchesUserContextScope(left.understanding.scope, params)) || right.score - left.score || right.understanding.updatedAt - left.understanding.updatedAt).slice(0, maxCandidates);
62
+ }
63
+ };
64
+ //#endregion
65
+ export { UserUnderstandingRetriever };
@@ -0,0 +1,7 @@
1
+ import type { UserContextScope } from './domain.js';
2
+ export interface UserContextScopeTarget {
3
+ sessionKey: string;
4
+ workspaceId: string;
5
+ projectId?: string;
6
+ }
7
+ export declare function matchesUserContextScope(scope: UserContextScope, target: UserContextScopeTarget): boolean;
@@ -0,0 +1,9 @@
1
+ //#region src/user-context/scope.ts
2
+ function matchesUserContextScope(scope, target) {
3
+ if (scope.type === "global") return true;
4
+ if (scope.type === "session") return scope.id === target.sessionKey;
5
+ if (scope.type === "workspace") return scope.id === target.workspaceId;
6
+ return Boolean(target.projectId && scope.id === target.projectId);
7
+ }
8
+ //#endregion
9
+ export { matchesUserContextScope };
@@ -1,130 +1,43 @@
1
- import { createHash } from "node:crypto";
1
+ import { clusterUnderstandingSignals } from "./signal-clustering.js";
2
2
  //#region src/user-context/sources/activity-clustering.ts
3
- const STOP_WORDS = new Set([
4
- "about",
5
- "and",
6
- "bookmark",
7
- "bookmarks",
8
- "desktop",
9
- "document",
10
- "documents",
11
- "download",
12
- "downloads",
13
- "file",
14
- "files",
15
- "from",
16
- "guide",
17
- "home",
18
- "index",
19
- "into",
20
- "latest",
21
- "new",
22
- "notes",
23
- "official",
24
- "overview",
25
- "page",
26
- "plan",
27
- "profile",
28
- "project",
29
- "recent",
30
- "roadmap",
31
- "the",
32
- "this",
33
- "with",
34
- "www"
35
- ]);
36
3
  function activityTimestamp(item) {
37
4
  return item.modifiedAt ?? item.occurredAt ?? item.startsAt ?? 0;
38
5
  }
39
- function tokenize(value) {
40
- const normalized = value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").toLocaleLowerCase().replace(/\.[a-z0-9]{1,8}$/i, "").replace(/https?:\/\//g, " ");
41
- const tokens = /* @__PURE__ */ new Set();
42
- for (const token of normalized.match(/[a-z0-9][a-z0-9-]{2,}|[\p{Script=Han}]{2,}/gu) ?? []) {
43
- if (/^[\p{Script=Han}]+$/u.test(token)) {
44
- if (token.length <= 4) tokens.add(token);
45
- else for (let index = 0; index < token.length - 1; index += 1) tokens.add(token.slice(index, index + 2));
46
- continue;
47
- }
48
- const clean = token.replace(/^-+|-+$/g, "");
49
- if (clean.length >= 3 && !STOP_WORDS.has(clean) && !/^\d+$/.test(clean)) tokens.add(clean);
6
+ function resourceHost(item) {
7
+ if (!item.resourceUri) return void 0;
8
+ try {
9
+ return new URL(item.resourceUri).hostname.replace(/^www\./, "") || void 0;
10
+ } catch {
11
+ return;
50
12
  }
51
- return tokens;
52
- }
53
- function itemTokens(item) {
54
- let host = "";
55
- if (item.resourceUri) try {
56
- host = new URL(item.resourceUri).hostname.replace(/^www\./, "");
57
- } catch {}
58
- return tokenize([
59
- item.title,
60
- item.group ?? "",
61
- host
62
- ].join(" "));
63
- }
64
- function overlap(left, right) {
65
- let count = 0;
66
- for (const token of left) if (right.has(token)) count += 1;
67
- return count;
68
- }
69
- function related(left, right) {
70
- const shared = overlap(left.tokens, right.tokens);
71
- if (shared >= 2) return true;
72
- const smallest = Math.min(left.tokens.size, right.tokens.size);
73
- if (shared === 1 && smallest <= 2) return true;
74
- return Boolean(shared === 1 && left.item.group && left.item.group === right.item.group);
75
- }
76
- function displayTitle(cluster) {
77
- const frequency = /* @__PURE__ */ new Map();
78
- for (const entry of cluster) for (const token of entry.tokens) frequency.set(token, (frequency.get(token) ?? 0) + 1);
79
- const shared = [...frequency.entries()].filter(([, count]) => count >= 2).sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, 3).map(([token]) => token);
80
- if (shared.length && shared.every((token) => /^[\p{Script=Han}]+$/u.test(token))) return cluster[0].item.title.replace(/\.[a-z0-9]{1,8}$/i, "").slice(0, 80);
81
- if (shared.length) return shared.map((token) => token.charAt(0).toUpperCase() + token.slice(1)).join(" ");
82
- return cluster[0].item.title.replace(/\.[a-z0-9]{1,8}$/i, "").slice(0, 80);
83
13
  }
84
14
  function clusterActivityTopics(items, now = Date.now()) {
85
- const prepared = items.filter((item) => item.type === "document" || item.type === "bookmark").map((item) => ({
86
- item,
87
- tokens: itemTokens(item),
88
- timestamp: activityTimestamp(item)
89
- })).filter((entry) => entry.tokens.size > 0);
90
- const parent = prepared.map((_, index) => index);
91
- const find = (index) => parent[index] === index ? index : parent[index] = find(parent[index]);
92
- const union = (left, right) => {
93
- const leftRoot = find(left);
94
- const rightRoot = find(right);
95
- if (leftRoot !== rightRoot) parent[rightRoot] = leftRoot;
96
- };
97
- for (let left = 0; left < prepared.length; left += 1) for (let right = left + 1; right < prepared.length; right += 1) if (related(prepared[left], prepared[right])) union(left, right);
98
- const clusters = /* @__PURE__ */ new Map();
99
- prepared.forEach((entry, index) => clusters.set(find(index), [...clusters.get(find(index)) ?? [], entry]));
100
- return [...clusters.values()].flatMap((cluster) => {
101
- if (cluster.length < 2) return [];
102
- const sourceIds = [...new Set(cluster.map(({ item }) => item.sourceId))];
103
- const types = new Set(cluster.map(({ item }) => item.type));
104
- if (types.size === 1 && types.has("bookmark") && cluster.length < 3) return [];
105
- const newestAt = Math.max(...cluster.map(({ timestamp }) => timestamp));
106
- const ageDays = newestAt ? Math.max(0, (now - newestAt) / 864e5) : 90;
107
- const recency = Math.max(0, 1 - ageDays / 90);
108
- const confidence = Math.min(.92, .48 + Math.min(cluster.length, 5) * .06 + Math.min(sourceIds.length, 3) * .09 + recency * .08);
109
- const title = displayTitle(cluster);
110
- const fileCount = cluster.filter(({ item }) => item.type === "document").length;
111
- const bookmarkCount = cluster.length - fileCount;
112
- const evidenceRefs = cluster.map(({ item }) => item.evidenceRef);
113
- const sharedTokens = /* @__PURE__ */ new Map();
114
- for (const entry of cluster) for (const token of entry.tokens) sharedTokens.set(token, (sharedTokens.get(token) ?? 0) + 1);
115
- const stableTopicTokens = [...sharedTokens.entries()].filter(([, count]) => count >= 2).map(([token]) => token).sort();
116
- const key = createHash("sha256").update(stableTopicTokens.join("|")).digest("hex").slice(0, 16);
117
- const signals = [fileCount ? `${fileCount} recent file${fileCount === 1 ? "" : "s"}` : "", bookmarkCount ? `${bookmarkCount} bookmark${bookmarkCount === 1 ? "" : "s"}` : ""].filter(Boolean).join(" and ");
15
+ const eligible = items.filter((item) => item.type === "document" || item.type === "bookmark");
16
+ const byEvidenceRef = new Map(eligible.map((item) => [item.evidenceRef, item]));
17
+ return clusterUnderstandingSignals(eligible.map((item) => ({
18
+ evidenceRef: item.evidenceRef,
19
+ sourceId: item.sourceId,
20
+ title: item.title,
21
+ group: [item.group, resourceHost(item)].filter(Boolean).join(" ") || void 0,
22
+ occurredAt: activityTimestamp(item)
23
+ })), now).flatMap((cluster) => {
24
+ const sourceItems = cluster.signals.map((signal) => byEvidenceRef.get(signal.evidenceRef)).filter((item) => Boolean(item));
25
+ const types = new Set(sourceItems.map((item) => item.type));
26
+ if (types.size === 1 && types.has("bookmark") && sourceItems.length < 3) return [];
27
+ const fileCount = sourceItems.filter((item) => item.type === "document").length;
28
+ const bookmarkCount = sourceItems.length - fileCount;
29
+ const evidenceRefs = cluster.signals.map((signal) => signal.evidenceRef);
30
+ const evidenceSummary = [fileCount ? `${fileCount} recent file${fileCount === 1 ? "" : "s"}` : "", bookmarkCount ? `${bookmarkCount} bookmark${bookmarkCount === 1 ? "" : "s"}` : ""].filter(Boolean).join(" and ");
118
31
  return [{
119
- canonicalKey: `activity-focus:${key}`,
120
- title,
121
- summary: `${signals} suggest sustained attention to ${title}.`,
122
- horizon: ageDays <= 14 ? "current" : "ongoing",
123
- confidence,
32
+ canonicalKey: `activity-focus:${cluster.key}`,
33
+ title: cluster.title,
34
+ summary: `${evidenceSummary} suggest sustained attention to ${cluster.title}.`,
35
+ horizon: cluster.horizon,
36
+ confidence: cluster.confidence,
124
37
  evidenceRefs,
125
- sourceIds
38
+ sourceIds: cluster.sourceIds
126
39
  }];
127
- }).sort((left, right) => right.confidence - left.confidence);
40
+ });
128
41
  }
129
42
  //#endregion
130
43
  export { clusterActivityTopics };
@@ -1,3 +1,4 @@
1
1
  export * from './catalog.js';
2
2
  export * from './repository.js';
3
+ export * from './signal-clustering.js';
3
4
  export * from './types.js';
@@ -1,3 +1,4 @@
1
1
  import { createUnderstandingSourceRun, deleteUserFocus, getUnderstandingSourceGrant, getUnderstandingSourceRun, listUnderstandingSourceGrants, listUnderstandingSourceRuns, listUserFocuses, revokeUnderstandingSourceGrant, setUserFocusStatus, updateUnderstandingSourceGrantCheckpoint, updateUnderstandingSourceRun, upsertUnderstandingSourceGrant, upsertUserFocus } from "./repository.js";
2
+ import { clusterUnderstandingSignals, tokenizeUnderstandingSignal } from "./signal-clustering.js";
2
3
  import { listUnderstandingSourceDefinitions } from "./catalog.js";
3
- export { createUnderstandingSourceRun, deleteUserFocus, getUnderstandingSourceGrant, getUnderstandingSourceRun, listUnderstandingSourceDefinitions, listUnderstandingSourceGrants, listUnderstandingSourceRuns, listUserFocuses, revokeUnderstandingSourceGrant, setUserFocusStatus, updateUnderstandingSourceGrantCheckpoint, updateUnderstandingSourceRun, upsertUnderstandingSourceGrant, upsertUserFocus };
4
+ export { clusterUnderstandingSignals, createUnderstandingSourceRun, deleteUserFocus, getUnderstandingSourceGrant, getUnderstandingSourceRun, listUnderstandingSourceDefinitions, listUnderstandingSourceGrants, listUnderstandingSourceRuns, listUserFocuses, revokeUnderstandingSourceGrant, setUserFocusStatus, tokenizeUnderstandingSignal, updateUnderstandingSourceGrantCheckpoint, updateUnderstandingSourceRun, upsertUnderstandingSourceGrant, upsertUserFocus };
@@ -0,0 +1,18 @@
1
+ export type UnderstandingSignal = {
2
+ evidenceRef: string;
3
+ sourceId: string;
4
+ title: string;
5
+ group?: string;
6
+ subjectKey?: string;
7
+ occurredAt?: number;
8
+ };
9
+ export type UnderstandingSignalCluster = {
10
+ key: string;
11
+ title: string;
12
+ confidence: number;
13
+ horizon: 'current' | 'ongoing';
14
+ signals: UnderstandingSignal[];
15
+ sourceIds: string[];
16
+ };
17
+ export declare function tokenizeUnderstandingSignal(value: string): Set<string>;
18
+ export declare function clusterUnderstandingSignals(signals: UnderstandingSignal[], now?: number): UnderstandingSignalCluster[];
@@ -0,0 +1,131 @@
1
+ import { createHash } from "node:crypto";
2
+ //#region src/user-context/sources/signal-clustering.ts
3
+ const STOP_WORDS = new Set([
4
+ "about",
5
+ "and",
6
+ "bookmark",
7
+ "bookmarks",
8
+ "desktop",
9
+ "document",
10
+ "documents",
11
+ "download",
12
+ "downloads",
13
+ "file",
14
+ "files",
15
+ "from",
16
+ "fwd",
17
+ "guide",
18
+ "home",
19
+ "index",
20
+ "into",
21
+ "latest",
22
+ "new",
23
+ "notes",
24
+ "official",
25
+ "overview",
26
+ "page",
27
+ "plan",
28
+ "profile",
29
+ "project",
30
+ "recent",
31
+ "reply",
32
+ "roadmap",
33
+ "the",
34
+ "this",
35
+ "with",
36
+ "www"
37
+ ]);
38
+ function normalizeKey(value) {
39
+ return value?.trim().toLocaleLowerCase() || void 0;
40
+ }
41
+ function tokenizeUnderstandingSignal(value) {
42
+ const normalized = value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").toLocaleLowerCase().replace(/\.[a-z0-9]{1,8}$/i, "").replace(/https?:\/\//g, " ");
43
+ const tokens = /* @__PURE__ */ new Set();
44
+ for (const token of normalized.match(/[a-z0-9][a-z0-9-]{2,}|[\p{Script=Han}]{2,}/gu) ?? []) {
45
+ if (/^[\p{Script=Han}]+$/u.test(token)) {
46
+ if (token.length <= 4) tokens.add(token);
47
+ else for (let index = 0; index < token.length - 1; index += 1) tokens.add(token.slice(index, index + 2));
48
+ continue;
49
+ }
50
+ const clean = token.replace(/^-+|-+$/g, "");
51
+ if (clean.length >= 3 && !STOP_WORDS.has(clean) && !/^\d+$/.test(clean)) tokens.add(clean);
52
+ }
53
+ return tokens;
54
+ }
55
+ function signalTokens(signal) {
56
+ return tokenizeUnderstandingSignal([signal.title, signal.group ?? ""].join(" "));
57
+ }
58
+ function overlap(left, right) {
59
+ let count = 0;
60
+ for (const token of left) if (right.has(token)) count += 1;
61
+ return count;
62
+ }
63
+ function related(left, right) {
64
+ const leftSubject = normalizeKey(left.signal.subjectKey);
65
+ const rightSubject = normalizeKey(right.signal.subjectKey);
66
+ if (leftSubject && leftSubject === rightSubject) return true;
67
+ const shared = overlap(left.tokens, right.tokens);
68
+ if (shared >= 2) return true;
69
+ const smallest = Math.min(left.tokens.size, right.tokens.size);
70
+ if (shared === 1 && smallest <= 2) return true;
71
+ return Boolean(shared === 1 && left.signal.group && normalizeKey(left.signal.group) === normalizeKey(right.signal.group));
72
+ }
73
+ function displayTitle(cluster) {
74
+ const subjects = /* @__PURE__ */ new Map();
75
+ for (const { signal } of cluster) {
76
+ const key = normalizeKey(signal.subjectKey);
77
+ if (!key) continue;
78
+ const current = subjects.get(key);
79
+ subjects.set(key, {
80
+ count: (current?.count ?? 0) + 1,
81
+ label: signal.subjectKey
82
+ });
83
+ }
84
+ const repeatedSubject = [...subjects.values()].sort((left, right) => right.count - left.count)[0];
85
+ if (repeatedSubject && repeatedSubject.count >= 2) return repeatedSubject.label.slice(0, 80);
86
+ const frequency = /* @__PURE__ */ new Map();
87
+ for (const entry of cluster) for (const token of entry.tokens) frequency.set(token, (frequency.get(token) ?? 0) + 1);
88
+ const shared = [...frequency.entries()].filter(([, count]) => count >= 2).sort((left, right) => right[1] - left[1] || left[0].localeCompare(right[0])).slice(0, 3).map(([token]) => token);
89
+ if (shared.length && !shared.every((token) => /^[\p{Script=Han}]+$/u.test(token))) return shared.map((token) => token.charAt(0).toUpperCase() + token.slice(1)).join(" ");
90
+ return cluster[0].signal.title.replace(/\.[a-z0-9]{1,8}$/i, "").slice(0, 80);
91
+ }
92
+ function clusterUnderstandingSignals(signals, now = Date.now()) {
93
+ const prepared = signals.map((signal) => ({
94
+ signal,
95
+ tokens: signalTokens(signal)
96
+ })).filter((entry) => entry.tokens.size > 0 || entry.signal.subjectKey);
97
+ const parent = prepared.map((_, index) => index);
98
+ const find = (index) => parent[index] === index ? index : parent[index] = find(parent[index]);
99
+ const union = (left, right) => {
100
+ const leftRoot = find(left);
101
+ const rightRoot = find(right);
102
+ if (leftRoot !== rightRoot) parent[rightRoot] = leftRoot;
103
+ };
104
+ for (let left = 0; left < prepared.length; left += 1) for (let right = left + 1; right < prepared.length; right += 1) if (related(prepared[left], prepared[right])) union(left, right);
105
+ const clusters = /* @__PURE__ */ new Map();
106
+ prepared.forEach((entry, index) => clusters.set(find(index), [...clusters.get(find(index)) ?? [], entry]));
107
+ return [...clusters.values()].flatMap((cluster) => {
108
+ if (cluster.length < 2) return [];
109
+ const sourceIds = [...new Set(cluster.map(({ signal }) => signal.sourceId))];
110
+ const timestamps = cluster.map(({ signal }) => signal.occurredAt ?? 0).filter(Boolean);
111
+ const newestAt = timestamps.length ? Math.max(...timestamps) : 0;
112
+ const ageDays = newestAt ? Math.max(0, (now - newestAt) / 864e5) : 90;
113
+ const recency = Math.max(0, 1 - ageDays / 90);
114
+ const confidence = Math.min(.92, .48 + Math.min(cluster.length, 5) * .06 + Math.min(sourceIds.length, 3) * .09 + recency * .08);
115
+ const tokenFrequency = /* @__PURE__ */ new Map();
116
+ for (const entry of cluster) for (const token of entry.tokens) tokenFrequency.set(token, (tokenFrequency.get(token) ?? 0) + 1);
117
+ const stableTokens = [...tokenFrequency.entries()].filter(([, count]) => count >= 2).map(([token]) => token).sort();
118
+ const stableSubjects = cluster.map(({ signal }) => normalizeKey(signal.subjectKey)).filter((value) => Boolean(value)).sort();
119
+ const keyMaterial = stableTokens.length ? stableTokens : stableSubjects;
120
+ return [{
121
+ key: createHash("sha256").update((keyMaterial.length ? keyMaterial : cluster.map(({ signal }) => signal.evidenceRef).sort()).join("|")).digest("hex").slice(0, 16),
122
+ title: displayTitle(cluster),
123
+ confidence,
124
+ horizon: ageDays <= 14 ? "current" : "ongoing",
125
+ signals: cluster.map(({ signal }) => signal),
126
+ sourceIds
127
+ }];
128
+ }).sort((left, right) => right.confidence - left.confidence);
129
+ }
130
+ //#endregion
131
+ export { clusterUnderstandingSignals, tokenizeUnderstandingSignal };
@@ -0,0 +1,17 @@
1
+ import { type DecodedPcmAudio } from '../local/wav.js';
2
+ export type AudioFormat = 'wav' | 'webm' | 'ogg' | 'mp3' | 'mp4' | 'unknown';
3
+ export declare class AudioNormalizationError extends Error {
4
+ readonly code = "unsupported_audio_codec";
5
+ constructor(message: string, options?: ErrorOptions);
6
+ }
7
+ export declare function detectAudioFormat(buffer: Buffer): AudioFormat;
8
+ export declare function decodeAudioToMonoFloat32(input: {
9
+ buffer: Buffer;
10
+ signal?: AbortSignal;
11
+ }): Promise<DecodedPcmAudio>;
12
+ /** Decodes a recording into bounded PCM WAV files and removes all temporary files afterwards. */
13
+ export declare function forEachNormalizedAudioSegment(input: {
14
+ filePath: string;
15
+ segmentSeconds?: number;
16
+ signal?: AbortSignal;
17
+ }, consume: (buffer: Buffer, index: number) => Promise<void>): Promise<number>;
@@ -0,0 +1,155 @@
1
+ import { decodeWavToMonoFloat32 } from "../local/wav.js";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { spawn } from "node:child_process";
5
+ import { mkdtemp, readFile, readdir, rm } from "node:fs/promises";
6
+ //#region src/voice/audio/normalize.ts
7
+ const TARGET_SAMPLE_RATE = 16e3;
8
+ const MAX_DECODED_BYTES = TARGET_SAMPLE_RATE * 4 * 15 * 60;
9
+ var AudioNormalizationError = class extends Error {
10
+ code = "unsupported_audio_codec";
11
+ constructor(message, options) {
12
+ super(message, options);
13
+ this.name = "AudioNormalizationError";
14
+ }
15
+ };
16
+ function detectAudioFormat(buffer) {
17
+ if (buffer.length >= 12 && buffer.toString("ascii", 0, 4) === "RIFF" && buffer.toString("ascii", 8, 12) === "WAVE") return "wav";
18
+ if (buffer.length >= 4 && buffer.subarray(0, 4).equals(Buffer.from([
19
+ 26,
20
+ 69,
21
+ 223,
22
+ 163
23
+ ]))) return "webm";
24
+ if (buffer.length >= 4 && buffer.toString("ascii", 0, 4) === "OggS") return "ogg";
25
+ if (buffer.length >= 3 && buffer.toString("ascii", 0, 3) === "ID3") return "mp3";
26
+ if (buffer.length >= 2 && buffer[0] === 255 && (buffer[1] & 224) === 224) return "mp3";
27
+ if (buffer.length >= 12 && buffer.toString("ascii", 4, 8) === "ftyp") return "mp4";
28
+ return "unknown";
29
+ }
30
+ function runFfmpeg(args, options = {}) {
31
+ options.signal?.throwIfAborted();
32
+ return new Promise((resolve, reject) => {
33
+ const child = spawn("ffmpeg", [
34
+ "-hide_banner",
35
+ "-loglevel",
36
+ "error",
37
+ ...args
38
+ ], { stdio: [
39
+ options.input ? "pipe" : "ignore",
40
+ "pipe",
41
+ "pipe"
42
+ ] });
43
+ const stdout = [];
44
+ const stderr = [];
45
+ let outputBytes = 0;
46
+ let errorBytes = 0;
47
+ let settled = false;
48
+ const finish = (error) => {
49
+ if (settled) return;
50
+ settled = true;
51
+ options.signal?.removeEventListener("abort", abort);
52
+ if (error) reject(error);
53
+ else resolve(Buffer.concat(stdout));
54
+ };
55
+ const abort = () => {
56
+ child.kill("SIGTERM");
57
+ finish(new AudioNormalizationError("Audio decoding was cancelled"));
58
+ };
59
+ options.signal?.addEventListener("abort", abort, { once: true });
60
+ child.stdout.on("data", (chunk) => {
61
+ outputBytes += chunk.length;
62
+ if (options.maxOutputBytes != null && outputBytes > options.maxOutputBytes) {
63
+ child.kill("SIGTERM");
64
+ finish(new AudioNormalizationError("Decoded audio exceeds the supported duration"));
65
+ return;
66
+ }
67
+ stdout.push(chunk);
68
+ });
69
+ child.stderr.on("data", (chunk) => {
70
+ if (errorBytes >= 8192) return;
71
+ const bounded = chunk.subarray(0, 8192 - errorBytes);
72
+ stderr.push(bounded);
73
+ errorBytes += bounded.length;
74
+ });
75
+ child.once("error", (error) => {
76
+ finish(new AudioNormalizationError(error.code === "ENOENT" ? "Audio decoder is unavailable; install ffmpeg to transcribe this format" : `Audio decoder failed to start: ${error.message}`, { cause: error }));
77
+ });
78
+ child.once("close", (code) => {
79
+ if (settled) return;
80
+ if (code === 0) finish();
81
+ else finish(new AudioNormalizationError(Buffer.concat(stderr).toString("utf8").trim() || `Unsupported or corrupt audio (decoder exit ${code})`));
82
+ });
83
+ if (options.input) {
84
+ child.stdin.on("error", () => void 0);
85
+ child.stdin.end(options.input);
86
+ }
87
+ });
88
+ }
89
+ async function decodeAudioToMonoFloat32(input) {
90
+ if (detectAudioFormat(input.buffer) === "wav") return decodeWavToMonoFloat32(input.buffer);
91
+ const bytes = await runFfmpeg([
92
+ "-i",
93
+ "pipe:0",
94
+ "-map",
95
+ "0:a:0",
96
+ "-vn",
97
+ "-ac",
98
+ "1",
99
+ "-ar",
100
+ String(TARGET_SAMPLE_RATE),
101
+ "-f",
102
+ "f32le",
103
+ "pipe:1"
104
+ ], {
105
+ input: input.buffer,
106
+ signal: input.signal,
107
+ maxOutputBytes: MAX_DECODED_BYTES
108
+ });
109
+ if (bytes.length === 0 || bytes.length % 4 !== 0) throw new AudioNormalizationError("Audio decoder produced no usable samples");
110
+ const copied = Uint8Array.from(bytes);
111
+ const samples = new Float32Array(copied.buffer);
112
+ return {
113
+ samples,
114
+ sampleRate: TARGET_SAMPLE_RATE,
115
+ durationSeconds: samples.length / TARGET_SAMPLE_RATE
116
+ };
117
+ }
118
+ /** Decodes a recording into bounded PCM WAV files and removes all temporary files afterwards. */
119
+ async function forEachNormalizedAudioSegment(input, consume) {
120
+ const directory = await mkdtemp(join(tmpdir(), "xopc-audio-"));
121
+ const outputPattern = join(directory, "segment-%05d.wav");
122
+ try {
123
+ await runFfmpeg([
124
+ "-i",
125
+ input.filePath,
126
+ "-map",
127
+ "0:a:0",
128
+ "-vn",
129
+ "-ac",
130
+ "1",
131
+ "-ar",
132
+ String(TARGET_SAMPLE_RATE),
133
+ "-c:a",
134
+ "pcm_s16le",
135
+ "-f",
136
+ "segment",
137
+ "-segment_time",
138
+ String(input.segmentSeconds ?? 20),
139
+ "-reset_timestamps",
140
+ "1",
141
+ outputPattern
142
+ ], { signal: input.signal });
143
+ const files = (await readdir(directory)).filter((name) => name.endsWith(".wav")).sort();
144
+ if (files.length === 0) throw new AudioNormalizationError("Audio decoder produced no segments");
145
+ for (let index = 0; index < files.length; index += 1) await consume(await readFile(join(directory, files[index])), index);
146
+ return files.length;
147
+ } finally {
148
+ await rm(directory, {
149
+ recursive: true,
150
+ force: true
151
+ });
152
+ }
153
+ }
154
+ //#endregion
155
+ export { AudioNormalizationError, decodeAudioToMonoFloat32, detectAudioFormat, forEachNormalizedAudioSegment };
@@ -9,10 +9,7 @@ export interface VoiceLanguageProfile {
9
9
  }
10
10
  export declare function resolveVoiceLanguageProfile(language: ProductLanguage): VoiceLanguageProfile;
11
11
  export declare function inferProductLanguageFromEnvironment(): ProductLanguage;
12
- /**
13
- * Install safe product defaults while preserving every explicit on/off choice.
14
- * Older configs with a persisted language or Edge voice are treated as manual.
15
- */
12
+ /** Install safe product defaults while preserving every explicit on/off choice. */
16
13
  export declare function initializeVoiceDefaults(config: Config, language?: ProductLanguage): boolean;
17
14
  /** Apply product language only to providers whose language mapping is known. */
18
15
  export declare function applyAutomaticVoiceLanguage(config: Config, language: ProductLanguage): boolean;
@@ -26,22 +26,14 @@ function inferProductLanguageFromEnvironment() {
26
26
  Intl.DateTimeFormat().resolvedOptions().locale
27
27
  ].find((value) => typeof value === "string" && value.trim())?.trim().toLowerCase().startsWith("zh") ? "zh" : "en";
28
28
  }
29
- function hasLegacyManualLanguageSelection(config) {
30
- const local = config.tools?.media?.audio?.providers?.["xopc-local"];
31
- const edge = config.messages?.tts?.providers?.edge;
32
- return typeof local?.language === "string" && local.language.trim().length > 0 || typeof edge?.voice === "string" && edge.voice.trim().length > 0 || typeof edge?.lang === "string" && edge.lang.trim().length > 0;
33
- }
34
- /**
35
- * Install safe product defaults while preserving every explicit on/off choice.
36
- * Older configs with a persisted language or Edge voice are treated as manual.
37
- */
29
+ /** Install safe product defaults while preserving every explicit on/off choice. */
38
30
  function initializeVoiceDefaults(config, language = inferProductLanguageFromEnvironment()) {
39
31
  const before = JSON.stringify({
40
32
  voice: config.voice,
41
33
  tools: config.tools?.media?.audio,
42
34
  tts: config.messages?.tts
43
35
  });
44
- const languageMode = config.voice?.languageMode ?? (hasLegacyManualLanguageSelection(config) ? "manual" : "auto");
36
+ const languageMode = config.voice?.languageMode ?? "auto";
45
37
  config.voice = {
46
38
  ...config.voice,
47
39
  languageMode,
@@ -66,21 +58,6 @@ function initializeVoiceDefaults(config, language = inferProductLanguageFromEnvi
66
58
  }
67
59
  }
68
60
  };
69
- config.messages = config.messages ?? {};
70
- const tts = config.messages.tts;
71
- config.messages.tts = {
72
- ...tts,
73
- enabled: tts?.enabled ?? true,
74
- provider: tts?.provider ?? "edge",
75
- trigger: tts?.trigger ?? "inbound",
76
- providers: {
77
- ...tts?.providers ?? {},
78
- edge: {
79
- enabled: true,
80
- ...tts?.providers?.edge ?? {}
81
- }
82
- }
83
- };
84
61
  if (languageMode === "auto") applyAutomaticVoiceLanguage(config, language);
85
62
  return before !== JSON.stringify({
86
63
  voice: config.voice,
@@ -9,6 +9,7 @@ export declare class LocalVoiceRuntimeClient {
9
9
  private child;
10
10
  private nextId;
11
11
  private pending;
12
+ private requestTail;
12
13
  request<T>(method: string, params?: Record<string, unknown>, options?: {
13
14
  signal?: AbortSignal;
14
15
  timeoutMs?: number;
@@ -16,6 +17,7 @@ export declare class LocalVoiceRuntimeClient {
16
17
  stopOnTimeout?: boolean;
17
18
  onProgress?: (progress: LocalVoiceRuntimeProgress) => void;
18
19
  }): Promise<T>;
20
+ private executeRequest;
19
21
  stop(): void;
20
22
  private ensureStarted;
21
23
  private handleLine;