@xopcai/xopc 0.0.143 → 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 (259) 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/Combination-DolwnuKi.js +41 -0
  4. package/dist/gateway/static/root/assets/{activity-center-store-jITiX2vJ.js → activity-center-store-3l9ahUqb.js} +1 -1
  5. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DiME9u_P.js → agent-avatar-dicebear-BEUxdhZx.js} +1 -1
  6. package/dist/gateway/static/root/assets/agents-1bpT0xRO.js +2 -0
  7. package/dist/gateway/static/root/assets/app-management-settings-panel-CRHSZJWi.js +1 -0
  8. package/dist/gateway/static/root/assets/{appearance-settings-DUfdNQqk.js → appearance-settings-BunADYJb.js} +1 -1
  9. package/dist/gateway/static/root/assets/apps-page-Cc4JgVUQ.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-B-Qk6cGr.js → archive-plugin-B6vTkH2A.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-Di6EEbQX.js → attachment-load-BjZXzaNv.js} +1 -1
  12. package/dist/gateway/static/root/assets/{automation-suggestion-card-DGxvRxtO.js → automation-suggestion-card-ZDA-Stg1.js} +1 -1
  13. package/dist/gateway/static/root/assets/automations-page-mb0fdVpq.js +6 -0
  14. package/dist/gateway/static/root/assets/{binary-plugins-ZaOZDH2I.js → binary-plugins-DYZfLvPz.js} +1 -1
  15. package/dist/gateway/static/root/assets/{block-editor-BTFhjWfg.js → block-editor-C3MUlYC9.js} +46 -46
  16. package/dist/gateway/static/root/assets/browser-settings-page-Bb0xhaMN.js +8 -0
  17. package/dist/gateway/static/root/assets/capability-presets-api-BV76yN9a.js +1 -0
  18. package/dist/gateway/static/root/assets/capability-presets-settings-panel-CUcGKZqC.js +2 -0
  19. package/dist/gateway/static/root/assets/channel-recipient-api-fTlTnWB4.js +1 -0
  20. package/dist/gateway/static/root/assets/channels-settings-BlSDMGdy.js +1 -0
  21. package/dist/gateway/static/root/assets/channels-status-swr-CJauF1CW.js +1 -0
  22. package/dist/gateway/static/root/assets/{code-editor--tMO38Tr.js → code-editor-D4_k-6QN.js} +1 -1
  23. package/dist/gateway/static/root/assets/connector-logo-BVFNT2zW.js +1 -0
  24. package/dist/gateway/static/root/assets/connectors-page-CMgAFGvb.js +2 -0
  25. package/dist/gateway/static/root/assets/copy-to-clipboard-HOJ79TWv.js +1 -0
  26. package/dist/gateway/static/root/assets/{desktop-pet---yzVxVR.js → desktop-pet-_jUmoXd3.js} +1 -1
  27. package/dist/gateway/static/root/assets/{desktop-pet-settings-Dc3gqBJE.js → desktop-pet-settings-DwGOy4AQ.js} +1 -1
  28. package/dist/gateway/static/root/assets/{directory-picker-path-field-DCmOGLtK.js → directory-picker-path-field-akvF0F-u.js} +1 -1
  29. package/dist/gateway/static/root/assets/dist-C99RGfAH.js +1 -0
  30. package/dist/gateway/static/root/assets/dreaming-settings-BLetQiYY.js +3 -0
  31. package/dist/gateway/static/root/assets/{extension-debug-page-ByaKTTq4.js → extension-debug-page-Cof2ncxE.js} +1 -1
  32. package/dist/gateway/static/root/assets/{extension-page-BmRzHAZr.js → extension-page-CwWktRNz.js} +1 -1
  33. package/dist/gateway/static/root/assets/extension-settings-page-CuggWOIl.js +1 -0
  34. package/dist/gateway/static/root/assets/gateway-config-api-B7sxIbza.js +1 -0
  35. package/dist/gateway/static/root/assets/gateway-settings-DIv0eKMf.js +1 -0
  36. package/dist/gateway/static/root/assets/gateway-startup-retry-DtoLihQE.js +1 -0
  37. package/dist/gateway/static/root/assets/goal-create-dialog-C4Kw0mfS.js +1 -0
  38. package/dist/gateway/static/root/assets/goal-detail-page-BMmzYpZL.js +4 -0
  39. package/dist/gateway/static/root/assets/goals-config-api-B0jm5JaA.js +1 -0
  40. package/dist/gateway/static/root/assets/goals-page-CGeT77PC.js +2 -0
  41. package/dist/gateway/static/root/assets/goals-settings-N5_iL7es.js +1 -0
  42. package/dist/gateway/static/root/assets/heartbeat-settings-XzH3lbRR.js +1 -0
  43. package/dist/gateway/static/root/assets/{html-workspace-editor-COqmtESs.js → html-workspace-editor-C3DKAkMc.js} +1 -1
  44. package/dist/gateway/static/root/assets/index-CSLF84-Q.css +1 -0
  45. package/dist/gateway/static/root/assets/index-I-ZCenVw.js +259 -0
  46. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-x_v0nrIi.js +1 -0
  47. package/dist/gateway/static/root/assets/locale-store-CiM-D9jA.js +1 -0
  48. package/dist/gateway/static/root/assets/logs-page-BSh1t8cD.js +7 -0
  49. package/dist/gateway/static/root/assets/markdown-editor-BvUebh3C.js +2 -0
  50. package/dist/gateway/static/root/assets/{markdown-split-Dw-yE2-y.js → markdown-split-5rJx5flj.js} +1 -1
  51. package/dist/gateway/static/root/assets/{media-plugins-D9NNNUgE.js → media-plugins-DYXccwAd.js} +1 -1
  52. package/dist/gateway/static/root/assets/messages-Cb1VMeqP.js +5 -0
  53. package/dist/gateway/static/root/assets/models-hub-panel-BNpTenAI.js +2 -0
  54. package/dist/gateway/static/root/assets/{notes-page-CRgbJGgk.js → notes-page-BgLyndCO.js} +1 -1
  55. package/dist/gateway/static/root/assets/notes-workbench-teklkhcE.js +4 -0
  56. package/dist/gateway/static/root/assets/{page-tabs-D4hkWVt_.js → page-tabs-6Al9_sGz.js} +1 -1
  57. package/dist/gateway/static/root/assets/{preview-open-alternatives-CIckv0uy.js → preview-open-alternatives-Cm3G72Hv.js} +1 -1
  58. package/dist/gateway/static/root/assets/project-detail-page-CCB_dKoh.js +1 -0
  59. package/dist/gateway/static/root/assets/projects-page-VOAFAHYj.js +1 -0
  60. package/dist/gateway/static/root/assets/remote-access-hub-USYu64Ru.js +1 -0
  61. package/dist/gateway/static/root/assets/{save-bar-controls-B0b42kB2.js → save-bar-controls-BYtfzu_F.js} +1 -1
  62. package/dist/gateway/static/root/assets/{schedule-field-BtjEkczK.js → schedule-field-CvIRc6yK.js} +1 -1
  63. package/dist/gateway/static/root/assets/{schema-form-Bf0bk3i6.js → schema-form-CQuKx0n7.js} +1 -1
  64. package/dist/gateway/static/root/assets/sessions-page-oGC8O5h_.js +1 -0
  65. package/dist/gateway/static/root/assets/settings-advanced-gate-D4rP66R1.js +1 -0
  66. package/dist/gateway/static/root/assets/{settings-collapsible-section-BTKTdTNX.js → settings-collapsible-section-CF3HHM-t.js} +1 -1
  67. package/dist/gateway/static/root/assets/{settings-form-section-DL4P0sAj.js → settings-form-section-CwWjoRN6.js} +1 -1
  68. package/dist/gateway/static/root/assets/{settings-loading-skeleton-BV6KFNj4.js → settings-loading-skeleton-aUFmJa13.js} +1 -1
  69. package/dist/gateway/static/root/assets/{settings-page-B_4DsX5W.js → settings-page-B2UUU9TF.js} +1 -1
  70. package/dist/gateway/static/root/assets/{settings-page-layout-CyGlrInB.js → settings-page-layout-DqpbTWqI.js} +1 -1
  71. package/dist/gateway/static/root/assets/setup-status-panel-Ck9keROI.js +1 -0
  72. package/dist/gateway/static/root/assets/share-preview-page-BOhlPsS1.js +2 -0
  73. package/dist/gateway/static/root/assets/shares-settings-BYLsCuqj.js +1 -0
  74. package/dist/gateway/static/root/assets/skill-reload-api-BNHUyVML.js +1 -0
  75. package/dist/gateway/static/root/assets/skills-page-CpXbQH4n.js +2 -0
  76. package/dist/gateway/static/root/assets/{system-settings-panel-D85fBBuI.js → system-settings-panel-CWxSvuwD.js} +1 -1
  77. package/dist/gateway/static/root/assets/{theme-store-Bt6vAkSB.js → theme-store-C9Dxcppm.js} +1 -1
  78. package/dist/gateway/static/root/assets/{typed-models-lib-CwEuYrHX.js → typed-models-lib-qROAvqTw.js} +1 -1
  79. package/dist/gateway/static/root/assets/use-channel-catalog-DE9cpn4G.js +1 -0
  80. package/dist/gateway/static/root/assets/user-context-page-DbNEK4Yp.js +1 -0
  81. package/dist/gateway/static/root/assets/user-profile-fields-editor-CWxc0ghP.js +1 -0
  82. package/dist/gateway/static/root/assets/{user-profile-settings-panel-CWM0fEpb.js → user-profile-settings-panel-DW-Up6vt.js} +1 -1
  83. package/dist/gateway/static/root/assets/{utils--BO6xT3u.js → utils-D53uRXVr.js} +1 -1
  84. package/dist/gateway/static/root/assets/{vendor-codemirror-C1WKjCk5.js → vendor-codemirror--gTq3YAI.js} +17 -17
  85. package/dist/gateway/static/root/assets/voice-api-key-field-Cs7MOrg0.js +1 -0
  86. package/dist/gateway/static/root/assets/work-item-detail-page-D1ziG1Pp.js +1 -0
  87. package/dist/gateway/static/root/assets/workflow-run-setup-panel-D_x9ELJp.js +3 -0
  88. package/dist/gateway/static/root/assets/workflows-page-DHGV_n6i.js +11 -0
  89. package/dist/gateway/static/root/index.html +10 -10
  90. package/dist/package.js +1 -1
  91. package/dist/src/agent/embedded/session-runner.js +3 -3
  92. package/dist/src/agent/embedded/session-runner.js.map +1 -1
  93. package/dist/src/agent/embedded/xopc-auth-storage.d.ts +3 -1
  94. package/dist/src/agent/embedded/xopc-auth-storage.js +11 -1
  95. package/dist/src/agent/embedded/xopc-auth-storage.js.map +1 -1
  96. package/dist/src/agent/memory/dreaming/config.js +1 -1
  97. package/dist/src/agent-runtime/index.js +1 -1
  98. package/dist/src/agent-runtime/runtime-profile.js +1 -1
  99. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  100. package/dist/src/config/agent-profile.js +1 -1
  101. package/dist/src/config/index.js +2 -2
  102. package/dist/src/config/schema.d.ts +60 -5
  103. package/dist/src/config/schema.js +30 -9
  104. package/dist/src/config/schema.js.map +1 -1
  105. package/dist/src/connectors/composio-catalog.js +11 -2
  106. package/dist/src/connectors/composio-catalog.js.map +1 -1
  107. package/dist/src/connectors/connector-memory-sync.js +135 -26
  108. package/dist/src/connectors/connector-memory-sync.js.map +1 -1
  109. package/dist/src/gateway/agents-admin.js +1 -1
  110. package/dist/src/gateway/heartbeat/service.js +1 -1
  111. package/dist/src/gateway/hono/app.js +1 -1
  112. package/dist/src/gateway/hono/app.js.map +1 -1
  113. package/dist/src/gateway/hono/lib/config-payload.d.ts +11 -0
  114. package/dist/src/gateway/hono/lib/config-payload.js +1 -0
  115. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  116. package/dist/src/gateway/hono/routes/config-patch/misc.js +6 -1
  117. package/dist/src/gateway/hono/routes/config-patch/misc.js.map +1 -1
  118. package/dist/src/gateway/hono/routes/memory.js +11 -1
  119. package/dist/src/gateway/hono/routes/memory.js.map +1 -1
  120. package/dist/src/gateway/hono/routes/status.js +3 -0
  121. package/dist/src/gateway/hono/routes/status.js.map +1 -1
  122. package/dist/src/gateway/hono/routes/voice.d.ts +5 -5
  123. package/dist/src/gateway/hono/routes/voice.js +288 -62
  124. package/dist/src/gateway/hono/routes/voice.js.map +1 -1
  125. package/dist/src/gateway/hono/routes/you.js +5 -1
  126. package/dist/src/gateway/hono/routes/you.js.map +1 -1
  127. package/dist/src/gateway/service.d.ts +8 -0
  128. package/dist/src/gateway/service.js +41 -11
  129. package/dist/src/gateway/service.js.map +1 -1
  130. package/dist/src/heartbeat/index.js +1 -1
  131. package/dist/src/knowledge/connected-knowledge-pipeline.d.ts +21 -0
  132. package/dist/src/knowledge/connected-knowledge-pipeline.js +267 -0
  133. package/dist/src/knowledge/connected-knowledge-pipeline.js.map +1 -0
  134. package/dist/src/knowledge/coordinator.d.ts +10 -0
  135. package/dist/src/knowledge/coordinator.js +52 -0
  136. package/dist/src/knowledge/coordinator.js.map +1 -0
  137. package/dist/src/knowledge/index.d.ts +2 -0
  138. package/dist/src/knowledge/index.js +3 -1
  139. package/dist/src/knowledge/ingestion-service.d.ts +7 -1
  140. package/dist/src/knowledge/ingestion-service.js +28 -0
  141. package/dist/src/knowledge/ingestion-service.js.map +1 -1
  142. package/dist/src/knowledge/types.d.ts +18 -0
  143. package/dist/src/media-understanding/audio-transcription-runner.js +5 -3
  144. package/dist/src/media-understanding/audio-transcription-runner.js.map +1 -1
  145. package/dist/src/media-understanding/runner.js +8 -3
  146. package/dist/src/media-understanding/runner.js.map +1 -1
  147. package/dist/src/media-understanding/types.d.ts +7 -0
  148. package/dist/src/storage/sqlite/index.d.ts +1 -1
  149. package/dist/src/storage/sqlite/index.js +2 -2
  150. package/dist/src/storage/sqlite/knowledge-repository.d.ts +26 -1
  151. package/dist/src/storage/sqlite/knowledge-repository.js +120 -6
  152. package/dist/src/storage/sqlite/knowledge-repository.js.map +1 -1
  153. package/dist/src/storage/sqlite/migrations/037_connected_knowledge_pipeline.sql +47 -0
  154. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  155. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  156. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  157. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  158. package/dist/src/storage/sqlite/schema.js +1 -1
  159. package/dist/src/user-context/projection.d.ts +13 -4
  160. package/dist/src/user-context/projection.js +19 -7
  161. package/dist/src/user-context/projection.js.map +1 -1
  162. package/dist/src/voice/language-profile.d.ts +20 -0
  163. package/dist/src/voice/language-profile.js +156 -0
  164. package/dist/src/voice/language-profile.js.map +1 -0
  165. package/dist/src/voice/local/model-files.d.ts +14 -0
  166. package/dist/src/voice/local/model-files.js +94 -0
  167. package/dist/src/voice/local/model-files.js.map +1 -0
  168. package/dist/src/voice/local/model-manager.d.ts +18 -0
  169. package/dist/src/voice/local/model-manager.js +135 -0
  170. package/dist/src/voice/local/model-manager.js.map +1 -0
  171. package/dist/src/voice/local/models.d.ts +28 -0
  172. package/dist/src/voice/local/models.js +101 -0
  173. package/dist/src/voice/local/models.js.map +1 -0
  174. package/dist/src/voice/local/runtime-client.d.ts +26 -0
  175. package/dist/src/voice/local/runtime-client.js +166 -0
  176. package/dist/src/voice/local/runtime-client.js.map +1 -0
  177. package/dist/src/voice/local/runtime-dispatcher.d.ts +9 -0
  178. package/dist/src/voice/local/runtime-dispatcher.js +22 -0
  179. package/dist/src/voice/local/runtime-dispatcher.js.map +1 -0
  180. package/dist/src/voice/local/runtime-worker.d.ts +1 -0
  181. package/dist/src/voice/local/runtime-worker.js +249 -0
  182. package/dist/src/voice/local/runtime-worker.js.map +1 -0
  183. package/dist/src/voice/local/wav.d.ts +6 -0
  184. package/dist/src/voice/local/wav.js +69 -0
  185. package/dist/src/voice/local/wav.js.map +1 -0
  186. package/dist/src/voice/metadata/builtin.js +46 -0
  187. package/dist/src/voice/metadata/builtin.js.map +1 -1
  188. package/dist/src/voice/stt/factory.js +8 -2
  189. package/dist/src/voice/stt/factory.js.map +1 -1
  190. package/dist/src/voice/stt/providers/alibaba-transcription.js +14 -8
  191. package/dist/src/voice/stt/providers/alibaba-transcription.js.map +1 -1
  192. package/dist/src/voice/stt/providers/index.d.ts +1 -0
  193. package/dist/src/voice/stt/providers/index.js +2 -1
  194. package/dist/src/voice/stt/providers/local-transcription.d.ts +2 -0
  195. package/dist/src/voice/stt/providers/local-transcription.js +51 -0
  196. package/dist/src/voice/stt/providers/local-transcription.js.map +1 -0
  197. package/dist/src/voice/stt/providers/openai-transcription.js +5 -3
  198. package/dist/src/voice/stt/providers/openai-transcription.js.map +1 -1
  199. package/dist/src/voice/stt/transcribe-core.js +5 -4
  200. package/dist/src/voice/stt/transcribe-core.js.map +1 -1
  201. package/dist/src/voice/stt/types.d.ts +4 -0
  202. package/dist/src/voice/stt/types.js +5 -4
  203. package/dist/src/voice/stt/types.js.map +1 -1
  204. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  205. package/dist/src/voice/tts/providers/edge-speech.js.map +1 -1
  206. package/dist/src/voice/tts/types.js +3 -3
  207. package/dist/src/voice/tts/types.js.map +1 -1
  208. package/package.json +4 -2
  209. package/dist/gateway/static/root/assets/Combination-HAlzriaz.js +0 -41
  210. package/dist/gateway/static/root/assets/agents-DzBXhZXO.js +0 -2
  211. package/dist/gateway/static/root/assets/app-management-settings-panel-Cuo7SbUP.js +0 -1
  212. package/dist/gateway/static/root/assets/apps-page-CKuKK5AU.js +0 -1
  213. package/dist/gateway/static/root/assets/automations-page-D-FF_WKV.js +0 -4
  214. package/dist/gateway/static/root/assets/browser-settings-page-BvKLdEQt.js +0 -8
  215. package/dist/gateway/static/root/assets/capability-presets-api-BU-pVZiZ.js +0 -1
  216. package/dist/gateway/static/root/assets/capability-presets-settings-panel-DgyeEwzh.js +0 -2
  217. package/dist/gateway/static/root/assets/channel-recipient-api-DuulnhIj.js +0 -1
  218. package/dist/gateway/static/root/assets/channels-settings-BbVsdD_I.js +0 -1
  219. package/dist/gateway/static/root/assets/channels-status-swr-B5lVrUsN.js +0 -1
  220. package/dist/gateway/static/root/assets/connectors-page-B8QqVy3I.js +0 -2
  221. package/dist/gateway/static/root/assets/dist-Mys7eFJ5.js +0 -1
  222. package/dist/gateway/static/root/assets/dreaming-settings-BgT5KZVe.js +0 -3
  223. package/dist/gateway/static/root/assets/extension-settings-page-JUtwIhbF.js +0 -1
  224. package/dist/gateway/static/root/assets/fetch-8QNN25Sh.js +0 -1
  225. package/dist/gateway/static/root/assets/gateway-config-api-CxicF50_.js +0 -1
  226. package/dist/gateway/static/root/assets/gateway-settings-Bz2I_EO5.js +0 -1
  227. package/dist/gateway/static/root/assets/gateway-startup-retry-5YBnS9Fj.js +0 -1
  228. package/dist/gateway/static/root/assets/goal-create-dialog-VcoyuZGN.js +0 -1
  229. package/dist/gateway/static/root/assets/goal-detail-page-Cilkap2G.js +0 -4
  230. package/dist/gateway/static/root/assets/goals-config-api-CwcHRdC0.js +0 -1
  231. package/dist/gateway/static/root/assets/goals-page-C6eoni4z.js +0 -2
  232. package/dist/gateway/static/root/assets/goals-settings-o4i-qAOS.js +0 -1
  233. package/dist/gateway/static/root/assets/heartbeat-settings-DQQkETX8.js +0 -1
  234. package/dist/gateway/static/root/assets/index-BKRqeRHm.js +0 -257
  235. package/dist/gateway/static/root/assets/index-CphxClbs.css +0 -1
  236. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-LT6qB-ua.js +0 -1
  237. package/dist/gateway/static/root/assets/locale-store-Ba72bFmP.js +0 -1
  238. package/dist/gateway/static/root/assets/logs-page-Dli2e3fS.js +0 -7
  239. package/dist/gateway/static/root/assets/markdown-editor-jD1LPiP-.js +0 -2
  240. package/dist/gateway/static/root/assets/messages-CzKxM6I4.js +0 -5
  241. package/dist/gateway/static/root/assets/models-hub-panel-DVn2Q1Ik.js +0 -2
  242. package/dist/gateway/static/root/assets/notes-workbench-BxZRHLWx.js +0 -2
  243. package/dist/gateway/static/root/assets/project-detail-page-Doz53xLn.js +0 -1
  244. package/dist/gateway/static/root/assets/projects-page-DoMtcRLg.js +0 -1
  245. package/dist/gateway/static/root/assets/remote-access-hub-BeHVEgrm.js +0 -1
  246. package/dist/gateway/static/root/assets/sessions-page-Bk4bQsBe.js +0 -1
  247. package/dist/gateway/static/root/assets/settings-advanced-gate-DdFyaRMm.js +0 -1
  248. package/dist/gateway/static/root/assets/setup-status-panel-DJ1_MLgX.js +0 -1
  249. package/dist/gateway/static/root/assets/share-preview-page-BQBV7YrV.js +0 -2
  250. package/dist/gateway/static/root/assets/shares-settings-0VuFLBeU.js +0 -1
  251. package/dist/gateway/static/root/assets/skill-reload-api-DO87Ckeo.js +0 -1
  252. package/dist/gateway/static/root/assets/skills-page-D3VdtxAn.js +0 -2
  253. package/dist/gateway/static/root/assets/use-channel-catalog-COXIfXcl.js +0 -1
  254. package/dist/gateway/static/root/assets/user-context-page-m9JVQ73F.js +0 -1
  255. package/dist/gateway/static/root/assets/user-profile-fields-editor-DtQiuY7E.js +0 -1
  256. package/dist/gateway/static/root/assets/voice-api-key-field-LoT3wgZ9.js +0 -1
  257. package/dist/gateway/static/root/assets/work-item-detail-page-DSTMz_mO.js +0 -1
  258. package/dist/gateway/static/root/assets/workflow-run-setup-panel-B35lJzvm.js +0 -3
  259. package/dist/gateway/static/root/assets/workflows-page-BfSm9oR8.js +0 -11
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-manager.js","names":[],"sources":["../../../../src/voice/local/model-manager.ts"],"sourcesContent":["import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nimport { createLogger } from '../../utils/logger.js';\nimport {\n LOCAL_VOICE_MODELS,\n getLocalVoiceModel,\n isLocalVoiceModelInstalled,\n resolveLocalVoiceModelDir,\n resolveLocalVoiceModelMarkerPath,\n} from './models.js';\nimport { getLocalVoiceRuntimeClient, type LocalVoiceRuntimeProgress } from './runtime-client.js';\n\nconst log = createLogger('LocalVoice:Models');\n\nexport type LocalVoiceModelState = 'not_installed' | 'downloading' | 'ready' | 'error';\n\nexport interface LocalVoiceModelStatus {\n id: string;\n name: string;\n description: string;\n approximateBytes: number;\n engine: string;\n languages: readonly string[];\n recommended?: boolean;\n state: LocalVoiceModelState;\n progress?: number;\n downloadedBytes?: number;\n totalBytes?: number;\n error?: string;\n}\n\nconst jobs = new Map<string, LocalVoiceModelStatus>();\n\nfunction progressFraction(progress: LocalVoiceRuntimeProgress): number | undefined {\n if (typeof progress.progress === 'number' && Number.isFinite(progress.progress)) {\n return progress.progress > 1 ? progress.progress / 100 : progress.progress;\n }\n if (typeof progress.loaded === 'number' && typeof progress.total === 'number' && progress.total > 0) {\n return progress.loaded / progress.total;\n }\n return undefined;\n}\n\nexport async function listLocalVoiceModelStatuses(): Promise<LocalVoiceModelStatus[]> {\n return Promise.all(\n LOCAL_VOICE_MODELS.map(async (model) => {\n const active = jobs.get(model.id);\n if (active) return { ...active };\n if (!isLocalVoiceModelInstalled(model.id)) {\n return {\n id: model.id,\n name: model.name,\n description: model.description,\n approximateBytes: model.approximateBytes,\n engine: model.engine,\n languages: model.languages,\n recommended: model.recommended,\n state: 'not_installed' as const,\n };\n }\n let installedAt: string | undefined;\n try {\n const marker = JSON.parse(await readFile(resolveLocalVoiceModelMarkerPath(model.id), 'utf8')) as { installedAt?: string };\n installedAt = marker.installedAt;\n } catch {\n // The marker's presence is authoritative; metadata is best-effort.\n }\n return {\n id: model.id,\n name: model.name,\n description: installedAt ? `${model.description} Installed ${installedAt}.` : model.description,\n approximateBytes: model.approximateBytes,\n engine: model.engine,\n languages: model.languages,\n recommended: model.recommended,\n state: 'ready' as const,\n };\n }),\n );\n}\n\nexport function startLocalVoiceModelInstall(modelId: string): LocalVoiceModelStatus {\n const model = getLocalVoiceModel(modelId);\n const existing = jobs.get(model.id);\n if (existing?.state === 'downloading') return { ...existing };\n const status: LocalVoiceModelStatus = {\n id: model.id,\n name: model.name,\n description: model.description,\n approximateBytes: model.approximateBytes,\n engine: model.engine,\n languages: model.languages,\n recommended: model.recommended,\n state: 'downloading',\n progress: 0,\n };\n jobs.set(model.id, status);\n void (async () => {\n const modelDir = resolveLocalVoiceModelDir(model.id);\n const stagingDir = `${modelDir}.download`;\n try {\n if (model.engine === 'transformers.js') {\n await rm(stagingDir, { recursive: true, force: true });\n }\n await mkdir(stagingDir, { recursive: true });\n await getLocalVoiceRuntimeClient().request(\n 'model.install',\n { modelId: model.id, cacheDir: stagingDir },\n {\n onProgress: (progress) => {\n const current = jobs.get(model.id);\n if (!current) return;\n current.progress = progressFraction(progress) ?? current.progress;\n current.downloadedBytes = progress.loaded;\n current.totalBytes = progress.total;\n },\n },\n );\n await writeFile(\n join(stagingDir, 'installed.json'),\n `${JSON.stringify({\n modelId: model.id,\n repository: model.repository,\n revision: model.revision,\n engine: model.engine,\n ...(model.dtype ? { dtype: model.dtype } : {}),\n installedAt: new Date().toISOString(),\n }, null, 2)}\\n`,\n { mode: 0o600 },\n );\n await rm(modelDir, { recursive: true, force: true });\n await rename(stagingDir, modelDir);\n jobs.delete(model.id);\n log.info({ modelId: model.id }, 'Local voice model installed');\n } catch (error) {\n // Keep verified/partial sherpa model files so a retry can continue with HTTP Range.\n if (model.engine === 'transformers.js') {\n await rm(stagingDir, { recursive: true, force: true }).catch(() => {});\n }\n const message = error instanceof Error ? error.message : String(error);\n jobs.set(model.id, { ...status, state: 'error', error: message });\n log.error({ err: error, modelId: model.id }, `Local voice model installation failed: ${message}`);\n }\n })();\n return { ...status };\n}\n\nexport async function removeLocalVoiceModel(modelId: string): Promise<void> {\n const model = getLocalVoiceModel(modelId);\n if (jobs.get(model.id)?.state === 'downloading') {\n throw new Error('Cannot remove a model while it is downloading');\n }\n try {\n await getLocalVoiceRuntimeClient().request('model.unload', { modelId: model.id }, { timeoutMs: 10_000 });\n } catch (error) {\n log.warn({ err: error, modelId: model.id }, 'Local voice runtime unload failed; removing model files');\n }\n await rm(resolveLocalVoiceModelDir(model.id), { recursive: true, force: true });\n jobs.delete(model.id);\n log.info({ modelId: model.id }, 'Local voice model removed');\n}\n"],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ export type LocalVoiceModelId = 'sensevoice-small' | 'tiny' | 'base' | 'small';
2
+ export type LocalVoiceEngine = 'sherpa-onnx' | 'transformers.js';
3
+ export interface LocalVoiceModelFile {
4
+ path: string;
5
+ bytes: number;
6
+ sha256: string;
7
+ }
8
+ export interface LocalVoiceModelDefinition {
9
+ id: LocalVoiceModelId;
10
+ name: string;
11
+ description: string;
12
+ engine: LocalVoiceEngine;
13
+ repository: string;
14
+ revision: string;
15
+ dtype?: 'q8';
16
+ files?: readonly LocalVoiceModelFile[];
17
+ languages: readonly string[];
18
+ recommended?: boolean;
19
+ approximateBytes: number;
20
+ }
21
+ export declare const DEFAULT_LOCAL_VOICE_MODEL_ID: LocalVoiceModelId;
22
+ export declare const LOCAL_VOICE_MODELS: readonly LocalVoiceModelDefinition[];
23
+ export declare function resolveLocalVoiceRootDir(): string;
24
+ export declare function resolveLocalVoiceModelDir(modelId: string): string;
25
+ export declare function resolveLocalVoiceModelMarkerPath(modelId: string): string;
26
+ export declare function getLocalVoiceModel(modelId: string | undefined): LocalVoiceModelDefinition;
27
+ export declare function isLocalVoiceModelInstalled(modelId: string): boolean;
28
+ export declare function hasInstalledLocalVoiceModel(): boolean;
@@ -0,0 +1,101 @@
1
+ import { resolveStateDir } from "../../config/paths-state.js";
2
+ import { init_paths } from "../../config/paths.js";
3
+ import { join } from "node:path";
4
+ import { existsSync } from "node:fs";
5
+ //#region src/voice/local/models.ts
6
+ init_paths();
7
+ const DEFAULT_LOCAL_VOICE_MODEL_ID = "sensevoice-small";
8
+ const LOCAL_VOICE_MODELS = [
9
+ {
10
+ id: "sensevoice-small",
11
+ name: "SenseVoice Small 中文",
12
+ description: "中文推荐;适合普通话、粤语和中英混说,支持标点与数字规整。",
13
+ engine: "sherpa-onnx",
14
+ repository: "csukuangfj/sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17",
15
+ revision: "2365baeacb507f821a0c8120fcee3d484dba7a07",
16
+ files: [
17
+ {
18
+ path: "model.int8.onnx",
19
+ bytes: 239233841,
20
+ sha256: "c71f0ce00bec95b07744e116345e33d8cbbe08cef896382cf907bf4b51a2cd51"
21
+ },
22
+ {
23
+ path: "tokens.txt",
24
+ bytes: 315894,
25
+ sha256: "f449eb28dc567533d7fa59be34e2abca8784f771850c78a47fb731a31429a1dc"
26
+ },
27
+ {
28
+ path: "LICENSE",
29
+ bytes: 71,
30
+ sha256: "221c6df10b0931a5629adad671ea48fb7747e034c414b6d2bfa275bc3dd4ea17"
31
+ }
32
+ ],
33
+ languages: [
34
+ "zh",
35
+ "yue",
36
+ "en",
37
+ "ja",
38
+ "ko"
39
+ ],
40
+ recommended: true,
41
+ approximateBytes: 239549806
42
+ },
43
+ {
44
+ id: "tiny",
45
+ name: "Whisper Tiny",
46
+ description: "Fastest and smallest; best for short commands.",
47
+ engine: "transformers.js",
48
+ repository: "onnx-community/whisper-tiny",
49
+ revision: "ff4177021cc41f7db950912b73ea4fdf7d01d8e7",
50
+ dtype: "q8",
51
+ languages: ["multilingual"],
52
+ approximateBytes: 45 * 1024 * 1024
53
+ },
54
+ {
55
+ id: "base",
56
+ name: "Whisper Base",
57
+ description: "Recommended balance of accuracy, speed, and disk use.",
58
+ engine: "transformers.js",
59
+ repository: "onnx-community/whisper-base",
60
+ revision: "1846881b6b3a3024392c1eea3ad983695bc23925",
61
+ dtype: "q8",
62
+ languages: ["multilingual"],
63
+ approximateBytes: 80 * 1024 * 1024
64
+ },
65
+ {
66
+ id: "small",
67
+ name: "Whisper Small",
68
+ description: "Higher accuracy with more memory and disk use.",
69
+ engine: "transformers.js",
70
+ repository: "onnx-community/whisper-small",
71
+ revision: "36050c46d777d46dc4b5f43f6d90574fc38f8732",
72
+ dtype: "q8",
73
+ languages: ["multilingual"],
74
+ approximateBytes: 245 * 1024 * 1024
75
+ }
76
+ ];
77
+ function resolveLocalVoiceRootDir() {
78
+ return process.env.XOPC_VOICE_MODEL_DIR?.trim() || join(resolveStateDir(), "voice");
79
+ }
80
+ function resolveLocalVoiceModelDir(modelId) {
81
+ return join(resolveLocalVoiceRootDir(), "models", modelId);
82
+ }
83
+ function resolveLocalVoiceModelMarkerPath(modelId) {
84
+ return join(resolveLocalVoiceModelDir(modelId), "installed.json");
85
+ }
86
+ function getLocalVoiceModel(modelId) {
87
+ const id = modelId?.trim() || "sensevoice-small";
88
+ const model = LOCAL_VOICE_MODELS.find((entry) => entry.id === id);
89
+ if (!model) throw new Error(`Unknown local voice model: ${id}`);
90
+ return model;
91
+ }
92
+ function isLocalVoiceModelInstalled(modelId) {
93
+ return existsSync(resolveLocalVoiceModelMarkerPath(modelId));
94
+ }
95
+ function hasInstalledLocalVoiceModel() {
96
+ return LOCAL_VOICE_MODELS.some((model) => isLocalVoiceModelInstalled(model.id));
97
+ }
98
+ //#endregion
99
+ export { DEFAULT_LOCAL_VOICE_MODEL_ID, LOCAL_VOICE_MODELS, getLocalVoiceModel, hasInstalledLocalVoiceModel, isLocalVoiceModelInstalled, resolveLocalVoiceModelDir, resolveLocalVoiceModelMarkerPath, resolveLocalVoiceRootDir };
100
+
101
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","names":[],"sources":["../../../../src/voice/local/models.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport { resolveStateDir } from '../../config/paths.js';\n\nexport type LocalVoiceModelId = 'sensevoice-small' | 'tiny' | 'base' | 'small';\n\nexport type LocalVoiceEngine = 'sherpa-onnx' | 'transformers.js';\n\nexport interface LocalVoiceModelFile {\n path: string;\n bytes: number;\n sha256: string;\n}\n\nexport interface LocalVoiceModelDefinition {\n id: LocalVoiceModelId;\n name: string;\n description: string;\n engine: LocalVoiceEngine;\n repository: string;\n revision: string;\n dtype?: 'q8';\n files?: readonly LocalVoiceModelFile[];\n languages: readonly string[];\n recommended?: boolean;\n approximateBytes: number;\n}\n\nexport const DEFAULT_LOCAL_VOICE_MODEL_ID: LocalVoiceModelId = 'sensevoice-small';\n\nexport const LOCAL_VOICE_MODELS: readonly LocalVoiceModelDefinition[] = [\n {\n id: 'sensevoice-small',\n name: 'SenseVoice Small 中文',\n description: '中文推荐;适合普通话、粤语和中英混说,支持标点与数字规整。',\n engine: 'sherpa-onnx',\n repository: 'csukuangfj/sherpa-onnx-sense-voice-zh-en-ja-ko-yue-2024-07-17',\n revision: '2365baeacb507f821a0c8120fcee3d484dba7a07',\n files: [\n {\n path: 'model.int8.onnx',\n bytes: 239_233_841,\n sha256: 'c71f0ce00bec95b07744e116345e33d8cbbe08cef896382cf907bf4b51a2cd51',\n },\n {\n path: 'tokens.txt',\n bytes: 315_894,\n sha256: 'f449eb28dc567533d7fa59be34e2abca8784f771850c78a47fb731a31429a1dc',\n },\n {\n path: 'LICENSE',\n bytes: 71,\n sha256: '221c6df10b0931a5629adad671ea48fb7747e034c414b6d2bfa275bc3dd4ea17',\n },\n ],\n languages: ['zh', 'yue', 'en', 'ja', 'ko'],\n recommended: true,\n approximateBytes: 239_549_806,\n },\n {\n id: 'tiny',\n name: 'Whisper Tiny',\n description: 'Fastest and smallest; best for short commands.',\n engine: 'transformers.js',\n repository: 'onnx-community/whisper-tiny',\n revision: 'ff4177021cc41f7db950912b73ea4fdf7d01d8e7',\n dtype: 'q8',\n languages: ['multilingual'],\n approximateBytes: 45 * 1024 * 1024,\n },\n {\n id: 'base',\n name: 'Whisper Base',\n description: 'Recommended balance of accuracy, speed, and disk use.',\n engine: 'transformers.js',\n repository: 'onnx-community/whisper-base',\n revision: '1846881b6b3a3024392c1eea3ad983695bc23925',\n dtype: 'q8',\n languages: ['multilingual'],\n approximateBytes: 80 * 1024 * 1024,\n },\n {\n id: 'small',\n name: 'Whisper Small',\n description: 'Higher accuracy with more memory and disk use.',\n engine: 'transformers.js',\n repository: 'onnx-community/whisper-small',\n revision: '36050c46d777d46dc4b5f43f6d90574fc38f8732',\n dtype: 'q8',\n languages: ['multilingual'],\n approximateBytes: 245 * 1024 * 1024,\n },\n] as const;\n\nexport function resolveLocalVoiceRootDir(): string {\n return process.env.XOPC_VOICE_MODEL_DIR?.trim() || join(resolveStateDir(), 'voice');\n}\n\nexport function resolveLocalVoiceModelDir(modelId: string): string {\n return join(resolveLocalVoiceRootDir(), 'models', modelId);\n}\n\nexport function resolveLocalVoiceModelMarkerPath(modelId: string): string {\n return join(resolveLocalVoiceModelDir(modelId), 'installed.json');\n}\n\nexport function getLocalVoiceModel(modelId: string | undefined): LocalVoiceModelDefinition {\n const id = modelId?.trim() || DEFAULT_LOCAL_VOICE_MODEL_ID;\n const model = LOCAL_VOICE_MODELS.find((entry) => entry.id === id);\n if (!model) {\n throw new Error(`Unknown local voice model: ${id}`);\n }\n return model;\n}\n\nexport function isLocalVoiceModelInstalled(modelId: string): boolean {\n return existsSync(resolveLocalVoiceModelMarkerPath(modelId));\n}\n\nexport function hasInstalledLocalVoiceModel(): boolean {\n return LOCAL_VOICE_MODELS.some((model) => isLocalVoiceModelInstalled(model.id));\n}\n"],"mappings":";;;;;YAGwD;AA0BxD,MAAa,+BAAkD;AAE/D,MAAa,qBAA2D;CACtE;EACE,IAAI;EACJ,MAAM;EACN,aAAa;EACb,QAAQ;EACR,YAAY;EACZ,UAAU;EACV,OAAO;GACL;IACE,MAAM;IACN,OAAO;IACP,QAAQ;IACT;GACD;IACE,MAAM;IACN,OAAO;IACP,QAAQ;IACT;GACD;IACE,MAAM;IACN,OAAO;IACP,QAAQ;IACT;GACF;EACD,WAAW;GAAC;GAAM;GAAO;GAAM;GAAM;GAAK;EAC1C,aAAa;EACb,kBAAkB;EACnB;CACD;EACE,IAAI;EACJ,MAAM;EACN,aAAa;EACb,QAAQ;EACR,YAAY;EACZ,UAAU;EACV,OAAO;EACP,WAAW,CAAC,eAAe;EAC3B,kBAAkB,KAAK,OAAO;EAC/B;CACD;EACE,IAAI;EACJ,MAAM;EACN,aAAa;EACb,QAAQ;EACR,YAAY;EACZ,UAAU;EACV,OAAO;EACP,WAAW,CAAC,eAAe;EAC3B,kBAAkB,KAAK,OAAO;EAC/B;CACD;EACE,IAAI;EACJ,MAAM;EACN,aAAa;EACb,QAAQ;EACR,YAAY;EACZ,UAAU;EACV,OAAO;EACP,WAAW,CAAC,eAAe;EAC3B,kBAAkB,MAAM,OAAO;EAChC;CACF;AAED,SAAgB,2BAAmC;AACjD,QAAO,QAAQ,IAAI,sBAAsB,MAAM,IAAI,KAAK,iBAAiB,EAAE,QAAQ;;AAGrF,SAAgB,0BAA0B,SAAyB;AACjE,QAAO,KAAK,0BAA0B,EAAE,UAAU,QAAQ;;AAG5D,SAAgB,iCAAiC,SAAyB;AACxE,QAAO,KAAK,0BAA0B,QAAQ,EAAE,iBAAiB;;AAGnE,SAAgB,mBAAmB,SAAwD;CACzF,MAAM,KAAK,SAAS,MAAM,IAAA;CAC1B,MAAM,QAAQ,mBAAmB,MAAM,UAAU,MAAM,OAAO,GAAG;AACjE,KAAI,CAAC,MACH,OAAM,IAAI,MAAM,8BAA8B,KAAK;AAErD,QAAO;;AAGT,SAAgB,2BAA2B,SAA0B;AACnE,QAAO,WAAW,iCAAiC,QAAQ,CAAC;;AAG9D,SAAgB,8BAAuC;AACrD,QAAO,mBAAmB,MAAM,UAAU,2BAA2B,MAAM,GAAG,CAAC"}
@@ -0,0 +1,26 @@
1
+ export interface LocalVoiceRuntimeProgress {
2
+ status?: string;
3
+ file?: string;
4
+ progress?: number;
5
+ loaded?: number;
6
+ total?: number;
7
+ }
8
+ export declare class LocalVoiceRuntimeClient {
9
+ private child;
10
+ private nextId;
11
+ private pending;
12
+ request<T>(method: string, params?: Record<string, unknown>, options?: {
13
+ signal?: AbortSignal;
14
+ timeoutMs?: number;
15
+ /** Health/status probes must never terminate an active model download on timeout. */
16
+ stopOnTimeout?: boolean;
17
+ onProgress?: (progress: LocalVoiceRuntimeProgress) => void;
18
+ }): Promise<T>;
19
+ stop(): void;
20
+ private ensureStarted;
21
+ private handleLine;
22
+ private rejectAll;
23
+ private deletePending;
24
+ }
25
+ export declare function getLocalVoiceRuntimeClient(): LocalVoiceRuntimeClient;
26
+ export declare function resetLocalVoiceRuntimeForTests(): void;
@@ -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":";;;;;;;;aAKqD;AAGrD,MAAM,MAAM,aAAa,qBAAqB;AAC9C,MAAM,6BAA6B,KAAK;AAmBxC,SAAS,uBAA0D;CACjE,MAAM,aAAa,QAAQ,IAAI,0BAA0B,MAAM;AAC/D,KAAI,WAAY,QAAO;EAAE,OAAO;EAAY,MAAM,CAAC,WAAW;EAAE;CAEhE,MAAM,UAAU,cAAc,IAAI,IAAI,uBAAuB,OAAO,KAAK,IAAI,CAAC;AAC9E,KAAI,WAAW,QAAQ,CAAE,QAAO;EAAE,OAAO;EAAS,MAAM,CAAC,QAAQ;EAAE;CAEnE,MAAM,UAAU,cAAc,IAAI,IAAI,uBAAuB,OAAO,KAAK,IAAI,CAAC;AAC9E,KAAI,WAAW,QAAQ,CAAE,QAAO;EAAE,OAAO;EAAS,MAAM;GAAC;GAAY;GAAO;GAAQ;EAAE;AACtF,OAAM,IAAI,MAAM,+CAA+C;;AAGjE,IAAa,0BAAb,MAAqC;CACnC,QAAuD;CACvD,SAAiB;CACjB,0BAAkB,IAAI,KAA6B;CAEnD,MAAM,QACJ,QACA,SAAkC,EAAE,EACpC,UAMI,EAAE,EACM;AACZ,UAAQ,QAAQ,gBAAgB;EAChC,MAAM,QAAQ,KAAK,eAAe;EAClC,MAAM,KAAK,KAAK;AAChB,SAAO,IAAI,SAAY,SAAS,WAAW;GACzC,MAAM,UAAU,iBAAiB;AAC/B,SAAK,cAAc,GAAG;AACtB,2BAAO,IAAI,MAAM,0CAA0C,SAAS,CAAC;AACrE,QAAI,QAAQ,kBAAkB,MAAO,MAAK,MAAM;MAC/C,QAAQ,aAAa,2BAA2B;AACnD,QAAK,QAAQ,IAAI,IAAI;IACnB,UAAU,UAAU,QAAQ,MAAW;IACvC;IACA;IACA,QAAQ,QAAQ;IAChB,YAAY,QAAQ;IACrB,CAAC;GACF,MAAM,cAAc;IAClB,MAAM,UAAU,KAAK,QAAQ,IAAI,GAAG;AACpC,QAAI,CAAC,QAAS;AACd,SAAK,cAAc,GAAG;AACtB,YAAQ,uBAAO,IAAI,MAAM,oCAAoC,CAAC;AAC9D,SAAK,MAAM;;GAEb,MAAM,UAAU,KAAK,QAAQ,IAAI,GAAG;AACpC,OAAI,QAAS,SAAQ,QAAQ;AAC7B,WAAQ,QAAQ,iBAAiB,SAAS,OAAO,EAAE,MAAM,MAAM,CAAC;AAChE,SAAM,MAAM,MAAM,GAAG,KAAK,UAAU;IAAE;IAAI;IAAQ;IAAQ,CAAC,CAAC,MAAM,UAAU;AAC1E,QAAI,CAAC,MAAO;AACZ,SAAK,cAAc,GAAG;AACtB,WAAO,MAAM;KACb;IACF;;CAGJ,OAAa;EACX,MAAM,QAAQ,KAAK;AACnB,OAAK,QAAQ;AACb,MAAI,SAAS,CAAC,MAAM,OAAQ,OAAM,KAAK,UAAU;AACjD,OAAK,0BAAU,IAAI,MAAM,8BAA8B,CAAC;;CAG1D,gBAAwD;AACtD,MAAI,KAAK,SAAS,CAAC,KAAK,MAAM,OAAQ,QAAO,KAAK;EAClD,MAAM,UAAU,sBAAsB;EACtC,MAAM,QAAQ,MAAM,QAAQ,UAAU,QAAQ,MAAM;GAClD,KAAK;IACH,GAAG,QAAQ;IACX,sBAAsB;IACtB,sBAAsB,0BAA0B;IACjD;GACD,OAAO;IAAC;IAAQ;IAAQ;IAAO;GAC/B,aAAa;GACd,CAAC;AACF,OAAK,QAAQ;AACb,kBAAgB,EAAE,OAAO,MAAM,QAAQ,CAAC,CAAC,GAAG,SAAS,SAAS,KAAK,WAAW,KAAK,CAAC;AACpF,QAAM,OAAO,GAAG,SAAS,UAAkB;GACzC,MAAM,UAAU,MAAM,UAAU,CAAC,MAAM;AACvC,OAAI,QAAS,KAAI,MAAM,EAAE,SAAS,EAAE,6BAA6B;IACjE;AACF,QAAM,KAAK,UAAU,UAAU;AAC7B,OAAI,KAAK,UAAU,MAAO,MAAK,QAAQ;AACvC,QAAK,UAAU,MAAM;IACrB;AACF,QAAM,KAAK,SAAS,MAAM,WAAW;AACnC,OAAI,KAAK,UAAU,MAAO,MAAK,QAAQ;AACvC,OAAI,KAAK,QAAQ,OAAO,EACtB,MAAK,0BAAU,IAAI,MAAM,+BAA+B,QAAQ,UAAU,UAAU,GAAG,CAAC;IAE1F;AACF,SAAO;;CAGT,WAAmB,MAAoB;EACrC,IAAI;AAOJ,MAAI;AACF,aAAU,KAAK,MAAM,KAAK;UACpB;AACN,OAAI,KAAK,EAAE,aAAa,KAAK,MAAM,GAAG,IAAI,EAAE,EAAE,6CAA6C;AAC3F;;AAEF,MAAI,OAAO,QAAQ,OAAO,SAAU;EACpC,MAAM,UAAU,KAAK,QAAQ,IAAI,QAAQ,GAAG;AAC5C,MAAI,CAAC,QAAS;AACd,MAAI,QAAQ,UAAU,YAAY;AAChC,WAAQ,aAAc,QAAQ,QAAQ,EAAE,CAA+B;AACvE;;AAEF,OAAK,cAAc,QAAQ,GAAG;AAC9B,MAAI,QAAQ,OAAO;GACjB,MAAM,SAAS,OAAO,QAAQ,UAAU,WAAW,EAAE,SAAS,QAAQ,OAAO,GAAG,QAAQ;GACxF,MAAM,SAAS,CAAC,OAAO,MAAM,OAAO,MAAM,CAAC,OAAO,QAAQ,CAAC,KAAK,KAAK;GACrE,MAAM,wBAAQ,IAAI,MAAM,GAAG,OAAO,WAAW,+BAA+B,SAAS,KAAK,OAAO,KAAK,KAAK;AAC3G,OAAI,OAAO,KAAM,QAAO,OAAO,OAAO,EAAE,MAAM,OAAO,MAAM,CAAC;AAC5D,WAAQ,OAAO,MAAM;QAChB,SAAQ,QAAQ,QAAQ,OAAO;;CAGxC,UAAkB,OAAoB;AACpC,OAAK,MAAM,WAAW,KAAK,QAAQ,QAAQ,EAAE;AAC3C,gBAAa,QAAQ,QAAQ;AAC7B,OAAI,QAAQ,UAAU,QAAQ,MAC5B,SAAQ,OAAO,oBAAoB,SAAS,QAAQ,MAAM;AAE5D,WAAQ,OAAO,MAAM;;AAEvB,OAAK,QAAQ,OAAO;;CAGtB,cAAsB,IAAkB;EACtC,MAAM,UAAU,KAAK,QAAQ,IAAI,GAAG;AACpC,MAAI,CAAC,QAAS;AACd,eAAa,QAAQ,QAAQ;AAC7B,MAAI,QAAQ,UAAU,QAAQ,MAC5B,SAAQ,OAAO,oBAAoB,SAAS,QAAQ,MAAM;AAE5D,OAAK,QAAQ,OAAO,GAAG;;;AAI3B,IAAI;AAEJ,SAAgB,6BAAsD;AACpE,mBAAkB,IAAI,yBAAyB;AAC/C,QAAO;;AAGT,SAAgB,iCAAuC;AACrD,gBAAe,MAAM;AACrB,iBAAgB,KAAA"}
@@ -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 {};