@xopcai/xopc 0.0.144 → 0.0.145

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 (353) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/feishu/src/workflow-progress.js +1 -1
  3. package/dist/extensions/telegram/src/adapters/streaming-adapter.js +1 -1
  4. package/dist/extensions/telegram/src/inbound-processor.js +1 -1
  5. package/dist/extensions/telegram/src/plugin.js +1 -1
  6. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  7. package/dist/extensions/telegram/src/workflow-progress.js +1 -1
  8. package/dist/extensions/telegram/xopc.extension.json +1 -1
  9. package/dist/extensions/weixin/src/api/api.js +1 -1
  10. package/dist/extensions/weixin/src/plugin.js +1 -1
  11. package/dist/extensions/weixin/src/workflow-progress.js +1 -1
  12. package/dist/gateway/static/root/assets/Combination-DolwnuKi.js +41 -0
  13. package/dist/gateway/static/root/assets/{activity-center-store-jITiX2vJ.js → activity-center-store-3l9ahUqb.js} +1 -1
  14. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-EAVnrCAs.js → agent-avatar-dicebear-BEUxdhZx.js} +1 -1
  15. package/dist/gateway/static/root/assets/agents-1bpT0xRO.js +2 -0
  16. package/dist/gateway/static/root/assets/app-management-settings-panel-CRHSZJWi.js +1 -0
  17. package/dist/gateway/static/root/assets/{appearance-settings-DSkm9bp_.js → appearance-settings-BunADYJb.js} +1 -1
  18. package/dist/gateway/static/root/assets/apps-page-Cc4JgVUQ.js +1 -0
  19. package/dist/gateway/static/root/assets/{archive-plugin-C99N0vV6.js → archive-plugin-B6vTkH2A.js} +1 -1
  20. package/dist/gateway/static/root/assets/{attachment-load-CHTDqME5.js → attachment-load-BjZXzaNv.js} +1 -1
  21. package/dist/gateway/static/root/assets/{automation-suggestion-card-CBt6U3-S.js → automation-suggestion-card-ZDA-Stg1.js} +1 -1
  22. package/dist/gateway/static/root/assets/automations-page-mb0fdVpq.js +6 -0
  23. package/dist/gateway/static/root/assets/{binary-plugins-BRtxOLlM.js → binary-plugins-DYZfLvPz.js} +1 -1
  24. package/dist/gateway/static/root/assets/{block-editor-CUlXfgXd.js → block-editor-C3MUlYC9.js} +46 -46
  25. package/dist/gateway/static/root/assets/browser-settings-page-Bb0xhaMN.js +8 -0
  26. package/dist/gateway/static/root/assets/capability-presets-api-BV76yN9a.js +1 -0
  27. package/dist/gateway/static/root/assets/capability-presets-settings-panel-CUcGKZqC.js +2 -0
  28. package/dist/gateway/static/root/assets/channel-recipient-api-fTlTnWB4.js +1 -0
  29. package/dist/gateway/static/root/assets/channels-settings-BlSDMGdy.js +1 -0
  30. package/dist/gateway/static/root/assets/channels-status-swr-CJauF1CW.js +1 -0
  31. package/dist/gateway/static/root/assets/{code-editor--tMO38Tr.js → code-editor-D4_k-6QN.js} +1 -1
  32. package/dist/gateway/static/root/assets/connector-logo-BVFNT2zW.js +1 -0
  33. package/dist/gateway/static/root/assets/connectors-page-CMgAFGvb.js +2 -0
  34. package/dist/gateway/static/root/assets/copy-to-clipboard-HOJ79TWv.js +1 -0
  35. package/dist/gateway/static/root/assets/{desktop-pet-C-Drhqyk.js → desktop-pet-_jUmoXd3.js} +1 -1
  36. package/dist/gateway/static/root/assets/{desktop-pet-settings-CRGiolqF.js → desktop-pet-settings-DwGOy4AQ.js} +1 -1
  37. package/dist/gateway/static/root/assets/{directory-picker-path-field-Dw1L3M84.js → directory-picker-path-field-akvF0F-u.js} +1 -1
  38. package/dist/gateway/static/root/assets/{dist-SwiI0Xu3.js → dist-C99RGfAH.js} +1 -1
  39. package/dist/gateway/static/root/assets/dreaming-settings-BLetQiYY.js +3 -0
  40. package/dist/gateway/static/root/assets/{extension-debug-page-Dcl8LJG_.js → extension-debug-page-Cof2ncxE.js} +1 -1
  41. package/dist/gateway/static/root/assets/{extension-page-i_BXmO_x.js → extension-page-CwWktRNz.js} +1 -1
  42. package/dist/gateway/static/root/assets/extension-settings-page-CuggWOIl.js +1 -0
  43. package/dist/gateway/static/root/assets/gateway-config-api-B7sxIbza.js +1 -0
  44. package/dist/gateway/static/root/assets/gateway-settings-DIv0eKMf.js +1 -0
  45. package/dist/gateway/static/root/assets/gateway-startup-retry-DtoLihQE.js +1 -0
  46. package/dist/gateway/static/root/assets/goal-create-dialog-C4Kw0mfS.js +1 -0
  47. package/dist/gateway/static/root/assets/goal-detail-page-BMmzYpZL.js +4 -0
  48. package/dist/gateway/static/root/assets/goals-config-api-B0jm5JaA.js +1 -0
  49. package/dist/gateway/static/root/assets/goals-page-CGeT77PC.js +2 -0
  50. package/dist/gateway/static/root/assets/goals-settings-N5_iL7es.js +1 -0
  51. package/dist/gateway/static/root/assets/heartbeat-settings-XzH3lbRR.js +1 -0
  52. package/dist/gateway/static/root/assets/{html-workspace-editor-COqmtESs.js → html-workspace-editor-C3DKAkMc.js} +1 -1
  53. package/dist/gateway/static/root/assets/index-CSLF84-Q.css +1 -0
  54. package/dist/gateway/static/root/assets/index-I-ZCenVw.js +259 -0
  55. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-x_v0nrIi.js +1 -0
  56. package/dist/gateway/static/root/assets/locale-store-CiM-D9jA.js +1 -0
  57. package/dist/gateway/static/root/assets/logs-page-BSh1t8cD.js +7 -0
  58. package/dist/gateway/static/root/assets/markdown-editor-BvUebh3C.js +2 -0
  59. package/dist/gateway/static/root/assets/{markdown-split-BTRFTK0w.js → markdown-split-5rJx5flj.js} +1 -1
  60. package/dist/gateway/static/root/assets/{media-plugins-BABfIZPU.js → media-plugins-DYXccwAd.js} +1 -1
  61. package/dist/gateway/static/root/assets/messages-Cb1VMeqP.js +5 -0
  62. package/dist/gateway/static/root/assets/models-hub-panel-BNpTenAI.js +2 -0
  63. package/dist/gateway/static/root/assets/{notes-page-88QBHW9a.js → notes-page-BgLyndCO.js} +1 -1
  64. package/dist/gateway/static/root/assets/notes-workbench-teklkhcE.js +4 -0
  65. package/dist/gateway/static/root/assets/{page-tabs-je95DZOf.js → page-tabs-6Al9_sGz.js} +1 -1
  66. package/dist/gateway/static/root/assets/{preview-open-alternatives-BJbwi7Rc.js → preview-open-alternatives-Cm3G72Hv.js} +1 -1
  67. package/dist/gateway/static/root/assets/project-detail-page-CCB_dKoh.js +1 -0
  68. package/dist/gateway/static/root/assets/projects-page-VOAFAHYj.js +1 -0
  69. package/dist/gateway/static/root/assets/remote-access-hub-USYu64Ru.js +1 -0
  70. package/dist/gateway/static/root/assets/{save-bar-controls-qWMQ9mod.js → save-bar-controls-BYtfzu_F.js} +1 -1
  71. package/dist/gateway/static/root/assets/{schedule-field-kxd270Gs.js → schedule-field-CvIRc6yK.js} +1 -1
  72. package/dist/gateway/static/root/assets/{schema-form-DLnD-MuD.js → schema-form-CQuKx0n7.js} +1 -1
  73. package/dist/gateway/static/root/assets/sessions-page-oGC8O5h_.js +1 -0
  74. package/dist/gateway/static/root/assets/settings-advanced-gate-D4rP66R1.js +1 -0
  75. package/dist/gateway/static/root/assets/{settings-collapsible-section-DQprvu5J.js → settings-collapsible-section-CF3HHM-t.js} +1 -1
  76. package/dist/gateway/static/root/assets/{settings-form-section-Cqq7Y98y.js → settings-form-section-CwWjoRN6.js} +1 -1
  77. package/dist/gateway/static/root/assets/{settings-loading-skeleton-b6rXULL5.js → settings-loading-skeleton-aUFmJa13.js} +1 -1
  78. package/dist/gateway/static/root/assets/{settings-page-BtBVz3cX.js → settings-page-B2UUU9TF.js} +1 -1
  79. package/dist/gateway/static/root/assets/{settings-page-layout-BNJbtklV.js → settings-page-layout-DqpbTWqI.js} +1 -1
  80. package/dist/gateway/static/root/assets/setup-status-panel-Ck9keROI.js +1 -0
  81. package/dist/gateway/static/root/assets/share-preview-page-BOhlPsS1.js +2 -0
  82. package/dist/gateway/static/root/assets/shares-settings-BYLsCuqj.js +1 -0
  83. package/dist/gateway/static/root/assets/skill-reload-api-BNHUyVML.js +1 -0
  84. package/dist/gateway/static/root/assets/skills-page-CpXbQH4n.js +2 -0
  85. package/dist/gateway/static/root/assets/{system-settings-panel-Cq9J7i7v.js → system-settings-panel-CWxSvuwD.js} +1 -1
  86. package/dist/gateway/static/root/assets/{theme-store-Bt6vAkSB.js → theme-store-C9Dxcppm.js} +1 -1
  87. package/dist/gateway/static/root/assets/{typed-models-lib-CdSwi1gT.js → typed-models-lib-qROAvqTw.js} +1 -1
  88. package/dist/gateway/static/root/assets/use-channel-catalog-DE9cpn4G.js +1 -0
  89. package/dist/gateway/static/root/assets/user-context-page-DbNEK4Yp.js +1 -0
  90. package/dist/gateway/static/root/assets/user-profile-fields-editor-CWxc0ghP.js +1 -0
  91. package/dist/gateway/static/root/assets/{user-profile-settings-panel-B8hlamVB.js → user-profile-settings-panel-DW-Up6vt.js} +1 -1
  92. package/dist/gateway/static/root/assets/{utils-Dx01V8qF.js → utils-D53uRXVr.js} +1 -1
  93. package/dist/gateway/static/root/assets/{vendor-codemirror-C1WKjCk5.js → vendor-codemirror--gTq3YAI.js} +17 -17
  94. package/dist/gateway/static/root/assets/voice-api-key-field-Cs7MOrg0.js +1 -0
  95. package/dist/gateway/static/root/assets/work-item-detail-page-D1ziG1Pp.js +1 -0
  96. package/dist/gateway/static/root/assets/workflow-run-setup-panel-D_x9ELJp.js +3 -0
  97. package/dist/gateway/static/root/assets/workflows-page-DHGV_n6i.js +11 -0
  98. package/dist/gateway/static/root/index.html +10 -10
  99. package/dist/package.js +1 -1
  100. package/dist/src/activity/emitter.js +1 -1
  101. package/dist/src/agent/agent-manager.js +4 -4
  102. package/dist/src/agent/code-intelligence/binary.js +1 -1
  103. package/dist/src/agent/context/project-context.js +2 -2
  104. package/dist/src/agent/context/workspace-seed.js +2 -2
  105. package/dist/src/agent/embedded/run-for-session.js +1 -1
  106. package/dist/src/agent/embedded/session-runner.js +3 -3
  107. package/dist/src/agent/embedded/session-runner.js.map +1 -1
  108. package/dist/src/agent/embedded/xopc-auth-storage.d.ts +3 -1
  109. package/dist/src/agent/embedded/xopc-auth-storage.js +11 -1
  110. package/dist/src/agent/embedded/xopc-auth-storage.js.map +1 -1
  111. package/dist/src/agent/goals/post-turn.js +2 -2
  112. package/dist/src/agent/ipc/bus.js +1 -1
  113. package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
  114. package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
  115. package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
  116. package/dist/src/agent/mcp/mcp-transport.js +1 -1
  117. package/dist/src/agent/memory/dreaming/config.js +1 -1
  118. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  119. package/dist/src/agent/models/manager.js +1 -1
  120. package/dist/src/agent/orchestration/agent-orchestrator.js +1 -1
  121. package/dist/src/agent/service.js +3 -3
  122. package/dist/src/agent/session/session-inspector.js +2 -2
  123. package/dist/src/agent/skills/hub-pull.js +1 -1
  124. package/dist/src/agent/tools/composio-tool.js +1 -1
  125. package/dist/src/agent/tools/goal-tool.js +2 -2
  126. package/dist/src/agent/tools/workflow-tool.js +1 -1
  127. package/dist/src/agent/tools/xopc-use-tool.js +1 -1
  128. package/dist/src/agent/workspace-runtime/registry.js +2 -2
  129. package/dist/src/agent-runtime/index.js +1 -1
  130. package/dist/src/agent-runtime/runtime-profile.js +1 -1
  131. package/dist/src/automations/api/routes.js +1 -1
  132. package/dist/src/automations/service/action-executor.js +2 -2
  133. package/dist/src/browser/cdp-local-launcher.js +1 -1
  134. package/dist/src/browser/providers/browser-ext-install.js +3 -3
  135. package/dist/src/browser/providers/cloakbrowser.js +2 -2
  136. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  137. package/dist/src/browser/stealth.js +1 -1
  138. package/dist/src/capabilities/store-connector.js +1 -1
  139. package/dist/src/chat-commands/agent-edit.js +1 -1
  140. package/dist/src/chat-commands/builtins/config.js +1 -1
  141. package/dist/src/chat-commands/builtins/goal.js +2 -2
  142. package/dist/src/chat-commands/context.js +1 -1
  143. package/dist/src/cli/commands/agent.js +1 -1
  144. package/dist/src/cli/commands/doctor/checks/database-schema.js +2 -2
  145. package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
  146. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  147. package/dist/src/cli/commands/extension-pack.js +1 -1
  148. package/dist/src/cli/commands/goal.js +2 -2
  149. package/dist/src/cli/commands/init.js +1 -1
  150. package/dist/src/cli/commands/project.js +3 -3
  151. package/dist/src/config/agent-profile.js +1 -1
  152. package/dist/src/config/gateway-bind.js +1 -1
  153. package/dist/src/config/index.js +3 -3
  154. package/dist/src/config/loader.js +1 -1
  155. package/dist/src/config/models-json.js +1 -1
  156. package/dist/src/config/schema.d.ts +60 -5
  157. package/dist/src/config/schema.js +30 -9
  158. package/dist/src/config/schema.js.map +1 -1
  159. package/dist/src/connectors/composio-catalog.js +11 -2
  160. package/dist/src/connectors/composio-catalog.js.map +1 -1
  161. package/dist/src/connectors/composio-sessions.js +1 -1
  162. package/dist/src/connectors/composio.js +1 -1
  163. package/dist/src/connectors/connector-memory-sync.js +135 -26
  164. package/dist/src/connectors/connector-memory-sync.js.map +1 -1
  165. package/dist/src/daemon/launchd.js +1 -1
  166. package/dist/src/daemon/systemd.js +1 -1
  167. package/dist/src/extensions/discover-extensions.js +1 -1
  168. package/dist/src/extensions/loader.js +2 -2
  169. package/dist/src/gateway/agents-admin.js +1 -1
  170. package/dist/src/gateway/heartbeat/service.js +1 -1
  171. package/dist/src/gateway/hono/app.js +1 -1
  172. package/dist/src/gateway/hono/app.js.map +1 -1
  173. package/dist/src/gateway/hono/lib/config-payload.d.ts +11 -0
  174. package/dist/src/gateway/hono/lib/config-payload.js +1 -0
  175. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  176. package/dist/src/gateway/hono/lib/static-ui.js +1 -1
  177. package/dist/src/gateway/hono/routes/config-patch/misc.js +6 -1
  178. package/dist/src/gateway/hono/routes/config-patch/misc.js.map +1 -1
  179. package/dist/src/gateway/hono/routes/home.js +2 -2
  180. package/dist/src/gateway/hono/routes/memory.js +13 -3
  181. package/dist/src/gateway/hono/routes/memory.js.map +1 -1
  182. package/dist/src/gateway/hono/routes/projects.js +5 -5
  183. package/dist/src/gateway/hono/routes/status.js +3 -0
  184. package/dist/src/gateway/hono/routes/status.js.map +1 -1
  185. package/dist/src/gateway/hono/routes/voice.d.ts +5 -5
  186. package/dist/src/gateway/hono/routes/voice.js +288 -62
  187. package/dist/src/gateway/hono/routes/voice.js.map +1 -1
  188. package/dist/src/gateway/hono/routes/workflows.js +1 -1
  189. package/dist/src/gateway/hono/routes/you.js +11 -7
  190. package/dist/src/gateway/hono/routes/you.js.map +1 -1
  191. package/dist/src/gateway/lock.js +1 -1
  192. package/dist/src/gateway/ports.js +1 -1
  193. package/dist/src/gateway/service.d.ts +8 -0
  194. package/dist/src/gateway/service.js +47 -17
  195. package/dist/src/gateway/service.js.map +1 -1
  196. package/dist/src/goals/goal-workflow-judge.js +1 -1
  197. package/dist/src/heartbeat/index.js +1 -1
  198. package/dist/src/infra/ports.js +1 -1
  199. package/dist/src/infra/ssh-tunnel.js +1 -1
  200. package/dist/src/infra/update-check.js +1 -1
  201. package/dist/src/knowledge/connected-knowledge-pipeline.d.ts +21 -0
  202. package/dist/src/knowledge/connected-knowledge-pipeline.js +267 -0
  203. package/dist/src/knowledge/connected-knowledge-pipeline.js.map +1 -0
  204. package/dist/src/knowledge/coordinator.d.ts +10 -0
  205. package/dist/src/knowledge/coordinator.js +52 -0
  206. package/dist/src/knowledge/coordinator.js.map +1 -0
  207. package/dist/src/knowledge/index.d.ts +2 -0
  208. package/dist/src/knowledge/index.js +3 -1
  209. package/dist/src/knowledge/ingestion-service.d.ts +7 -1
  210. package/dist/src/knowledge/ingestion-service.js +28 -0
  211. package/dist/src/knowledge/ingestion-service.js.map +1 -1
  212. package/dist/src/knowledge/types.d.ts +18 -0
  213. package/dist/src/media-understanding/audio-transcription-runner.js +5 -3
  214. package/dist/src/media-understanding/audio-transcription-runner.js.map +1 -1
  215. package/dist/src/media-understanding/runner.js +8 -3
  216. package/dist/src/media-understanding/runner.js.map +1 -1
  217. package/dist/src/media-understanding/types.d.ts +7 -0
  218. package/dist/src/migrations/runner.js +1 -1
  219. package/dist/src/notes/service.js +3 -3
  220. package/dist/src/notes/store.js +1 -1
  221. package/dist/src/projects/project-service.js +1 -1
  222. package/dist/src/projects/workspace.js +1 -1
  223. package/dist/src/routing/agent-session-key.js +1 -1
  224. package/dist/src/routing/resolve-route.js +1 -1
  225. package/dist/src/routing/resolve-tui-session-key.js +1 -1
  226. package/dist/src/session/init-session-turn.js +1 -1
  227. package/dist/src/session/resolve-session.js +1 -1
  228. package/dist/src/session/session-title.js +2 -2
  229. package/dist/src/session/store.js +1 -1
  230. package/dist/src/storage/sqlite/connection.js +1 -1
  231. package/dist/src/storage/sqlite/index.d.ts +1 -1
  232. package/dist/src/storage/sqlite/index.js +2 -2
  233. package/dist/src/storage/sqlite/knowledge-repository.d.ts +26 -1
  234. package/dist/src/storage/sqlite/knowledge-repository.js +120 -6
  235. package/dist/src/storage/sqlite/knowledge-repository.js.map +1 -1
  236. package/dist/src/storage/sqlite/migrations/037_connected_knowledge_pipeline.sql +47 -0
  237. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  238. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  239. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  240. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  241. package/dist/src/storage/sqlite/row-mappers.js +1 -1
  242. package/dist/src/storage/sqlite/schema.js +1 -1
  243. package/dist/src/tui/backends/embedded-backend.js +4 -4
  244. package/dist/src/tui/clipboard-image.js +1 -1
  245. package/dist/src/tui/tui-command-formatters.js +2 -2
  246. package/dist/src/tui/tui-commands.js +3 -3
  247. package/dist/src/tui/tui.js +1 -1
  248. package/dist/src/user-context/projection.d.ts +13 -4
  249. package/dist/src/user-context/projection.js +19 -7
  250. package/dist/src/user-context/projection.js.map +1 -1
  251. package/dist/src/utils/index.js +1 -1
  252. package/dist/src/utils/logger/index.js +1 -1
  253. package/dist/src/utils/logger.js +1 -1
  254. package/dist/src/voice/language-profile.d.ts +20 -0
  255. package/dist/src/voice/language-profile.js +156 -0
  256. package/dist/src/voice/language-profile.js.map +1 -0
  257. package/dist/src/voice/local/model-files.d.ts +14 -0
  258. package/dist/src/voice/local/model-files.js +94 -0
  259. package/dist/src/voice/local/model-files.js.map +1 -0
  260. package/dist/src/voice/local/model-manager.d.ts +18 -0
  261. package/dist/src/voice/local/model-manager.js +135 -0
  262. package/dist/src/voice/local/model-manager.js.map +1 -0
  263. package/dist/src/voice/local/models.d.ts +28 -0
  264. package/dist/src/voice/local/models.js +101 -0
  265. package/dist/src/voice/local/models.js.map +1 -0
  266. package/dist/src/voice/local/runtime-client.d.ts +26 -0
  267. package/dist/src/voice/local/runtime-client.js +166 -0
  268. package/dist/src/voice/local/runtime-client.js.map +1 -0
  269. package/dist/src/voice/local/runtime-dispatcher.d.ts +9 -0
  270. package/dist/src/voice/local/runtime-dispatcher.js +22 -0
  271. package/dist/src/voice/local/runtime-dispatcher.js.map +1 -0
  272. package/dist/src/voice/local/runtime-worker.d.ts +1 -0
  273. package/dist/src/voice/local/runtime-worker.js +249 -0
  274. package/dist/src/voice/local/runtime-worker.js.map +1 -0
  275. package/dist/src/voice/local/wav.d.ts +6 -0
  276. package/dist/src/voice/local/wav.js +69 -0
  277. package/dist/src/voice/local/wav.js.map +1 -0
  278. package/dist/src/voice/metadata/builtin.js +46 -0
  279. package/dist/src/voice/metadata/builtin.js.map +1 -1
  280. package/dist/src/voice/stt/factory.js +8 -2
  281. package/dist/src/voice/stt/factory.js.map +1 -1
  282. package/dist/src/voice/stt/providers/alibaba-transcription.js +14 -8
  283. package/dist/src/voice/stt/providers/alibaba-transcription.js.map +1 -1
  284. package/dist/src/voice/stt/providers/index.d.ts +1 -0
  285. package/dist/src/voice/stt/providers/index.js +2 -1
  286. package/dist/src/voice/stt/providers/local-transcription.d.ts +2 -0
  287. package/dist/src/voice/stt/providers/local-transcription.js +51 -0
  288. package/dist/src/voice/stt/providers/local-transcription.js.map +1 -0
  289. package/dist/src/voice/stt/providers/openai-transcription.js +5 -3
  290. package/dist/src/voice/stt/providers/openai-transcription.js.map +1 -1
  291. package/dist/src/voice/stt/transcribe-core.js +5 -4
  292. package/dist/src/voice/stt/transcribe-core.js.map +1 -1
  293. package/dist/src/voice/stt/types.d.ts +4 -0
  294. package/dist/src/voice/stt/types.js +5 -4
  295. package/dist/src/voice/stt/types.js.map +1 -1
  296. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  297. package/dist/src/voice/tts/providers/edge-speech.js.map +1 -1
  298. package/dist/src/voice/tts/types.js +3 -3
  299. package/dist/src/voice/tts/types.js.map +1 -1
  300. package/dist/src/work-items/work-item-service.js +1 -1
  301. package/dist/src/workflows/draft/workflow-draft-service.js +1 -1
  302. package/dist/src/workflows/service/workflow-session-bridge.js +3 -3
  303. package/package.json +3 -1
  304. package/dist/gateway/static/root/assets/Combination-HAlzriaz.js +0 -41
  305. package/dist/gateway/static/root/assets/agents-5rTuJOtT.js +0 -2
  306. package/dist/gateway/static/root/assets/app-management-settings-panel-Bu568NpC.js +0 -1
  307. package/dist/gateway/static/root/assets/apps-page-DWetalKp.js +0 -1
  308. package/dist/gateway/static/root/assets/automations-page-ICUfxeOz.js +0 -4
  309. package/dist/gateway/static/root/assets/browser-settings-page-D7Bj4MKi.js +0 -8
  310. package/dist/gateway/static/root/assets/capability-presets-api-Bg1ntFSD.js +0 -1
  311. package/dist/gateway/static/root/assets/capability-presets-settings-panel-C-8I-Ktn.js +0 -2
  312. package/dist/gateway/static/root/assets/channel-recipient-api-DuulnhIj.js +0 -1
  313. package/dist/gateway/static/root/assets/channels-settings-Dm5EqQyK.js +0 -1
  314. package/dist/gateway/static/root/assets/channels-status-swr-B5lVrUsN.js +0 -1
  315. package/dist/gateway/static/root/assets/connectors-page-BOzjh-OK.js +0 -2
  316. package/dist/gateway/static/root/assets/dreaming-settings-CF21cbjo.js +0 -3
  317. package/dist/gateway/static/root/assets/extension-settings-page-CWIi7xsn.js +0 -1
  318. package/dist/gateway/static/root/assets/fetch-8QNN25Sh.js +0 -1
  319. package/dist/gateway/static/root/assets/gateway-config-api-2sLP2kkA.js +0 -1
  320. package/dist/gateway/static/root/assets/gateway-settings-DMHiZc-2.js +0 -1
  321. package/dist/gateway/static/root/assets/gateway-startup-retry-5YBnS9Fj.js +0 -1
  322. package/dist/gateway/static/root/assets/goal-create-dialog-CAODVDiA.js +0 -1
  323. package/dist/gateway/static/root/assets/goal-detail-page-_d4DjmeX.js +0 -4
  324. package/dist/gateway/static/root/assets/goals-config-api-B4qeLKQS.js +0 -1
  325. package/dist/gateway/static/root/assets/goals-page-lgsop664.js +0 -2
  326. package/dist/gateway/static/root/assets/goals-settings-Dx_1ZNgb.js +0 -1
  327. package/dist/gateway/static/root/assets/heartbeat-settings-DeTseEk_.js +0 -1
  328. package/dist/gateway/static/root/assets/index-CphxClbs.css +0 -1
  329. package/dist/gateway/static/root/assets/index-VWvztcst.js +0 -257
  330. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-BpwpMmlk.js +0 -1
  331. package/dist/gateway/static/root/assets/locale-store-Ba72bFmP.js +0 -1
  332. package/dist/gateway/static/root/assets/logs-page-9_hbTg3j.js +0 -7
  333. package/dist/gateway/static/root/assets/markdown-editor-jD1LPiP-.js +0 -2
  334. package/dist/gateway/static/root/assets/messages-CzKxM6I4.js +0 -5
  335. package/dist/gateway/static/root/assets/models-hub-panel-B1CUvZxh.js +0 -2
  336. package/dist/gateway/static/root/assets/notes-workbench-CerZOeLW.js +0 -2
  337. package/dist/gateway/static/root/assets/project-detail-page-BmrApldl.js +0 -1
  338. package/dist/gateway/static/root/assets/projects-page-tTn-k76N.js +0 -1
  339. package/dist/gateway/static/root/assets/remote-access-hub-DeA2-pOi.js +0 -1
  340. package/dist/gateway/static/root/assets/sessions-page-D4kvvcL1.js +0 -1
  341. package/dist/gateway/static/root/assets/settings-advanced-gate-CI1OG4gq.js +0 -1
  342. package/dist/gateway/static/root/assets/setup-status-panel-cmclUJzS.js +0 -1
  343. package/dist/gateway/static/root/assets/share-preview-page--zO-A1W1.js +0 -2
  344. package/dist/gateway/static/root/assets/shares-settings-DNJvqA67.js +0 -1
  345. package/dist/gateway/static/root/assets/skill-reload-api-DWr_0Xgn.js +0 -1
  346. package/dist/gateway/static/root/assets/skills-page-DEGsTbJx.js +0 -2
  347. package/dist/gateway/static/root/assets/use-channel-catalog-COXIfXcl.js +0 -1
  348. package/dist/gateway/static/root/assets/user-context-page-C-V73ZaJ.js +0 -1
  349. package/dist/gateway/static/root/assets/user-profile-fields-editor-B1cxoGkh.js +0 -1
  350. package/dist/gateway/static/root/assets/voice-api-key-field-DGpIUelZ.js +0 -1
  351. package/dist/gateway/static/root/assets/work-item-detail-page-fzWTxF26.js +0 -1
  352. package/dist/gateway/static/root/assets/workflow-run-setup-panel-Dt_x8LGg.js +0 -3
  353. package/dist/gateway/static/root/assets/workflows-page-Bg02zEUh.js +0 -11
@@ -0,0 +1,166 @@
1
+ import { createLogger } from "../../utils/logger/index.js";
2
+ import { init_logger } from "../../utils/logger.js";
3
+ import { resolveLocalVoiceRootDir } from "./models.js";
4
+ import { existsSync } from "node:fs";
5
+ import { fileURLToPath } from "node:url";
6
+ import { spawn } from "node:child_process";
7
+ import { createInterface } from "node:readline";
8
+ //#region src/voice/local/runtime-client.ts
9
+ init_logger();
10
+ const log = createLogger("LocalVoice:Runtime");
11
+ const DEFAULT_REQUEST_TIMEOUT_MS = 10 * 6e4;
12
+ function resolveWorkerCommand() {
13
+ const configured = process.env.XOPC_VOICE_RUNTIME_ENTRY?.trim();
14
+ if (configured) return {
15
+ entry: configured,
16
+ args: [configured]
17
+ };
18
+ const jsEntry = fileURLToPath(new URL("./runtime-worker.js", import.meta.url));
19
+ if (existsSync(jsEntry)) return {
20
+ entry: jsEntry,
21
+ args: [jsEntry]
22
+ };
23
+ const tsEntry = fileURLToPath(new URL("./runtime-worker.ts", import.meta.url));
24
+ if (existsSync(tsEntry)) return {
25
+ entry: tsEntry,
26
+ args: [
27
+ "--import",
28
+ "tsx",
29
+ tsEntry
30
+ ]
31
+ };
32
+ throw new Error("Bundled local voice runtime entry is missing");
33
+ }
34
+ var LocalVoiceRuntimeClient = class {
35
+ child = null;
36
+ nextId = 1;
37
+ pending = /* @__PURE__ */ new Map();
38
+ async request(method, params = {}, options = {}) {
39
+ options.signal?.throwIfAborted();
40
+ const child = this.ensureStarted();
41
+ const id = this.nextId++;
42
+ return new Promise((resolve, reject) => {
43
+ const timeout = setTimeout(() => {
44
+ this.deletePending(id);
45
+ reject(/* @__PURE__ */ new Error(`Local voice runtime request timed out: ${method}`));
46
+ if (options.stopOnTimeout !== false) this.stop();
47
+ }, options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS);
48
+ this.pending.set(id, {
49
+ resolve: (value) => resolve(value),
50
+ reject,
51
+ timeout,
52
+ signal: options.signal,
53
+ onProgress: options.onProgress
54
+ });
55
+ const abort = () => {
56
+ const pending = this.pending.get(id);
57
+ if (!pending) return;
58
+ this.deletePending(id);
59
+ pending.reject(/* @__PURE__ */ new Error("Local voice transcription aborted"));
60
+ this.stop();
61
+ };
62
+ const pending = this.pending.get(id);
63
+ if (pending) pending.abort = abort;
64
+ options.signal?.addEventListener("abort", abort, { once: true });
65
+ child.stdin.write(`${JSON.stringify({
66
+ id,
67
+ method,
68
+ params
69
+ })}\n`, (error) => {
70
+ if (!error) return;
71
+ this.deletePending(id);
72
+ reject(error);
73
+ });
74
+ });
75
+ }
76
+ stop() {
77
+ const child = this.child;
78
+ this.child = null;
79
+ if (child && !child.killed) child.kill("SIGTERM");
80
+ this.rejectAll(/* @__PURE__ */ new Error("Local voice runtime stopped"));
81
+ }
82
+ ensureStarted() {
83
+ if (this.child && !this.child.killed) return this.child;
84
+ const command = resolveWorkerCommand();
85
+ const child = spawn(process.execPath, command.args, {
86
+ env: {
87
+ ...process.env,
88
+ ELECTRON_RUN_AS_NODE: "1",
89
+ XOPC_VOICE_MODEL_DIR: resolveLocalVoiceRootDir()
90
+ },
91
+ stdio: [
92
+ "pipe",
93
+ "pipe",
94
+ "pipe"
95
+ ],
96
+ windowsHide: true
97
+ });
98
+ this.child = child;
99
+ createInterface({ input: child.stdout }).on("line", (line) => this.handleLine(line));
100
+ child.stderr.on("data", (chunk) => {
101
+ const message = chunk.toString().trim();
102
+ if (message) log.debug({ message }, "Local voice runtime stderr");
103
+ });
104
+ child.once("error", (error) => {
105
+ if (this.child === child) this.child = null;
106
+ this.rejectAll(error);
107
+ });
108
+ child.once("exit", (code, signal) => {
109
+ if (this.child === child) this.child = null;
110
+ if (this.pending.size > 0) this.rejectAll(/* @__PURE__ */ new Error(`Local voice runtime exited (${code ?? signal ?? "unknown"})`));
111
+ });
112
+ return child;
113
+ }
114
+ handleLine(line) {
115
+ let message;
116
+ try {
117
+ message = JSON.parse(line);
118
+ } catch {
119
+ log.warn({ linePreview: line.slice(0, 200) }, "Ignored invalid local voice runtime output");
120
+ return;
121
+ }
122
+ if (typeof message.id !== "number") return;
123
+ const pending = this.pending.get(message.id);
124
+ if (!pending) return;
125
+ if (message.event === "progress") {
126
+ pending.onProgress?.(message.data ?? {});
127
+ return;
128
+ }
129
+ this.deletePending(message.id);
130
+ if (message.error) {
131
+ const detail = typeof message.error === "string" ? { message: message.error } : message.error;
132
+ const suffix = [detail.code, detail.cause].filter(Boolean).join(": ");
133
+ const error = /* @__PURE__ */ new Error(`${detail.message || "Local voice runtime failed"}${suffix ? ` (${suffix})` : ""}`);
134
+ if (detail.code) Object.assign(error, { code: detail.code });
135
+ pending.reject(error);
136
+ } else pending.resolve(message.result);
137
+ }
138
+ rejectAll(error) {
139
+ for (const pending of this.pending.values()) {
140
+ clearTimeout(pending.timeout);
141
+ if (pending.signal && pending.abort) pending.signal.removeEventListener("abort", pending.abort);
142
+ pending.reject(error);
143
+ }
144
+ this.pending.clear();
145
+ }
146
+ deletePending(id) {
147
+ const pending = this.pending.get(id);
148
+ if (!pending) return;
149
+ clearTimeout(pending.timeout);
150
+ if (pending.signal && pending.abort) pending.signal.removeEventListener("abort", pending.abort);
151
+ this.pending.delete(id);
152
+ }
153
+ };
154
+ let sharedRuntime;
155
+ function getLocalVoiceRuntimeClient() {
156
+ sharedRuntime ??= new LocalVoiceRuntimeClient();
157
+ return sharedRuntime;
158
+ }
159
+ function resetLocalVoiceRuntimeForTests() {
160
+ sharedRuntime?.stop();
161
+ sharedRuntime = void 0;
162
+ }
163
+ //#endregion
164
+ export { LocalVoiceRuntimeClient, getLocalVoiceRuntimeClient, resetLocalVoiceRuntimeForTests };
165
+
166
+ //# sourceMappingURL=runtime-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-client.js","names":[],"sources":["../../../../src/voice/local/runtime-client.ts"],"sourcesContent":["import { spawn, type ChildProcessWithoutNullStreams } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { createInterface } from 'node:readline';\nimport { fileURLToPath } from 'node:url';\n\nimport { createLogger } from '../../utils/logger.js';\nimport { resolveLocalVoiceRootDir } from './models.js';\n\nconst log = createLogger('LocalVoice:Runtime');\nconst DEFAULT_REQUEST_TIMEOUT_MS = 10 * 60_000;\n\ntype PendingRequest = {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n timeout: ReturnType<typeof setTimeout>;\n signal?: AbortSignal;\n abort?: () => void;\n onProgress?: (progress: LocalVoiceRuntimeProgress) => void;\n};\n\nexport interface LocalVoiceRuntimeProgress {\n status?: string;\n file?: string;\n progress?: number;\n loaded?: number;\n total?: number;\n}\n\nfunction resolveWorkerCommand(): { entry: string; args: string[] } {\n const configured = process.env.XOPC_VOICE_RUNTIME_ENTRY?.trim();\n if (configured) return { entry: configured, args: [configured] };\n\n const jsEntry = fileURLToPath(new URL('./runtime-worker.js', import.meta.url));\n if (existsSync(jsEntry)) return { entry: jsEntry, args: [jsEntry] };\n\n const tsEntry = fileURLToPath(new URL('./runtime-worker.ts', import.meta.url));\n if (existsSync(tsEntry)) return { entry: tsEntry, args: ['--import', 'tsx', tsEntry] };\n throw new Error('Bundled local voice runtime entry is missing');\n}\n\nexport class LocalVoiceRuntimeClient {\n private child: ChildProcessWithoutNullStreams | null = null;\n private nextId = 1;\n private pending = new Map<number, PendingRequest>();\n\n async request<T>(\n method: string,\n params: Record<string, unknown> = {},\n options: {\n signal?: AbortSignal;\n timeoutMs?: number;\n /** Health/status probes must never terminate an active model download on timeout. */\n stopOnTimeout?: boolean;\n onProgress?: (progress: LocalVoiceRuntimeProgress) => void;\n } = {},\n ): Promise<T> {\n options.signal?.throwIfAborted();\n const child = this.ensureStarted();\n const id = this.nextId++;\n return new Promise<T>((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.deletePending(id);\n reject(new Error(`Local voice runtime request timed out: ${method}`));\n if (options.stopOnTimeout !== false) this.stop();\n }, options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS);\n this.pending.set(id, {\n resolve: (value) => resolve(value as T),\n reject,\n timeout,\n signal: options.signal,\n onProgress: options.onProgress,\n });\n const abort = () => {\n const pending = this.pending.get(id);\n if (!pending) return;\n this.deletePending(id);\n pending.reject(new Error('Local voice transcription aborted'));\n this.stop();\n };\n const pending = this.pending.get(id);\n if (pending) pending.abort = abort;\n options.signal?.addEventListener('abort', abort, { once: true });\n child.stdin.write(`${JSON.stringify({ id, method, params })}\\n`, (error) => {\n if (!error) return;\n this.deletePending(id);\n reject(error);\n });\n });\n }\n\n stop(): void {\n const child = this.child;\n this.child = null;\n if (child && !child.killed) child.kill('SIGTERM');\n this.rejectAll(new Error('Local voice runtime stopped'));\n }\n\n private ensureStarted(): ChildProcessWithoutNullStreams {\n if (this.child && !this.child.killed) return this.child;\n const command = resolveWorkerCommand();\n const child = spawn(process.execPath, command.args, {\n env: {\n ...process.env,\n ELECTRON_RUN_AS_NODE: '1',\n XOPC_VOICE_MODEL_DIR: resolveLocalVoiceRootDir(),\n },\n stdio: ['pipe', 'pipe', 'pipe'],\n windowsHide: true,\n });\n this.child = child;\n createInterface({ input: child.stdout }).on('line', (line) => this.handleLine(line));\n child.stderr.on('data', (chunk: Buffer) => {\n const message = chunk.toString().trim();\n if (message) log.debug({ message }, 'Local voice runtime stderr');\n });\n child.once('error', (error) => {\n if (this.child === child) this.child = null;\n this.rejectAll(error);\n });\n child.once('exit', (code, signal) => {\n if (this.child === child) this.child = null;\n if (this.pending.size > 0) {\n this.rejectAll(new Error(`Local voice runtime exited (${code ?? signal ?? 'unknown'})`));\n }\n });\n return child;\n }\n\n private handleLine(line: string): void {\n let message: {\n id?: number;\n result?: unknown;\n error?: string | { message?: string; code?: string; cause?: string };\n event?: string;\n data?: unknown;\n };\n try {\n message = JSON.parse(line) as typeof message;\n } catch {\n log.warn({ linePreview: line.slice(0, 200) }, 'Ignored invalid local voice runtime output');\n return;\n }\n if (typeof message.id !== 'number') return;\n const pending = this.pending.get(message.id);\n if (!pending) return;\n if (message.event === 'progress') {\n pending.onProgress?.((message.data ?? {}) as LocalVoiceRuntimeProgress);\n return;\n }\n this.deletePending(message.id);\n if (message.error) {\n const detail = typeof message.error === 'string' ? { message: message.error } : message.error;\n const suffix = [detail.code, detail.cause].filter(Boolean).join(': ');\n const error = new Error(`${detail.message || 'Local voice runtime failed'}${suffix ? ` (${suffix})` : ''}`);\n if (detail.code) Object.assign(error, { code: detail.code });\n pending.reject(error);\n } else pending.resolve(message.result);\n }\n\n private rejectAll(error: Error): void {\n for (const pending of this.pending.values()) {\n clearTimeout(pending.timeout);\n if (pending.signal && pending.abort) {\n pending.signal.removeEventListener('abort', pending.abort);\n }\n pending.reject(error);\n }\n this.pending.clear();\n }\n\n private deletePending(id: number): void {\n const pending = this.pending.get(id);\n if (!pending) return;\n clearTimeout(pending.timeout);\n if (pending.signal && pending.abort) {\n pending.signal.removeEventListener('abort', pending.abort);\n }\n this.pending.delete(id);\n }\n}\n\nlet sharedRuntime: LocalVoiceRuntimeClient | undefined;\n\nexport function getLocalVoiceRuntimeClient(): LocalVoiceRuntimeClient {\n sharedRuntime ??= new LocalVoiceRuntimeClient();\n return sharedRuntime;\n}\n\nexport function resetLocalVoiceRuntimeForTests(): void {\n sharedRuntime?.stop();\n sharedRuntime = undefined;\n}\n"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export interface RuntimeDispatchRequest {
2
+ id: number;
3
+ method: string;
4
+ }
5
+ export declare function createRuntimeDispatcher<T extends RuntimeDispatchRequest>(options: {
6
+ execute: (request: T) => Promise<unknown>;
7
+ sendResult: (request: T, result: unknown) => void;
8
+ sendError: (request: T, error: unknown) => void;
9
+ }): (request: T) => void;
@@ -0,0 +1,22 @@
1
+ //#region src/voice/local/runtime-dispatcher.ts
2
+ function createRuntimeDispatcher(options) {
3
+ let queue = Promise.resolve();
4
+ const run = async (request) => {
5
+ try {
6
+ options.sendResult(request, await options.execute(request));
7
+ } catch (error) {
8
+ options.sendError(request, error);
9
+ }
10
+ };
11
+ return (request) => {
12
+ if (request.method === "health") {
13
+ run(request);
14
+ return;
15
+ }
16
+ queue = queue.then(() => run(request));
17
+ };
18
+ }
19
+ //#endregion
20
+ export { createRuntimeDispatcher };
21
+
22
+ //# sourceMappingURL=runtime-dispatcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-dispatcher.js","names":[],"sources":["../../../../src/voice/local/runtime-dispatcher.ts"],"sourcesContent":["export interface RuntimeDispatchRequest {\n id: number;\n method: string;\n}\n\nexport function createRuntimeDispatcher<T extends RuntimeDispatchRequest>(options: {\n execute: (request: T) => Promise<unknown>;\n sendResult: (request: T, result: unknown) => void;\n sendError: (request: T, error: unknown) => void;\n}): (request: T) => void {\n let queue = Promise.resolve();\n const run = async (request: T) => {\n try {\n options.sendResult(request, await options.execute(request));\n } catch (error) {\n options.sendError(request, error);\n }\n };\n\n return (request) => {\n if (request.method === 'health') {\n void run(request);\n return;\n }\n queue = queue.then(() => run(request));\n };\n}\n"],"mappings":";AAKA,SAAgB,wBAA0D,SAIjD;CACvB,IAAI,QAAQ,QAAQ,SAAS;CAC7B,MAAM,MAAM,OAAO,YAAe;AAChC,MAAI;AACF,WAAQ,WAAW,SAAS,MAAM,QAAQ,QAAQ,QAAQ,CAAC;WACpD,OAAO;AACd,WAAQ,UAAU,SAAS,MAAM;;;AAIrC,SAAQ,YAAY;AAClB,MAAI,QAAQ,WAAW,UAAU;AAC1B,OAAI,QAAQ;AACjB;;AAEF,UAAQ,MAAM,WAAW,IAAI,QAAQ,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,249 @@
1
+ import { getLocalVoiceModel, resolveLocalVoiceModelDir } from "./models.js";
2
+ import { downloadLocalVoiceModelFiles } from "./model-files.js";
3
+ import { createRuntimeDispatcher } from "./runtime-dispatcher.js";
4
+ import { join, resolve, sep } from "node:path";
5
+ import { mkdir, rm } from "node:fs/promises";
6
+ import { EnvHttpProxyAgent, RetryAgent, setGlobalDispatcher } from "undici";
7
+ import { createInterface } from "node:readline";
8
+ //#region src/voice/local/runtime-worker.ts
9
+ const pipelines = /* @__PURE__ */ new Map();
10
+ const sherpaRecognizers = /* @__PURE__ */ new Map();
11
+ const networkAgent = new RetryAgent(new EnvHttpProxyAgent(), {
12
+ maxRetries: 4,
13
+ minTimeout: 500,
14
+ maxTimeout: 8e3,
15
+ timeoutFactor: 2,
16
+ retryAfter: true
17
+ });
18
+ setGlobalDispatcher(networkAgent);
19
+ function normalizeRemoteHost(value) {
20
+ const url = new URL(value);
21
+ if (url.username || url.password) throw new Error("Local voice model endpoint must not contain credentials");
22
+ if (url.protocol !== "https:" && url.hostname !== "127.0.0.1" && url.hostname !== "localhost") throw new Error("Local voice model endpoint must use HTTPS");
23
+ url.pathname = `${url.pathname.replace(/\/+$/, "")}/`;
24
+ return url.toString();
25
+ }
26
+ function resolveRemoteHosts() {
27
+ const configured = process.env.XOPC_VOICE_MODEL_ENDPOINT?.trim() || process.env.HF_ENDPOINT?.trim();
28
+ if (configured) return [normalizeRemoteHost(configured)];
29
+ return [normalizeRemoteHost("https://xopc.ai/api/voice/models"), normalizeRemoteHost("https://huggingface.co")];
30
+ }
31
+ function serializeError(error) {
32
+ if (!(error instanceof Error)) return { message: String(error) };
33
+ const withCode = error;
34
+ const nested = withCode.cause;
35
+ const nestedMessage = nested instanceof Error ? nested.message : void 0;
36
+ const nestedCode = nested && typeof nested === "object" && "code" in nested ? String(nested.code ?? "") : void 0;
37
+ return {
38
+ message: error.message,
39
+ ...typeof withCode.code === "string" ? { code: withCode.code } : {},
40
+ ...nestedCode ? { code: nestedCode } : {},
41
+ ...nestedMessage && nestedMessage !== error.message ? { cause: nestedMessage } : {}
42
+ };
43
+ }
44
+ function send(message) {
45
+ process.stdout.write(`${JSON.stringify(message)}\n`);
46
+ }
47
+ async function loadPipeline(modelId, allowRemote, cacheDir = resolveLocalVoiceModelDir(modelId), onProgress) {
48
+ const key = `${modelId}:${cacheDir}`;
49
+ const existing = pipelines.get(key);
50
+ if (existing) return existing;
51
+ const model = getLocalVoiceModel(modelId);
52
+ if (model.engine !== "transformers.js") throw new Error(`Model ${model.id} does not use the Transformers.js engine`);
53
+ const promise = (async () => {
54
+ const transformers = await import("@huggingface/transformers");
55
+ transformers.env.cacheDir = cacheDir;
56
+ transformers.env.allowRemoteModels = allowRemote;
57
+ transformers.env.allowLocalModels = true;
58
+ const remoteHosts = allowRemote ? resolveRemoteHosts() : [normalizeRemoteHost("https://xopc.ai")];
59
+ let lastError;
60
+ for (const [index, remoteHost] of remoteHosts.entries()) {
61
+ transformers.env.remoteHost = remoteHost;
62
+ try {
63
+ return await transformers.pipeline("automatic-speech-recognition", model.repository, {
64
+ revision: model.revision,
65
+ dtype: model.dtype,
66
+ progress_callback: onProgress
67
+ });
68
+ } catch (error) {
69
+ lastError = error;
70
+ if (index + 1 < remoteHosts.length) {
71
+ await rm(cacheDir, {
72
+ recursive: true,
73
+ force: true
74
+ });
75
+ await mkdir(cacheDir, { recursive: true });
76
+ }
77
+ }
78
+ }
79
+ throw lastError;
80
+ })();
81
+ pipelines.set(key, promise);
82
+ try {
83
+ return await promise;
84
+ } catch (error) {
85
+ pipelines.delete(key);
86
+ throw error;
87
+ }
88
+ }
89
+ function normalizeSenseVoiceLanguage(language) {
90
+ if (typeof language !== "string") return "auto";
91
+ const value = language.trim().toLowerCase().replace("_", "-");
92
+ if (!value || value === "auto") return "auto";
93
+ if (value === "cmn" || value.startsWith("zh")) return "zh";
94
+ if (value === "cantonese" || value.startsWith("yue")) return "yue";
95
+ if (value.startsWith("en")) return "en";
96
+ if (value.startsWith("ja")) return "ja";
97
+ if (value.startsWith("ko")) return "ko";
98
+ return "auto";
99
+ }
100
+ function cleanSenseVoiceTag(value) {
101
+ return value?.replace(/^<\|/, "").replace(/\|>$/, "").trim() || void 0;
102
+ }
103
+ async function loadSherpaRecognizer(modelId, language) {
104
+ const key = `${modelId}:${language}`;
105
+ const existing = sherpaRecognizers.get(key);
106
+ if (existing) return existing;
107
+ const model = getLocalVoiceModel(modelId);
108
+ if (model.engine !== "sherpa-onnx") throw new Error(`Model ${model.id} does not use the sherpa-onnx engine`);
109
+ const modelDir = resolveLocalVoiceModelDir(model.id);
110
+ const promise = (async () => {
111
+ const imported = await import("sherpa-onnx-node");
112
+ return new (imported.default ?? imported).OfflineRecognizer({
113
+ featConfig: {
114
+ sampleRate: 16e3,
115
+ featureDim: 80
116
+ },
117
+ modelConfig: {
118
+ senseVoice: {
119
+ model: join(modelDir, "model.int8.onnx"),
120
+ language,
121
+ useInverseTextNormalization: 1
122
+ },
123
+ tokens: join(modelDir, "tokens.txt"),
124
+ numThreads: Math.max(1, Math.min(4, Number(process.env.XOPC_VOICE_THREADS) || 2)),
125
+ provider: "cpu",
126
+ debug: 0
127
+ }
128
+ });
129
+ })();
130
+ sherpaRecognizers.set(key, promise);
131
+ try {
132
+ return await promise;
133
+ } catch (error) {
134
+ sherpaRecognizers.delete(key);
135
+ throw error;
136
+ }
137
+ }
138
+ async function transcribeWithSherpa(modelId, audio, language) {
139
+ const recognizer = await loadSherpaRecognizer(modelId, normalizeSenseVoiceLanguage(language));
140
+ const stream = recognizer.createStream();
141
+ stream.acceptWaveform({
142
+ sampleRate: 16e3,
143
+ samples: audio
144
+ });
145
+ const result = recognizer.decodeAsync ? await recognizer.decodeAsync(stream) : (recognizer.decode(stream), recognizer.getResult(stream));
146
+ return {
147
+ text: String(result.text ?? "").trim(),
148
+ ...cleanSenseVoiceTag(result.lang) ? { language: cleanSenseVoiceTag(result.lang) } : {},
149
+ ...cleanSenseVoiceTag(result.emotion) ? { emotion: cleanSenseVoiceTag(result.emotion) } : {},
150
+ ...cleanSenseVoiceTag(result.event) ? { event: cleanSenseVoiceTag(result.event) } : {}
151
+ };
152
+ }
153
+ async function handle(request) {
154
+ const params = request.params ?? {};
155
+ if (request.method === "health") return {
156
+ ok: true,
157
+ protocolVersion: 2,
158
+ engine: "transformers.js+sherpa-onnx",
159
+ engines: ["transformers.js", "sherpa-onnx"]
160
+ };
161
+ if (request.method === "model.install") {
162
+ const modelId = String(params.modelId ?? "");
163
+ const modelDir = resolve(resolveLocalVoiceModelDir(modelId));
164
+ const requestedCacheDir = typeof params.cacheDir === "string" ? resolve(params.cacheDir) : modelDir;
165
+ const allowedPrefix = `${resolve(modelDir, "..")}${sep}`;
166
+ if (requestedCacheDir !== modelDir && !requestedCacheDir.startsWith(allowedPrefix)) throw new Error("Local voice model cache directory is outside the managed root");
167
+ const model = getLocalVoiceModel(modelId);
168
+ if (model.engine === "sherpa-onnx") await downloadLocalVoiceModelFiles({
169
+ model,
170
+ destinationDir: requestedCacheDir,
171
+ remoteHosts: resolveRemoteHosts(),
172
+ onProgress: (data) => send({
173
+ id: request.id,
174
+ event: "progress",
175
+ data
176
+ })
177
+ });
178
+ else {
179
+ await loadPipeline(modelId, true, requestedCacheDir, (data) => send({
180
+ id: request.id,
181
+ event: "progress",
182
+ data
183
+ }));
184
+ pipelines.delete(`${modelId}:${requestedCacheDir}`);
185
+ }
186
+ return {
187
+ installed: true,
188
+ modelId
189
+ };
190
+ }
191
+ if (request.method === "model.unload") {
192
+ const modelId = String(params.modelId ?? "");
193
+ for (const key of pipelines.keys()) if (key.startsWith(`${modelId}:`)) pipelines.delete(key);
194
+ for (const key of sherpaRecognizers.keys()) if (key.startsWith(`${modelId}:`)) sherpaRecognizers.delete(key);
195
+ return { unloaded: true };
196
+ }
197
+ if (request.method === "transcribe") {
198
+ const modelId = String(params.modelId ?? "");
199
+ const bytes = Buffer.from(String(params.audioBase64 ?? ""), "base64");
200
+ const copied = Uint8Array.from(bytes);
201
+ const audio = new Float32Array(copied.buffer);
202
+ const language = typeof params.language === "string" && params.language ? params.language : void 0;
203
+ const model = getLocalVoiceModel(modelId);
204
+ if (model.engine === "sherpa-onnx") return {
205
+ ...await transcribeWithSherpa(model.id, audio, language),
206
+ modelId
207
+ };
208
+ const output = await (await loadPipeline(modelId, false))(audio, {
209
+ task: "transcribe",
210
+ ...language ? { language } : {},
211
+ chunk_length_s: 30,
212
+ stride_length_s: 5,
213
+ return_timestamps: false
214
+ });
215
+ return {
216
+ text: (output && typeof output === "object" && "text" in output ? String(output.text ?? "") : "").trim(),
217
+ modelId
218
+ };
219
+ }
220
+ throw new Error(`Unknown local voice runtime method: ${request.method}`);
221
+ }
222
+ const lines = createInterface({ input: process.stdin });
223
+ const dispatch = createRuntimeDispatcher({
224
+ execute: handle,
225
+ sendResult: (request, result) => send({
226
+ id: request.id,
227
+ result
228
+ }),
229
+ sendError: (request, error) => send({
230
+ id: request.id,
231
+ error: serializeError(error)
232
+ })
233
+ });
234
+ lines.on("line", (line) => {
235
+ let request;
236
+ try {
237
+ request = JSON.parse(line);
238
+ } catch {
239
+ return;
240
+ }
241
+ dispatch(request);
242
+ });
243
+ lines.once("close", () => {
244
+ networkAgent.close().finally(() => process.exit(0));
245
+ });
246
+ //#endregion
247
+ export {};
248
+
249
+ //# sourceMappingURL=runtime-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-worker.js","names":[],"sources":["../../../../src/voice/local/runtime-worker.ts"],"sourcesContent":["import { createInterface } from 'node:readline';\nimport { join, resolve, sep } from 'node:path';\nimport { mkdir, rm } from 'node:fs/promises';\n\nimport { EnvHttpProxyAgent, RetryAgent, setGlobalDispatcher } from 'undici';\n\nimport { getLocalVoiceModel, resolveLocalVoiceModelDir } from './models.js';\nimport { downloadLocalVoiceModelFiles } from './model-files.js';\nimport { createRuntimeDispatcher } from './runtime-dispatcher.js';\n\ntype RuntimeRequest = { id: number; method: string; params?: Record<string, unknown> };\ntype AsrPipeline = (audio: Float32Array, options?: Record<string, unknown>) => Promise<unknown>;\n\nconst pipelines = new Map<string, Promise<AsrPipeline>>();\n\ninterface SherpaOfflineStream {\n acceptWaveform(input: { sampleRate: number; samples: Float32Array }): void;\n setOption?(key: string, value: string): void;\n}\n\ninterface SherpaResult {\n text?: string;\n lang?: string;\n emotion?: string;\n event?: string;\n}\n\ninterface SherpaOfflineRecognizer {\n createStream(): SherpaOfflineStream;\n decodeAsync?(stream: SherpaOfflineStream): Promise<SherpaResult>;\n decode(stream: SherpaOfflineStream): void;\n getResult(stream: SherpaOfflineStream): SherpaResult;\n}\n\ntype SherpaModule = {\n OfflineRecognizer: new (config: Record<string, unknown>) => SherpaOfflineRecognizer;\n};\n\nconst sherpaRecognizers = new Map<string, Promise<SherpaOfflineRecognizer>>();\n\nconst networkAgent = new RetryAgent(new EnvHttpProxyAgent(), {\n maxRetries: 4,\n minTimeout: 500,\n maxTimeout: 8_000,\n timeoutFactor: 2,\n retryAfter: true,\n});\nsetGlobalDispatcher(networkAgent);\n\nfunction normalizeRemoteHost(value: string): string {\n const url = new URL(value);\n if (url.username || url.password) {\n throw new Error('Local voice model endpoint must not contain credentials');\n }\n if (url.protocol !== 'https:' && url.hostname !== '127.0.0.1' && url.hostname !== 'localhost') {\n throw new Error('Local voice model endpoint must use HTTPS');\n }\n url.pathname = `${url.pathname.replace(/\\/+$/, '')}/`;\n return url.toString();\n}\n\nfunction resolveRemoteHosts(): string[] {\n const configured = process.env.XOPC_VOICE_MODEL_ENDPOINT?.trim()\n || process.env.HF_ENDPOINT?.trim();\n if (configured) return [normalizeRemoteHost(configured)];\n return [\n normalizeRemoteHost('https://xopc.ai/api/voice/models'),\n normalizeRemoteHost('https://huggingface.co'),\n ];\n}\n\nfunction serializeError(error: unknown): { message: string; code?: string; cause?: string } {\n if (!(error instanceof Error)) return { message: String(error) };\n const withCode = error as Error & { code?: unknown; cause?: unknown };\n const nested = withCode.cause;\n const nestedMessage = nested instanceof Error ? nested.message : undefined;\n const nestedCode = nested && typeof nested === 'object' && 'code' in nested\n ? String((nested as { code?: unknown }).code ?? '')\n : undefined;\n return {\n message: error.message,\n ...(typeof withCode.code === 'string' ? { code: withCode.code } : {}),\n ...(nestedCode ? { code: nestedCode } : {}),\n ...(nestedMessage && nestedMessage !== error.message ? { cause: nestedMessage } : {}),\n };\n}\n\nfunction send(message: Record<string, unknown>): void {\n process.stdout.write(`${JSON.stringify(message)}\\n`);\n}\n\nasync function loadPipeline(\n modelId: string,\n allowRemote: boolean,\n cacheDir = resolveLocalVoiceModelDir(modelId),\n onProgress?: (data: Record<string, unknown>) => void,\n): Promise<AsrPipeline> {\n const key = `${modelId}:${cacheDir}`;\n const existing = pipelines.get(key);\n if (existing) return existing;\n const model = getLocalVoiceModel(modelId);\n if (model.engine !== 'transformers.js') {\n throw new Error(`Model ${model.id} does not use the Transformers.js engine`);\n }\n const promise = (async () => {\n const transformers = await import('@huggingface/transformers');\n transformers.env.cacheDir = cacheDir;\n transformers.env.allowRemoteModels = allowRemote;\n transformers.env.allowLocalModels = true;\n const remoteHosts = allowRemote ? resolveRemoteHosts() : [normalizeRemoteHost('https://xopc.ai')];\n let lastError: unknown;\n for (const [index, remoteHost] of remoteHosts.entries()) {\n transformers.env.remoteHost = remoteHost;\n try {\n const result = await transformers.pipeline('automatic-speech-recognition', model.repository, {\n revision: model.revision,\n dtype: model.dtype,\n progress_callback: onProgress,\n });\n return result as unknown as AsrPipeline;\n } catch (error) {\n lastError = error;\n if (index + 1 < remoteHosts.length) {\n await rm(cacheDir, { recursive: true, force: true });\n await mkdir(cacheDir, { recursive: true });\n }\n }\n }\n throw lastError;\n })();\n pipelines.set(key, promise);\n try {\n return await promise;\n } catch (error) {\n pipelines.delete(key);\n throw error;\n }\n}\n\nfunction normalizeSenseVoiceLanguage(language: unknown): string {\n if (typeof language !== 'string') return 'auto';\n const value = language.trim().toLowerCase().replace('_', '-');\n if (!value || value === 'auto') return 'auto';\n if (value === 'cmn' || value.startsWith('zh')) return 'zh';\n if (value === 'cantonese' || value.startsWith('yue')) return 'yue';\n if (value.startsWith('en')) return 'en';\n if (value.startsWith('ja')) return 'ja';\n if (value.startsWith('ko')) return 'ko';\n return 'auto';\n}\n\nfunction cleanSenseVoiceTag(value: string | undefined): string | undefined {\n const cleaned = value?.replace(/^<\\|/, '').replace(/\\|>$/, '').trim();\n return cleaned || undefined;\n}\n\nasync function loadSherpaRecognizer(\n modelId: string,\n language: string,\n): Promise<SherpaOfflineRecognizer> {\n const key = `${modelId}:${language}`;\n const existing = sherpaRecognizers.get(key);\n if (existing) return existing;\n const model = getLocalVoiceModel(modelId);\n if (model.engine !== 'sherpa-onnx') {\n throw new Error(`Model ${model.id} does not use the sherpa-onnx engine`);\n }\n const modelDir = resolveLocalVoiceModelDir(model.id);\n const promise = (async () => {\n const imported = await import('sherpa-onnx-node');\n const sherpa = ((imported as { default?: SherpaModule }).default ?? imported) as SherpaModule;\n return new sherpa.OfflineRecognizer({\n featConfig: { sampleRate: 16_000, featureDim: 80 },\n modelConfig: {\n senseVoice: {\n model: join(modelDir, 'model.int8.onnx'),\n language,\n useInverseTextNormalization: 1,\n },\n tokens: join(modelDir, 'tokens.txt'),\n numThreads: Math.max(1, Math.min(4, Number(process.env.XOPC_VOICE_THREADS) || 2)),\n provider: 'cpu',\n debug: 0,\n },\n });\n })();\n sherpaRecognizers.set(key, promise);\n try {\n return await promise;\n } catch (error) {\n sherpaRecognizers.delete(key);\n throw error;\n }\n}\n\nasync function transcribeWithSherpa(\n modelId: string,\n audio: Float32Array,\n language: unknown,\n): Promise<{ text: string; language?: string; emotion?: string; event?: string }> {\n const recognizer = await loadSherpaRecognizer(modelId, normalizeSenseVoiceLanguage(language));\n const stream = recognizer.createStream();\n stream.acceptWaveform({ sampleRate: 16_000, samples: audio });\n const result = recognizer.decodeAsync\n ? await recognizer.decodeAsync(stream)\n : (recognizer.decode(stream), recognizer.getResult(stream));\n return {\n text: String(result.text ?? '').trim(),\n ...(cleanSenseVoiceTag(result.lang) ? { language: cleanSenseVoiceTag(result.lang) } : {}),\n ...(cleanSenseVoiceTag(result.emotion) ? { emotion: cleanSenseVoiceTag(result.emotion) } : {}),\n ...(cleanSenseVoiceTag(result.event) ? { event: cleanSenseVoiceTag(result.event) } : {}),\n };\n}\n\nasync function handle(request: RuntimeRequest): Promise<unknown> {\n const params = request.params ?? {};\n if (request.method === 'health') {\n return {\n ok: true,\n protocolVersion: 2,\n engine: 'transformers.js+sherpa-onnx',\n engines: ['transformers.js', 'sherpa-onnx'],\n };\n }\n if (request.method === 'model.install') {\n const modelId = String(params.modelId ?? '');\n const modelDir = resolve(resolveLocalVoiceModelDir(modelId));\n const requestedCacheDir = typeof params.cacheDir === 'string' ? resolve(params.cacheDir) : modelDir;\n const allowedPrefix = `${resolve(modelDir, '..')}${sep}`;\n if (requestedCacheDir !== modelDir && !requestedCacheDir.startsWith(allowedPrefix)) {\n throw new Error('Local voice model cache directory is outside the managed root');\n }\n const model = getLocalVoiceModel(modelId);\n if (model.engine === 'sherpa-onnx') {\n await downloadLocalVoiceModelFiles({\n model,\n destinationDir: requestedCacheDir,\n remoteHosts: resolveRemoteHosts(),\n onProgress: (data) => send({ id: request.id, event: 'progress', data }),\n });\n } else {\n await loadPipeline(\n modelId,\n true,\n requestedCacheDir,\n (data) => send({ id: request.id, event: 'progress', data }),\n );\n pipelines.delete(`${modelId}:${requestedCacheDir}`);\n }\n return { installed: true, modelId };\n }\n if (request.method === 'model.unload') {\n const modelId = String(params.modelId ?? '');\n for (const key of pipelines.keys()) {\n if (key.startsWith(`${modelId}:`)) pipelines.delete(key);\n }\n for (const key of sherpaRecognizers.keys()) {\n if (key.startsWith(`${modelId}:`)) sherpaRecognizers.delete(key);\n }\n return { unloaded: true };\n }\n if (request.method === 'transcribe') {\n const modelId = String(params.modelId ?? '');\n const bytes = Buffer.from(String(params.audioBase64 ?? ''), 'base64');\n const copied = Uint8Array.from(bytes);\n const audio = new Float32Array(copied.buffer);\n const language = typeof params.language === 'string' && params.language ? params.language : undefined;\n const model = getLocalVoiceModel(modelId);\n if (model.engine === 'sherpa-onnx') {\n return { ...(await transcribeWithSherpa(model.id, audio, language)), modelId };\n }\n const pipeline = await loadPipeline(modelId, false);\n const output = await pipeline(audio, {\n task: 'transcribe',\n ...(language ? { language } : {}),\n chunk_length_s: 30,\n stride_length_s: 5,\n return_timestamps: false,\n });\n const text = output && typeof output === 'object' && 'text' in output\n ? String((output as { text?: unknown }).text ?? '')\n : '';\n return { text: text.trim(), modelId };\n }\n throw new Error(`Unknown local voice runtime method: ${request.method}`);\n}\n\nconst lines = createInterface({ input: process.stdin });\nconst dispatch = createRuntimeDispatcher<RuntimeRequest>({\n execute: handle,\n sendResult: (request, result) => send({ id: request.id, result }),\n sendError: (request, error) => send({ id: request.id, error: serializeError(error) }),\n});\nlines.on('line', (line) => {\n let request: RuntimeRequest;\n try {\n request = JSON.parse(line) as RuntimeRequest;\n } catch {\n return;\n }\n dispatch(request);\n});\nlines.once('close', () => {\n void networkAgent.close().finally(() => process.exit(0));\n});\n"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export interface DecodedPcmAudio {
2
+ samples: Float32Array;
3
+ sampleRate: number;
4
+ durationSeconds: number;
5
+ }
6
+ export declare function decodeWavToMonoFloat32(buffer: Buffer, targetRate?: number): DecodedPcmAudio;
@@ -0,0 +1,69 @@
1
+ //#region src/voice/local/wav.ts
2
+ function readChunkId(buffer, offset) {
3
+ return buffer.toString("ascii", offset, offset + 4);
4
+ }
5
+ function resampleLinear(input, sourceRate, targetRate) {
6
+ if (sourceRate === targetRate) return input;
7
+ const outputLength = Math.max(1, Math.round(input.length * targetRate / sourceRate));
8
+ const output = new Float32Array(outputLength);
9
+ const ratio = sourceRate / targetRate;
10
+ for (let i = 0; i < outputLength; i += 1) {
11
+ const sourcePosition = i * ratio;
12
+ const left = Math.min(input.length - 1, Math.floor(sourcePosition));
13
+ const right = Math.min(input.length - 1, left + 1);
14
+ const fraction = sourcePosition - left;
15
+ output[i] = input[left] * (1 - fraction) + input[right] * fraction;
16
+ }
17
+ return output;
18
+ }
19
+ function decodeWavToMonoFloat32(buffer, targetRate = 16e3) {
20
+ if (buffer.length < 44 || readChunkId(buffer, 0) !== "RIFF" || readChunkId(buffer, 8) !== "WAVE") throw new Error("Local STT currently requires PCM WAV audio");
21
+ let offset = 12;
22
+ let format;
23
+ let dataOffset = -1;
24
+ let dataLength = 0;
25
+ while (offset + 8 <= buffer.length) {
26
+ const id = readChunkId(buffer, offset);
27
+ const length = buffer.readUInt32LE(offset + 4);
28
+ const bodyOffset = offset + 8;
29
+ if (bodyOffset + length > buffer.length) break;
30
+ if (id === "fmt " && length >= 16) format = {
31
+ audioFormat: buffer.readUInt16LE(bodyOffset),
32
+ channels: buffer.readUInt16LE(bodyOffset + 2),
33
+ sampleRate: buffer.readUInt32LE(bodyOffset + 4),
34
+ bitsPerSample: buffer.readUInt16LE(bodyOffset + 14)
35
+ };
36
+ else if (id === "data") {
37
+ dataOffset = bodyOffset;
38
+ dataLength = length;
39
+ break;
40
+ }
41
+ offset = bodyOffset + length + length % 2;
42
+ }
43
+ if (!format || dataOffset < 0 || dataLength === 0) throw new Error("WAV audio is missing format or data chunks");
44
+ if (format.channels < 1 || format.channels > 8 || format.sampleRate < 8e3) throw new Error("Unsupported WAV channel count or sample rate");
45
+ const bytesPerSample = format.bitsPerSample / 8;
46
+ if (!Number.isInteger(bytesPerSample) || bytesPerSample < 2) throw new Error(`Unsupported WAV bit depth: ${format.bitsPerSample}`);
47
+ const frameBytes = bytesPerSample * format.channels;
48
+ const frameCount = Math.floor(dataLength / frameBytes);
49
+ const mono = new Float32Array(frameCount);
50
+ for (let frame = 0; frame < frameCount; frame += 1) {
51
+ let sum = 0;
52
+ for (let channel = 0; channel < format.channels; channel += 1) {
53
+ const sampleOffset = dataOffset + frame * frameBytes + channel * bytesPerSample;
54
+ if (format.audioFormat === 1 && format.bitsPerSample === 16) sum += buffer.readInt16LE(sampleOffset) / 32768;
55
+ else if (format.audioFormat === 3 && format.bitsPerSample === 32) sum += buffer.readFloatLE(sampleOffset);
56
+ else throw new Error(`Unsupported WAV encoding: format ${format.audioFormat}, ${format.bitsPerSample}-bit`);
57
+ }
58
+ mono[frame] = Math.max(-1, Math.min(1, sum / format.channels));
59
+ }
60
+ return {
61
+ samples: resampleLinear(mono, format.sampleRate, targetRate),
62
+ sampleRate: targetRate,
63
+ durationSeconds: frameCount / format.sampleRate
64
+ };
65
+ }
66
+ //#endregion
67
+ export { decodeWavToMonoFloat32 };
68
+
69
+ //# sourceMappingURL=wav.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wav.js","names":[],"sources":["../../../../src/voice/local/wav.ts"],"sourcesContent":["export interface DecodedPcmAudio {\n samples: Float32Array;\n sampleRate: number;\n durationSeconds: number;\n}\n\nfunction readChunkId(buffer: Buffer, offset: number): string {\n return buffer.toString('ascii', offset, offset + 4);\n}\n\nfunction resampleLinear(input: Float32Array, sourceRate: number, targetRate: number): Float32Array {\n if (sourceRate === targetRate) return input;\n const outputLength = Math.max(1, Math.round((input.length * targetRate) / sourceRate));\n const output = new Float32Array(outputLength);\n const ratio = sourceRate / targetRate;\n for (let i = 0; i < outputLength; i += 1) {\n const sourcePosition = i * ratio;\n const left = Math.min(input.length - 1, Math.floor(sourcePosition));\n const right = Math.min(input.length - 1, left + 1);\n const fraction = sourcePosition - left;\n output[i] = input[left]! * (1 - fraction) + input[right]! * fraction;\n }\n return output;\n}\n\nexport function decodeWavToMonoFloat32(buffer: Buffer, targetRate = 16_000): DecodedPcmAudio {\n if (buffer.length < 44 || readChunkId(buffer, 0) !== 'RIFF' || readChunkId(buffer, 8) !== 'WAVE') {\n throw new Error('Local STT currently requires PCM WAV audio');\n }\n\n let offset = 12;\n let format: { audioFormat: number; channels: number; sampleRate: number; bitsPerSample: number } | undefined;\n let dataOffset = -1;\n let dataLength = 0;\n while (offset + 8 <= buffer.length) {\n const id = readChunkId(buffer, offset);\n const length = buffer.readUInt32LE(offset + 4);\n const bodyOffset = offset + 8;\n if (bodyOffset + length > buffer.length) break;\n if (id === 'fmt ' && length >= 16) {\n format = {\n audioFormat: buffer.readUInt16LE(bodyOffset),\n channels: buffer.readUInt16LE(bodyOffset + 2),\n sampleRate: buffer.readUInt32LE(bodyOffset + 4),\n bitsPerSample: buffer.readUInt16LE(bodyOffset + 14),\n };\n } else if (id === 'data') {\n dataOffset = bodyOffset;\n dataLength = length;\n break;\n }\n offset = bodyOffset + length + (length % 2);\n }\n\n if (!format || dataOffset < 0 || dataLength === 0) {\n throw new Error('WAV audio is missing format or data chunks');\n }\n if (format.channels < 1 || format.channels > 8 || format.sampleRate < 8_000) {\n throw new Error('Unsupported WAV channel count or sample rate');\n }\n const bytesPerSample = format.bitsPerSample / 8;\n if (!Number.isInteger(bytesPerSample) || bytesPerSample < 2) {\n throw new Error(`Unsupported WAV bit depth: ${format.bitsPerSample}`);\n }\n const frameBytes = bytesPerSample * format.channels;\n const frameCount = Math.floor(dataLength / frameBytes);\n const mono = new Float32Array(frameCount);\n for (let frame = 0; frame < frameCount; frame += 1) {\n let sum = 0;\n for (let channel = 0; channel < format.channels; channel += 1) {\n const sampleOffset = dataOffset + frame * frameBytes + channel * bytesPerSample;\n if (format.audioFormat === 1 && format.bitsPerSample === 16) {\n sum += buffer.readInt16LE(sampleOffset) / 32768;\n } else if (format.audioFormat === 3 && format.bitsPerSample === 32) {\n sum += buffer.readFloatLE(sampleOffset);\n } else {\n throw new Error(`Unsupported WAV encoding: format ${format.audioFormat}, ${format.bitsPerSample}-bit`);\n }\n }\n mono[frame] = Math.max(-1, Math.min(1, sum / format.channels));\n }\n\n const samples = resampleLinear(mono, format.sampleRate, targetRate);\n return {\n samples,\n sampleRate: targetRate,\n durationSeconds: frameCount / format.sampleRate,\n };\n}\n"],"mappings":";AAMA,SAAS,YAAY,QAAgB,QAAwB;AAC3D,QAAO,OAAO,SAAS,SAAS,QAAQ,SAAS,EAAE;;AAGrD,SAAS,eAAe,OAAqB,YAAoB,YAAkC;AACjG,KAAI,eAAe,WAAY,QAAO;CACtC,MAAM,eAAe,KAAK,IAAI,GAAG,KAAK,MAAO,MAAM,SAAS,aAAc,WAAW,CAAC;CACtF,MAAM,SAAS,IAAI,aAAa,aAAa;CAC7C,MAAM,QAAQ,aAAa;AAC3B,MAAK,IAAI,IAAI,GAAG,IAAI,cAAc,KAAK,GAAG;EACxC,MAAM,iBAAiB,IAAI;EAC3B,MAAM,OAAO,KAAK,IAAI,MAAM,SAAS,GAAG,KAAK,MAAM,eAAe,CAAC;EACnE,MAAM,QAAQ,KAAK,IAAI,MAAM,SAAS,GAAG,OAAO,EAAE;EAClD,MAAM,WAAW,iBAAiB;AAClC,SAAO,KAAK,MAAM,SAAU,IAAI,YAAY,MAAM,SAAU;;AAE9D,QAAO;;AAGT,SAAgB,uBAAuB,QAAgB,aAAa,MAAyB;AAC3F,KAAI,OAAO,SAAS,MAAM,YAAY,QAAQ,EAAE,KAAK,UAAU,YAAY,QAAQ,EAAE,KAAK,OACxF,OAAM,IAAI,MAAM,6CAA6C;CAG/D,IAAI,SAAS;CACb,IAAI;CACJ,IAAI,aAAa;CACjB,IAAI,aAAa;AACjB,QAAO,SAAS,KAAK,OAAO,QAAQ;EAClC,MAAM,KAAK,YAAY,QAAQ,OAAO;EACtC,MAAM,SAAS,OAAO,aAAa,SAAS,EAAE;EAC9C,MAAM,aAAa,SAAS;AAC5B,MAAI,aAAa,SAAS,OAAO,OAAQ;AACzC,MAAI,OAAO,UAAU,UAAU,GAC7B,UAAS;GACP,aAAa,OAAO,aAAa,WAAW;GAC5C,UAAU,OAAO,aAAa,aAAa,EAAE;GAC7C,YAAY,OAAO,aAAa,aAAa,EAAE;GAC/C,eAAe,OAAO,aAAa,aAAa,GAAG;GACpD;WACQ,OAAO,QAAQ;AACxB,gBAAa;AACb,gBAAa;AACb;;AAEF,WAAS,aAAa,SAAU,SAAS;;AAG3C,KAAI,CAAC,UAAU,aAAa,KAAK,eAAe,EAC9C,OAAM,IAAI,MAAM,6CAA6C;AAE/D,KAAI,OAAO,WAAW,KAAK,OAAO,WAAW,KAAK,OAAO,aAAa,IACpE,OAAM,IAAI,MAAM,+CAA+C;CAEjE,MAAM,iBAAiB,OAAO,gBAAgB;AAC9C,KAAI,CAAC,OAAO,UAAU,eAAe,IAAI,iBAAiB,EACxD,OAAM,IAAI,MAAM,8BAA8B,OAAO,gBAAgB;CAEvE,MAAM,aAAa,iBAAiB,OAAO;CAC3C,MAAM,aAAa,KAAK,MAAM,aAAa,WAAW;CACtD,MAAM,OAAO,IAAI,aAAa,WAAW;AACzC,MAAK,IAAI,QAAQ,GAAG,QAAQ,YAAY,SAAS,GAAG;EAClD,IAAI,MAAM;AACV,OAAK,IAAI,UAAU,GAAG,UAAU,OAAO,UAAU,WAAW,GAAG;GAC7D,MAAM,eAAe,aAAa,QAAQ,aAAa,UAAU;AACjE,OAAI,OAAO,gBAAgB,KAAK,OAAO,kBAAkB,GACvD,QAAO,OAAO,YAAY,aAAa,GAAG;YACjC,OAAO,gBAAgB,KAAK,OAAO,kBAAkB,GAC9D,QAAO,OAAO,YAAY,aAAa;OAEvC,OAAM,IAAI,MAAM,oCAAoC,OAAO,YAAY,IAAI,OAAO,cAAc,MAAM;;AAG1G,OAAK,SAAS,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,MAAM,OAAO,SAAS,CAAC;;AAIhE,QAAO;EACL,SAFc,eAAe,MAAM,OAAO,YAAY,WAE/C;EACP,YAAY;EACZ,iBAAiB,aAAa,OAAO;EACtC"}