@desktalk/core 0.1.0-alpha.1

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 (281) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cli/index.d.ts +3 -0
  3. package/dist/cli/index.d.ts.map +1 -0
  4. package/dist/cli/index.js +82 -0
  5. package/dist/cli/index.js.map +1 -0
  6. package/dist/frontend/assets/frontend-B3QNYf3p.js +413 -0
  7. package/dist/frontend/assets/frontend-B3QNYf3p.js.map +1 -0
  8. package/dist/frontend/assets/frontend-B4aeXn9d.js +416 -0
  9. package/dist/frontend/assets/frontend-B4aeXn9d.js.map +1 -0
  10. package/dist/frontend/assets/frontend-BwyRSlHp.js +6513 -0
  11. package/dist/frontend/assets/frontend-BwyRSlHp.js.map +1 -0
  12. package/dist/frontend/assets/frontend-Dix2OWTT.js +229 -0
  13. package/dist/frontend/assets/frontend-Dix2OWTT.js.map +1 -0
  14. package/dist/frontend/assets/frontend-Dx41dEM9.js +407 -0
  15. package/dist/frontend/assets/frontend-Dx41dEM9.js.map +1 -0
  16. package/dist/frontend/assets/frontend-WpQng8Mt.js +1991 -0
  17. package/dist/frontend/assets/frontend-WpQng8Mt.js.map +1 -0
  18. package/dist/frontend/assets/frontend-rTwBdJbn.js +2123 -0
  19. package/dist/frontend/assets/frontend-rTwBdJbn.js.map +1 -0
  20. package/dist/frontend/assets/highlighted-body-TPN3WLV5-DD4wpkf4.js +2 -0
  21. package/dist/frontend/assets/highlighted-body-TPN3WLV5-DD4wpkf4.js.map +1 -0
  22. package/dist/frontend/assets/index-C5-XUOS7.js +1863 -0
  23. package/dist/frontend/assets/index-C5-XUOS7.js.map +1 -0
  24. package/dist/frontend/assets/index-C_e3_6yE.css +1 -0
  25. package/dist/frontend/index.html +22 -0
  26. package/dist/frontend/pcm-capture-processor.js +65 -0
  27. package/dist/i18n/manifest.json +34 -0
  28. package/dist/i18n/zh-CN.json +7 -0
  29. package/dist/index.d.ts +6 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +6 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/server/admin-routes.d.ts +14 -0
  34. package/dist/server/admin-routes.d.ts.map +1 -0
  35. package/dist/server/admin-routes.js +118 -0
  36. package/dist/server/admin-routes.js.map +1 -0
  37. package/dist/server/api-routes.d.ts +8 -0
  38. package/dist/server/api-routes.d.ts.map +1 -0
  39. package/dist/server/api-routes.js +203 -0
  40. package/dist/server/api-routes.js.map +1 -0
  41. package/dist/server/auth-routes.d.ts +19 -0
  42. package/dist/server/auth-routes.d.ts.map +1 -0
  43. package/dist/server/auth-routes.js +155 -0
  44. package/dist/server/auth-routes.js.map +1 -0
  45. package/dist/server/dtfs-routes.d.ts +3 -0
  46. package/dist/server/dtfs-routes.d.ts.map +1 -0
  47. package/dist/server/dtfs-routes.js +183 -0
  48. package/dist/server/dtfs-routes.js.map +1 -0
  49. package/dist/server/index.d.ts +15 -0
  50. package/dist/server/index.d.ts.map +1 -0
  51. package/dist/server/index.js +158 -0
  52. package/dist/server/index.js.map +1 -0
  53. package/dist/server/monaco-routes.d.ts +3 -0
  54. package/dist/server/monaco-routes.d.ts.map +1 -0
  55. package/dist/server/monaco-routes.js +45 -0
  56. package/dist/server/monaco-routes.js.map +1 -0
  57. package/dist/server/voice-routes.d.ts +7 -0
  58. package/dist/server/voice-routes.d.ts.map +1 -0
  59. package/dist/server/voice-routes.js +142 -0
  60. package/dist/server/voice-routes.js.map +1 -0
  61. package/dist/server/ws-routes.d.ts +29 -0
  62. package/dist/server/ws-routes.d.ts.map +1 -0
  63. package/dist/server/ws-routes.js +334 -0
  64. package/dist/server/ws-routes.js.map +1 -0
  65. package/dist/services/ai/action-tool.d.ts +9 -0
  66. package/dist/services/ai/action-tool.d.ts.map +1 -0
  67. package/dist/services/ai/action-tool.js +51 -0
  68. package/dist/services/ai/action-tool.js.map +1 -0
  69. package/dist/services/ai/app-tools.d.ts +15 -0
  70. package/dist/services/ai/app-tools.d.ts.map +1 -0
  71. package/dist/services/ai/app-tools.js +119 -0
  72. package/dist/services/ai/app-tools.js.map +1 -0
  73. package/dist/services/ai/chat-service.d.ts +27 -0
  74. package/dist/services/ai/chat-service.d.ts.map +1 -0
  75. package/dist/services/ai/chat-service.js +213 -0
  76. package/dist/services/ai/chat-service.js.map +1 -0
  77. package/dist/services/ai/create-liveapp-tool.d.ts +15 -0
  78. package/dist/services/ai/create-liveapp-tool.d.ts.map +1 -0
  79. package/dist/services/ai/create-liveapp-tool.js +142 -0
  80. package/dist/services/ai/create-liveapp-tool.js.map +1 -0
  81. package/dist/services/ai/desktop-tool.d.ts +27 -0
  82. package/dist/services/ai/desktop-tool.d.ts.map +1 -0
  83. package/dist/services/ai/desktop-tool.js +106 -0
  84. package/dist/services/ai/desktop-tool.js.map +1 -0
  85. package/dist/services/ai/edit-history.d.ts +16 -0
  86. package/dist/services/ai/edit-history.d.ts.map +1 -0
  87. package/dist/services/ai/edit-history.js +137 -0
  88. package/dist/services/ai/edit-history.js.map +1 -0
  89. package/dist/services/ai/edit-tool.d.ts +9 -0
  90. package/dist/services/ai/edit-tool.d.ts.map +1 -0
  91. package/dist/services/ai/edit-tool.js +113 -0
  92. package/dist/services/ai/edit-tool.js.map +1 -0
  93. package/dist/services/ai/generate-html-tool.d.ts +15 -0
  94. package/dist/services/ai/generate-html-tool.d.ts.map +1 -0
  95. package/dist/services/ai/generate-html-tool.js +140 -0
  96. package/dist/services/ai/generate-html-tool.js.map +1 -0
  97. package/dist/services/ai/generate-icon-tool.d.ts +10 -0
  98. package/dist/services/ai/generate-icon-tool.d.ts.map +1 -0
  99. package/dist/services/ai/generate-icon-tool.js +58 -0
  100. package/dist/services/ai/generate-icon-tool.js.map +1 -0
  101. package/dist/services/ai/html-bridge-script.d.ts +2 -0
  102. package/dist/services/ai/html-bridge-script.d.ts.map +1 -0
  103. package/dist/services/ai/html-bridge-script.js +2 -0
  104. package/dist/services/ai/html-bridge-script.js.map +1 -0
  105. package/dist/services/ai/html-guidelines-tool.d.ts +3 -0
  106. package/dist/services/ai/html-guidelines-tool.d.ts.map +1 -0
  107. package/dist/services/ai/html-guidelines-tool.js +157 -0
  108. package/dist/services/ai/html-guidelines-tool.js.map +1 -0
  109. package/dist/services/ai/html-stream-coordinator.d.ts +92 -0
  110. package/dist/services/ai/html-stream-coordinator.d.ts.map +1 -0
  111. package/dist/services/ai/html-stream-coordinator.js +314 -0
  112. package/dist/services/ai/html-stream-coordinator.js.map +1 -0
  113. package/dist/services/ai/html-theme-link.d.ts +9 -0
  114. package/dist/services/ai/html-theme-link.d.ts.map +1 -0
  115. package/dist/services/ai/html-theme-link.js +12 -0
  116. package/dist/services/ai/html-theme-link.js.map +1 -0
  117. package/dist/services/ai/html-ui-script.d.ts +9 -0
  118. package/dist/services/ai/html-ui-script.d.ts.map +1 -0
  119. package/dist/services/ai/html-ui-script.js +9 -0
  120. package/dist/services/ai/html-ui-script.js.map +1 -0
  121. package/dist/services/ai/image-generation-service.d.ts +26 -0
  122. package/dist/services/ai/image-generation-service.d.ts.map +1 -0
  123. package/dist/services/ai/image-generation-service.js +205 -0
  124. package/dist/services/ai/image-generation-service.js.map +1 -0
  125. package/dist/services/ai/manual-pages/desktop-actions.md +36 -0
  126. package/dist/services/ai/manual-pages/desktop-windows.md +24 -0
  127. package/dist/services/ai/manual-pages/dt-badge.md +36 -0
  128. package/dist/services/ai/manual-pages/dt-button.md +38 -0
  129. package/dist/services/ai/manual-pages/dt-card.md +22 -0
  130. package/dist/services/ai/manual-pages/dt-chart.md +261 -0
  131. package/dist/services/ai/manual-pages/dt-divider.md +25 -0
  132. package/dist/services/ai/manual-pages/dt-grid.md +29 -0
  133. package/dist/services/ai/manual-pages/dt-list-view.md +96 -0
  134. package/dist/services/ai/manual-pages/dt-markdown-editor.md +90 -0
  135. package/dist/services/ai/manual-pages/dt-markdown.md +86 -0
  136. package/dist/services/ai/manual-pages/dt-select.md +21 -0
  137. package/dist/services/ai/manual-pages/dt-stack.md +31 -0
  138. package/dist/services/ai/manual-pages/dt-stat.md +43 -0
  139. package/dist/services/ai/manual-pages/dt-table-view.md +120 -0
  140. package/dist/services/ai/manual-pages/dt-tooltip.md +18 -0
  141. package/dist/services/ai/manual-pages/editing-preview.md +25 -0
  142. package/dist/services/ai/manual-pages/html-actions.md +74 -0
  143. package/dist/services/ai/manual-pages/html-bridge.md +187 -0
  144. package/dist/services/ai/manual-pages/html-components.md +66 -0
  145. package/dist/services/ai/manual-pages/html-examples.md +185 -0
  146. package/dist/services/ai/manual-pages/html-layouts.md +128 -0
  147. package/dist/services/ai/manual-pages/html-storage.md +153 -0
  148. package/dist/services/ai/manual-pages/html-tokens.md +26 -0
  149. package/dist/services/ai/manual-pages/index.d.ts +10 -0
  150. package/dist/services/ai/manual-pages/index.d.ts.map +1 -0
  151. package/dist/services/ai/manual-pages/index.js +186 -0
  152. package/dist/services/ai/manual-pages/index.js.map +1 -0
  153. package/dist/services/ai/manual-tool.d.ts +3 -0
  154. package/dist/services/ai/manual-tool.d.ts.map +1 -0
  155. package/dist/services/ai/manual-tool.js +104 -0
  156. package/dist/services/ai/manual-tool.js.map +1 -0
  157. package/dist/services/ai/pi-session-service.d.ts +101 -0
  158. package/dist/services/ai/pi-session-service.d.ts.map +1 -0
  159. package/dist/services/ai/pi-session-service.js +697 -0
  160. package/dist/services/ai/pi-session-service.js.map +1 -0
  161. package/dist/services/ai/providers.d.ts +21 -0
  162. package/dist/services/ai/providers.d.ts.map +1 -0
  163. package/dist/services/ai/providers.js +93 -0
  164. package/dist/services/ai/providers.js.map +1 -0
  165. package/dist/services/ai/redo-edit-tool.d.ts +9 -0
  166. package/dist/services/ai/redo-edit-tool.d.ts.map +1 -0
  167. package/dist/services/ai/redo-edit-tool.js +44 -0
  168. package/dist/services/ai/redo-edit-tool.js.map +1 -0
  169. package/dist/services/ai/system-prompt.d.ts +7 -0
  170. package/dist/services/ai/system-prompt.d.ts.map +1 -0
  171. package/dist/services/ai/system-prompt.js +72 -0
  172. package/dist/services/ai/system-prompt.js.map +1 -0
  173. package/dist/services/ai/undo-edit-tool.d.ts +9 -0
  174. package/dist/services/ai/undo-edit-tool.d.ts.map +1 -0
  175. package/dist/services/ai/undo-edit-tool.js +44 -0
  176. package/dist/services/ai/undo-edit-tool.js.map +1 -0
  177. package/dist/services/ai/window-tools.d.ts +27 -0
  178. package/dist/services/ai/window-tools.d.ts.map +1 -0
  179. package/dist/services/ai/window-tools.js +155 -0
  180. package/dist/services/ai/window-tools.js.map +1 -0
  181. package/dist/services/backend-host.d.ts +10 -0
  182. package/dist/services/backend-host.d.ts.map +1 -0
  183. package/dist/services/backend-host.js +117 -0
  184. package/dist/services/backend-host.js.map +1 -0
  185. package/dist/services/backend-ipc.d.ts +60 -0
  186. package/dist/services/backend-ipc.d.ts.map +1 -0
  187. package/dist/services/backend-ipc.js +2 -0
  188. package/dist/services/backend-ipc.js.map +1 -0
  189. package/dist/services/backend-process-manager.d.ts +60 -0
  190. package/dist/services/backend-process-manager.d.ts.map +1 -0
  191. package/dist/services/backend-process-manager.js +203 -0
  192. package/dist/services/backend-process-manager.js.map +1 -0
  193. package/dist/services/filesystem.d.ts +8 -0
  194. package/dist/services/filesystem.d.ts.map +1 -0
  195. package/dist/services/filesystem.js +94 -0
  196. package/dist/services/filesystem.js.map +1 -0
  197. package/dist/services/i18n.d.ts +28 -0
  198. package/dist/services/i18n.d.ts.map +1 -0
  199. package/dist/services/i18n.js +76 -0
  200. package/dist/services/i18n.js.map +1 -0
  201. package/dist/services/liveapp-icon.d.ts +9 -0
  202. package/dist/services/liveapp-icon.d.ts.map +1 -0
  203. package/dist/services/liveapp-icon.js +28 -0
  204. package/dist/services/liveapp-icon.js.map +1 -0
  205. package/dist/services/liveapps.d.ts +12 -0
  206. package/dist/services/liveapps.d.ts.map +1 -0
  207. package/dist/services/liveapps.js +84 -0
  208. package/dist/services/liveapps.js.map +1 -0
  209. package/dist/services/logger.d.ts +34 -0
  210. package/dist/services/logger.d.ts.map +1 -0
  211. package/dist/services/logger.js +74 -0
  212. package/dist/services/logger.js.map +1 -0
  213. package/dist/services/messaging.d.ts +14 -0
  214. package/dist/services/messaging.d.ts.map +1 -0
  215. package/dist/services/messaging.js +41 -0
  216. package/dist/services/messaging.js.map +1 -0
  217. package/dist/services/miniapp-icon.d.ts +9 -0
  218. package/dist/services/miniapp-icon.d.ts.map +1 -0
  219. package/dist/services/miniapp-icon.js +25 -0
  220. package/dist/services/miniapp-icon.js.map +1 -0
  221. package/dist/services/miniapp-registry.d.ts +73 -0
  222. package/dist/services/miniapp-registry.d.ts.map +1 -0
  223. package/dist/services/miniapp-registry.js +144 -0
  224. package/dist/services/miniapp-registry.js.map +1 -0
  225. package/dist/services/onboarding-config.d.ts +37 -0
  226. package/dist/services/onboarding-config.d.ts.map +1 -0
  227. package/dist/services/onboarding-config.js +76 -0
  228. package/dist/services/onboarding-config.js.map +1 -0
  229. package/dist/services/preferences.d.ts +10 -0
  230. package/dist/services/preferences.d.ts.map +1 -0
  231. package/dist/services/preferences.js +48 -0
  232. package/dist/services/preferences.js.map +1 -0
  233. package/dist/services/proxy-dispatcher.d.ts +18 -0
  234. package/dist/services/proxy-dispatcher.d.ts.map +1 -0
  235. package/dist/services/proxy-dispatcher.js +33 -0
  236. package/dist/services/proxy-dispatcher.js.map +1 -0
  237. package/dist/services/storage.d.ts +7 -0
  238. package/dist/services/storage.d.ts.map +1 -0
  239. package/dist/services/storage.js +55 -0
  240. package/dist/services/storage.js.map +1 -0
  241. package/dist/services/theme-css.d.ts +21 -0
  242. package/dist/services/theme-css.d.ts.map +1 -0
  243. package/dist/services/theme-css.js +213 -0
  244. package/dist/services/theme-css.js.map +1 -0
  245. package/dist/services/user-db.d.ts +69 -0
  246. package/dist/services/user-db.d.ts.map +1 -0
  247. package/dist/services/user-db.js +175 -0
  248. package/dist/services/user-db.js.map +1 -0
  249. package/dist/services/voice/audio-format.d.ts +5 -0
  250. package/dist/services/voice/audio-format.d.ts.map +1 -0
  251. package/dist/services/voice/audio-format.js +27 -0
  252. package/dist/services/voice/audio-format.js.map +1 -0
  253. package/dist/services/voice/azure-openai-whisper-adapter.d.ts +23 -0
  254. package/dist/services/voice/azure-openai-whisper-adapter.d.ts.map +1 -0
  255. package/dist/services/voice/azure-openai-whisper-adapter.js +60 -0
  256. package/dist/services/voice/azure-openai-whisper-adapter.js.map +1 -0
  257. package/dist/services/voice/openai-whisper-adapter.d.ts +22 -0
  258. package/dist/services/voice/openai-whisper-adapter.d.ts.map +1 -0
  259. package/dist/services/voice/openai-whisper-adapter.js +61 -0
  260. package/dist/services/voice/openai-whisper-adapter.js.map +1 -0
  261. package/dist/services/voice/stt-adapter.d.ts +31 -0
  262. package/dist/services/voice/stt-adapter.d.ts.map +1 -0
  263. package/dist/services/voice/stt-adapter.js +8 -0
  264. package/dist/services/voice/stt-adapter.js.map +1 -0
  265. package/dist/services/voice/vad-segmenter.d.ts +68 -0
  266. package/dist/services/voice/vad-segmenter.d.ts.map +1 -0
  267. package/dist/services/voice/vad-segmenter.js +159 -0
  268. package/dist/services/voice/vad-segmenter.js.map +1 -0
  269. package/dist/services/voice/voice-session.d.ts +54 -0
  270. package/dist/services/voice/voice-session.d.ts.map +1 -0
  271. package/dist/services/voice/voice-session.js +137 -0
  272. package/dist/services/voice/voice-session.js.map +1 -0
  273. package/dist/services/window-manager.d.ts +94 -0
  274. package/dist/services/window-manager.d.ts.map +1 -0
  275. package/dist/services/window-manager.js +282 -0
  276. package/dist/services/window-manager.js.map +1 -0
  277. package/dist/services/workspace.d.ts +51 -0
  278. package/dist/services/workspace.d.ts.map +1 -0
  279. package/dist/services/workspace.js +144 -0
  280. package/dist/services/workspace.js.map +1 -0
  281. package/package.json +89 -0
@@ -0,0 +1,61 @@
1
+ /**
2
+ * OpenAI Whisper STT adapter.
3
+ *
4
+ * Uses the /v1/audio/transcriptions endpoint to transcribe complete
5
+ * audio buffers. Audio is sent as WAV (PCM s16le, 16kHz, mono) since
6
+ * Whisper requires a file-like format.
7
+ */
8
+ import { createWavBuffer } from './audio-format.js';
9
+ export class OpenAIWhisperAdapter {
10
+ name = 'openai-whisper';
11
+ apiKey;
12
+ model;
13
+ baseUrl;
14
+ constructor(options) {
15
+ this.apiKey = options.apiKey;
16
+ this.model = options.model ?? 'whisper-1';
17
+ this.baseUrl = options.baseUrl ?? 'https://api.openai.com/v1';
18
+ }
19
+ async transcribe(audioBuffer, sampleRate, language) {
20
+ const wavBuffer = createWavBuffer(audioBuffer, sampleRate);
21
+ const durationMs = Math.round((audioBuffer.length / 2 / sampleRate) * 1000);
22
+ // Build multipart/form-data manually to avoid heavy dependencies
23
+ const boundary = `----DeskTalkBoundary${Date.now()}`;
24
+ const parts = [];
25
+ // model field
26
+ parts.push(Buffer.from(`--${boundary}\r\nContent-Disposition: form-data; name="model"\r\n\r\n${this.model}\r\n`));
27
+ // response_format field
28
+ parts.push(Buffer.from(`--${boundary}\r\nContent-Disposition: form-data; name="response_format"\r\n\r\njson\r\n`));
29
+ console.log("Language:", language);
30
+ // language field (ISO-639-1 code, e.g. 'en', 'zh')
31
+ if (language) {
32
+ parts.push(Buffer.from(`--${boundary}\r\nContent-Disposition: form-data; name="language"\r\n\r\n${language}\r\n`));
33
+ }
34
+ // file field
35
+ parts.push(Buffer.from(`--${boundary}\r\nContent-Disposition: form-data; name="file"; filename="audio.wav"\r\nContent-Type: audio/wav\r\n\r\n`));
36
+ parts.push(wavBuffer);
37
+ parts.push(Buffer.from(`\r\n--${boundary}--\r\n`));
38
+ const body = Buffer.concat(parts);
39
+ const response = await fetch(`${this.baseUrl}/audio/transcriptions`, {
40
+ method: 'POST',
41
+ headers: {
42
+ Authorization: `Bearer ${this.apiKey}`,
43
+ 'Content-Type': `multipart/form-data; boundary=${boundary}`,
44
+ },
45
+ body,
46
+ });
47
+ if (!response.ok) {
48
+ const errorText = await response.text();
49
+ throw new Error(`OpenAI Whisper API error (${response.status}): ${errorText}`);
50
+ }
51
+ const result = (await response.json());
52
+ return {
53
+ text: result.text.trim(),
54
+ durationMs,
55
+ };
56
+ }
57
+ close() {
58
+ // No persistent resources to clean up
59
+ }
60
+ }
61
+ //# sourceMappingURL=openai-whisper-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-whisper-adapter.js","sourceRoot":"","sources":["../../../src/services/voice/openai-whisper-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,OAAO,oBAAoB;IACtB,IAAI,GAAG,gBAAgB,CAAC;IACzB,MAAM,CAAS;IACf,KAAK,CAAS;IACd,OAAO,CAAS;IAExB,YAAY,OAA6D;QACvE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,WAAW,CAAC;QAC1C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,2BAA2B,CAAC;IAChE,CAAC;IAED,KAAK,CAAC,UAAU,CACd,WAAmB,EACnB,UAAkB,EAClB,QAAiB;QAEjB,MAAM,SAAS,GAAG,eAAe,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,IAAI,CAAC,CAAC;QAE5E,iEAAiE;QACjE,MAAM,QAAQ,GAAG,uBAAuB,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QACrD,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,cAAc;QACd,KAAK,CAAC,IAAI,CACR,MAAM,CAAC,IAAI,CACT,KAAK,QAAQ,2DAA2D,IAAI,CAAC,KAAK,MAAM,CACzF,CACF,CAAC;QAEF,wBAAwB;QACxB,KAAK,CAAC,IAAI,CACR,MAAM,CAAC,IAAI,CACT,KAAK,QAAQ,4EAA4E,CAC1F,CACF,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAEnC,mDAAmD;QACnD,IAAI,QAAQ,EAAE,CAAC;YACb,KAAK,CAAC,IAAI,CACR,MAAM,CAAC,IAAI,CACT,KAAK,QAAQ,8DAA8D,QAAQ,MAAM,CAC1F,CACF,CAAC;QACJ,CAAC;QAED,aAAa;QACb,KAAK,CAAC,IAAI,CACR,MAAM,CAAC,IAAI,CACT,KAAK,QAAQ,0GAA0G,CACxH,CACF,CAAC;QACF,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,QAAQ,QAAQ,CAAC,CAAC,CAAC;QAEnD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAElC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,uBAAuB,EAAE;YACnE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;gBACtC,cAAc,EAAE,iCAAiC,QAAQ,EAAE;aAC5D;YACD,IAAI;SACL,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,6BAA6B,QAAQ,CAAC,MAAM,MAAM,SAAS,EAAE,CAAC,CAAC;QACjF,CAAC;QAED,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAqB,CAAC;QAE3D,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE;YACxB,UAAU;SACX,CAAC;IACJ,CAAC;IAED,KAAK;QACH,sCAAsC;IACxC,CAAC;CACF"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Speech-to-Text adapter interface.
3
+ *
4
+ * Abstracts the STT provider so the voice pipeline can swap providers
5
+ * without changing the session manager or segmenter logic.
6
+ */
7
+ export interface SttTranscript {
8
+ text: string;
9
+ /** Confidence score 0-1 if available from provider */
10
+ confidence?: number;
11
+ /** Duration of the audio in milliseconds */
12
+ durationMs?: number;
13
+ }
14
+ export interface SttAdapter {
15
+ /** Human-readable name of the provider */
16
+ readonly name: string;
17
+ /**
18
+ * Transcribe a complete audio buffer.
19
+ *
20
+ * @param audioBuffer - Raw PCM s16le audio at 16kHz mono
21
+ * @param sampleRate - Sample rate (always 16000 for v1)
22
+ * @param language - Optional ISO-639-1 language code (e.g. 'en', 'zh') to hint the STT engine
23
+ * @returns Transcript result
24
+ */
25
+ transcribe(audioBuffer: Buffer, sampleRate: number, language?: string): Promise<SttTranscript>;
26
+ /**
27
+ * Clean up any resources held by the adapter.
28
+ */
29
+ close(): void;
30
+ }
31
+ //# sourceMappingURL=stt-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stt-adapter.d.ts","sourceRoot":"","sources":["../../../src/services/voice/stt-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,0CAA0C;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;;;;;OAOG;IACH,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAE/F;;OAEG;IACH,KAAK,IAAI,IAAI,CAAC;CACf"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Speech-to-Text adapter interface.
3
+ *
4
+ * Abstracts the STT provider so the voice pipeline can swap providers
5
+ * without changing the session manager or segmenter logic.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=stt-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stt-adapter.js","sourceRoot":"","sources":["../../../src/services/voice/stt-adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Voice Activity Detection (VAD) and utterance segmenter.
3
+ *
4
+ * Uses energy-based detection on raw PCM s16le audio to determine
5
+ * speech vs silence boundaries. Manages state transitions for
6
+ * utterance segmentation with configurable thresholds.
7
+ *
8
+ * Design decisions:
9
+ * - Energy-based VAD rather than ML-based for v1 simplicity
10
+ * - RMS energy with configurable threshold
11
+ * - Silence timeout finalizes utterances (800ms default)
12
+ * - Minimum speech duration prevents noise spikes (300ms default)
13
+ * - Maximum utterance duration caps long segments (15s default)
14
+ */
15
+ export interface VadConfig {
16
+ /** RMS energy threshold to consider as speech (0-32767 range). Default: 500 */
17
+ energyThreshold: number;
18
+ /** Silence duration (ms) before finalizing utterance. Default: 800 */
19
+ silenceTimeoutMs: number;
20
+ /** Minimum speech duration (ms) to count as valid utterance. Default: 300 */
21
+ minSpeechDurationMs: number;
22
+ /** Maximum utterance duration (ms). Default: 15000 */
23
+ maxUtteranceDurationMs: number;
24
+ }
25
+ export declare const DEFAULT_VAD_CONFIG: VadConfig;
26
+ export type VadState = 'LISTENING' | 'IN_SPEECH' | 'WAITING_FOR_FINAL_SILENCE' | 'PROCESSING';
27
+ export interface VadEvent {
28
+ type: 'speech_start' | 'speech_end' | 'silence_timeout' | 'max_duration';
29
+ timestamp: number;
30
+ }
31
+ export declare class VadSegmenter {
32
+ private config;
33
+ private state;
34
+ private speechStartTime;
35
+ private lastVoiceActivityTime;
36
+ private speechBuffer;
37
+ private speechBufferBytes;
38
+ constructor(config?: Partial<VadConfig>);
39
+ getState(): VadState;
40
+ /**
41
+ * Feed a chunk of PCM s16le audio into the segmenter.
42
+ *
43
+ * @param chunk - Raw PCM s16le audio buffer at 16kHz
44
+ * @returns Array of events triggered by this chunk, plus the
45
+ * complete utterance buffer if the utterance was finalized.
46
+ */
47
+ processChunk(chunk: Buffer): {
48
+ events: VadEvent[];
49
+ finalizedUtterance: Buffer | null;
50
+ };
51
+ /**
52
+ * Concatenate the speech buffer and transition to PROCESSING.
53
+ */
54
+ private finalizeUtterance;
55
+ /**
56
+ * Mark processing as complete and return to listening.
57
+ */
58
+ doneProcessing(): void;
59
+ /**
60
+ * Reset the segmenter to the initial listening state.
61
+ */
62
+ reset(): void;
63
+ /**
64
+ * Get the current speech buffer size in bytes (for observability).
65
+ */
66
+ getBufferSizeBytes(): number;
67
+ }
68
+ //# sourceMappingURL=vad-segmenter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vad-segmenter.d.ts","sourceRoot":"","sources":["../../../src/services/voice/vad-segmenter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,SAAS;IACxB,+EAA+E;IAC/E,eAAe,EAAE,MAAM,CAAC;IACxB,sEAAsE;IACtE,gBAAgB,EAAE,MAAM,CAAC;IACzB,6EAA6E;IAC7E,mBAAmB,EAAE,MAAM,CAAC;IAC5B,sDAAsD;IACtD,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,eAAO,MAAM,kBAAkB,EAAE,SAKhC,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,WAAW,GAAG,2BAA2B,GAAG,YAAY,CAAC;AAE9F,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,cAAc,GAAG,YAAY,GAAG,iBAAiB,GAAG,cAAc,CAAC;IACzE,SAAS,EAAE,MAAM,CAAC;CACnB;AAkBD,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,iBAAiB,CAAK;gBAElB,MAAM,GAAE,OAAO,CAAC,SAAS,CAAM;IAI3C,QAAQ,IAAI,QAAQ;IAIpB;;;;;;OAMG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG;QAC3B,MAAM,EAAE,QAAQ,EAAE,CAAC;QACnB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;KACnC;IAkFD;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAQzB;;OAEG;IACH,cAAc,IAAI,IAAI;IAMtB;;OAEG;IACH,KAAK,IAAI,IAAI;IAQb;;OAEG;IACH,kBAAkB,IAAI,MAAM;CAG7B"}
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Voice Activity Detection (VAD) and utterance segmenter.
3
+ *
4
+ * Uses energy-based detection on raw PCM s16le audio to determine
5
+ * speech vs silence boundaries. Manages state transitions for
6
+ * utterance segmentation with configurable thresholds.
7
+ *
8
+ * Design decisions:
9
+ * - Energy-based VAD rather than ML-based for v1 simplicity
10
+ * - RMS energy with configurable threshold
11
+ * - Silence timeout finalizes utterances (800ms default)
12
+ * - Minimum speech duration prevents noise spikes (300ms default)
13
+ * - Maximum utterance duration caps long segments (15s default)
14
+ */
15
+ export const DEFAULT_VAD_CONFIG = {
16
+ energyThreshold: 500,
17
+ silenceTimeoutMs: 800,
18
+ minSpeechDurationMs: 300,
19
+ maxUtteranceDurationMs: 15000,
20
+ };
21
+ /**
22
+ * Compute RMS (Root Mean Square) energy of a PCM s16le buffer.
23
+ */
24
+ function computeRmsEnergy(pcmBuffer) {
25
+ const sampleCount = pcmBuffer.length / 2;
26
+ if (sampleCount === 0)
27
+ return 0;
28
+ let sumSquares = 0;
29
+ for (let i = 0; i < pcmBuffer.length; i += 2) {
30
+ const sample = pcmBuffer.readInt16LE(i);
31
+ sumSquares += sample * sample;
32
+ }
33
+ return Math.sqrt(sumSquares / sampleCount);
34
+ }
35
+ export class VadSegmenter {
36
+ config;
37
+ state = 'LISTENING';
38
+ speechStartTime = 0;
39
+ lastVoiceActivityTime = 0;
40
+ speechBuffer = [];
41
+ speechBufferBytes = 0;
42
+ constructor(config = {}) {
43
+ this.config = { ...DEFAULT_VAD_CONFIG, ...config };
44
+ }
45
+ getState() {
46
+ return this.state;
47
+ }
48
+ /**
49
+ * Feed a chunk of PCM s16le audio into the segmenter.
50
+ *
51
+ * @param chunk - Raw PCM s16le audio buffer at 16kHz
52
+ * @returns Array of events triggered by this chunk, plus the
53
+ * complete utterance buffer if the utterance was finalized.
54
+ */
55
+ processChunk(chunk) {
56
+ const now = Date.now();
57
+ const events = [];
58
+ let finalizedUtterance = null;
59
+ const energy = computeRmsEnergy(chunk);
60
+ const isSpeech = energy >= this.config.energyThreshold;
61
+ switch (this.state) {
62
+ case 'LISTENING':
63
+ if (isSpeech) {
64
+ this.state = 'IN_SPEECH';
65
+ this.speechStartTime = now;
66
+ this.lastVoiceActivityTime = now;
67
+ this.speechBuffer = [chunk];
68
+ this.speechBufferBytes = chunk.length;
69
+ events.push({ type: 'speech_start', timestamp: now });
70
+ }
71
+ break;
72
+ case 'IN_SPEECH':
73
+ this.speechBuffer.push(chunk);
74
+ this.speechBufferBytes += chunk.length;
75
+ if (isSpeech) {
76
+ this.lastVoiceActivityTime = now;
77
+ }
78
+ // Check max duration
79
+ if (now - this.speechStartTime >= this.config.maxUtteranceDurationMs) {
80
+ events.push({ type: 'max_duration', timestamp: now });
81
+ finalizedUtterance = this.finalizeUtterance();
82
+ break;
83
+ }
84
+ // Transition to waiting if we detect silence
85
+ if (!isSpeech) {
86
+ this.state = 'WAITING_FOR_FINAL_SILENCE';
87
+ }
88
+ break;
89
+ case 'WAITING_FOR_FINAL_SILENCE':
90
+ this.speechBuffer.push(chunk);
91
+ this.speechBufferBytes += chunk.length;
92
+ if (isSpeech) {
93
+ // Speech resumed — go back to IN_SPEECH
94
+ this.state = 'IN_SPEECH';
95
+ this.lastVoiceActivityTime = now;
96
+ break;
97
+ }
98
+ // Check max duration
99
+ if (now - this.speechStartTime >= this.config.maxUtteranceDurationMs) {
100
+ events.push({ type: 'max_duration', timestamp: now });
101
+ finalizedUtterance = this.finalizeUtterance();
102
+ break;
103
+ }
104
+ // Check if silence has lasted long enough
105
+ if (now - this.lastVoiceActivityTime >= this.config.silenceTimeoutMs) {
106
+ const speechDuration = this.lastVoiceActivityTime - this.speechStartTime;
107
+ if (speechDuration >= this.config.minSpeechDurationMs) {
108
+ events.push({ type: 'silence_timeout', timestamp: now });
109
+ finalizedUtterance = this.finalizeUtterance();
110
+ }
111
+ else {
112
+ // Too short to be real speech — discard and go back to listening
113
+ this.reset();
114
+ }
115
+ }
116
+ break;
117
+ case 'PROCESSING':
118
+ // While processing, buffer audio for the next utterance
119
+ // In v1, just drop it and wait for reset
120
+ break;
121
+ }
122
+ return { events, finalizedUtterance };
123
+ }
124
+ /**
125
+ * Concatenate the speech buffer and transition to PROCESSING.
126
+ */
127
+ finalizeUtterance() {
128
+ this.state = 'PROCESSING';
129
+ const result = Buffer.concat(this.speechBuffer);
130
+ this.speechBuffer = [];
131
+ this.speechBufferBytes = 0;
132
+ return result;
133
+ }
134
+ /**
135
+ * Mark processing as complete and return to listening.
136
+ */
137
+ doneProcessing() {
138
+ this.state = 'LISTENING';
139
+ this.speechBuffer = [];
140
+ this.speechBufferBytes = 0;
141
+ }
142
+ /**
143
+ * Reset the segmenter to the initial listening state.
144
+ */
145
+ reset() {
146
+ this.state = 'LISTENING';
147
+ this.speechStartTime = 0;
148
+ this.lastVoiceActivityTime = 0;
149
+ this.speechBuffer = [];
150
+ this.speechBufferBytes = 0;
151
+ }
152
+ /**
153
+ * Get the current speech buffer size in bytes (for observability).
154
+ */
155
+ getBufferSizeBytes() {
156
+ return this.speechBufferBytes;
157
+ }
158
+ }
159
+ //# sourceMappingURL=vad-segmenter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vad-segmenter.js","sourceRoot":"","sources":["../../../src/services/voice/vad-segmenter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAaH,MAAM,CAAC,MAAM,kBAAkB,GAAc;IAC3C,eAAe,EAAE,GAAG;IACpB,gBAAgB,EAAE,GAAG;IACrB,mBAAmB,EAAE,GAAG;IACxB,sBAAsB,EAAE,KAAK;CAC9B,CAAC;AASF;;GAEG;AACH,SAAS,gBAAgB,CAAC,SAAiB;IACzC,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;IACzC,IAAI,WAAW,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAEhC,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACxC,UAAU,IAAI,MAAM,GAAG,MAAM,CAAC;IAChC,CAAC;IAED,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,OAAO,YAAY;IACf,MAAM,CAAY;IAClB,KAAK,GAAa,WAAW,CAAC;IAC9B,eAAe,GAAG,CAAC,CAAC;IACpB,qBAAqB,GAAG,CAAC,CAAC;IAC1B,YAAY,GAAa,EAAE,CAAC;IAC5B,iBAAiB,GAAG,CAAC,CAAC;IAE9B,YAAY,SAA6B,EAAE;QACzC,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,kBAAkB,EAAE,GAAG,MAAM,EAAE,CAAC;IACrD,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED;;;;;;OAMG;IACH,YAAY,CAAC,KAAa;QAIxB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,MAAM,GAAe,EAAE,CAAC;QAC9B,IAAI,kBAAkB,GAAkB,IAAI,CAAC;QAE7C,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM,QAAQ,GAAG,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC;QAEvD,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;YACnB,KAAK,WAAW;gBACd,IAAI,QAAQ,EAAE,CAAC;oBACb,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC;oBACzB,IAAI,CAAC,eAAe,GAAG,GAAG,CAAC;oBAC3B,IAAI,CAAC,qBAAqB,GAAG,GAAG,CAAC;oBACjC,IAAI,CAAC,YAAY,GAAG,CAAC,KAAK,CAAC,CAAC;oBAC5B,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC,MAAM,CAAC;oBACtC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;gBACxD,CAAC;gBACD,MAAM;YAER,KAAK,WAAW;gBACd,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC9B,IAAI,CAAC,iBAAiB,IAAI,KAAK,CAAC,MAAM,CAAC;gBAEvC,IAAI,QAAQ,EAAE,CAAC;oBACb,IAAI,CAAC,qBAAqB,GAAG,GAAG,CAAC;gBACnC,CAAC;gBAED,qBAAqB;gBACrB,IAAI,GAAG,GAAG,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,MAAM,CAAC,sBAAsB,EAAE,CAAC;oBACrE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;oBACtD,kBAAkB,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;oBAC9C,MAAM;gBACR,CAAC;gBAED,6CAA6C;gBAC7C,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,IAAI,CAAC,KAAK,GAAG,2BAA2B,CAAC;gBAC3C,CAAC;gBACD,MAAM;YAER,KAAK,2BAA2B;gBAC9B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC9B,IAAI,CAAC,iBAAiB,IAAI,KAAK,CAAC,MAAM,CAAC;gBAEvC,IAAI,QAAQ,EAAE,CAAC;oBACb,wCAAwC;oBACxC,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC;oBACzB,IAAI,CAAC,qBAAqB,GAAG,GAAG,CAAC;oBACjC,MAAM;gBACR,CAAC;gBAED,qBAAqB;gBACrB,IAAI,GAAG,GAAG,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,MAAM,CAAC,sBAAsB,EAAE,CAAC;oBACrE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;oBACtD,kBAAkB,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;oBAC9C,MAAM;gBACR,CAAC;gBAED,0CAA0C;gBAC1C,IAAI,GAAG,GAAG,IAAI,CAAC,qBAAqB,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;oBACrE,MAAM,cAAc,GAAG,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,eAAe,CAAC;oBAEzE,IAAI,cAAc,IAAI,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;wBACtD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;wBACzD,kBAAkB,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;oBAChD,CAAC;yBAAM,CAAC;wBACN,iEAAiE;wBACjE,IAAI,CAAC,KAAK,EAAE,CAAC;oBACf,CAAC;gBACH,CAAC;gBACD,MAAM;YAER,KAAK,YAAY;gBACf,wDAAwD;gBACxD,yCAAyC;gBACzC,MAAM;QACV,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;IACxC,CAAC;IAED;;OAEG;IACK,iBAAiB;QACvB,IAAI,CAAC,KAAK,GAAG,YAAY,CAAC;QAC1B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAChD,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;QAC3B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC;QACzB,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC;QACzB,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,qBAAqB,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,kBAAkB;QAChB,OAAO,IAAI,CAAC,iBAAiB,CAAC;IAChC,CAAC;CACF"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Voice session manager.
3
+ *
4
+ * Manages per-session state: audio ingestion, VAD segmentation,
5
+ * STT transcription, and event publishing back to the client.
6
+ *
7
+ * Each voice WebSocket connection gets one VoiceSession instance.
8
+ */
9
+ import type { WebSocket } from 'ws';
10
+ import type pino from 'pino';
11
+ import { type VadConfig } from './vad-segmenter.js';
12
+ import type { SttAdapter } from './stt-adapter.js';
13
+ export type SessionState = 'LISTENING' | 'IN_SPEECH' | 'WAITING_FOR_FINAL_SILENCE' | 'PROCESSING' | 'CLOSED';
14
+ export interface VoiceSessionConfig {
15
+ sampleRate: number;
16
+ channels: number;
17
+ format: string;
18
+ vad?: Partial<VadConfig>;
19
+ /** ISO-639-1 language code (e.g. 'en', 'zh') to hint the STT engine */
20
+ language?: string;
21
+ }
22
+ export interface TranscriptEntry {
23
+ utteranceId: string;
24
+ text: string;
25
+ timestamp: number;
26
+ durationMs?: number;
27
+ }
28
+ export declare class VoiceSession {
29
+ readonly sessionId: string;
30
+ private ws;
31
+ private sttAdapter;
32
+ private segmenter;
33
+ private config;
34
+ private state;
35
+ private transcripts;
36
+ private chunkCount;
37
+ private createdAt;
38
+ private currentUtteranceId;
39
+ private logger;
40
+ constructor(sessionId: string, ws: WebSocket, sttAdapter: SttAdapter, config: VoiceSessionConfig, logger: pino.Logger);
41
+ /**
42
+ * Process an incoming binary audio chunk from the client.
43
+ */
44
+ processAudioChunk(chunk: Buffer): Promise<void>;
45
+ /**
46
+ * Close the session and clean up resources.
47
+ */
48
+ close(): void;
49
+ getState(): SessionState;
50
+ getTranscripts(): TranscriptEntry[];
51
+ getChunkCount(): number;
52
+ private sendEvent;
53
+ }
54
+ //# sourceMappingURL=voice-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-session.d.ts","sourceRoot":"","sources":["../../../src/services/voice/voice-session.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,MAAM,YAAY,GACpB,WAAW,GACX,WAAW,GACX,2BAA2B,GAC3B,YAAY,GACZ,QAAQ,CAAC;AAEb,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IACzB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAcD,qBAAa,YAAY;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,CAAY;IACtB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,SAAS,CAAe;IAChC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,WAAW,CAAyB;IAC5C,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,kBAAkB,CAAuB;IACjD,OAAO,CAAC,MAAM,CAAc;gBAG1B,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,SAAS,EACb,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,IAAI,CAAC,MAAM;IAWrB;;OAEG;IACG,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoFrD;;OAEG;IACH,KAAK,IAAI,IAAI;IAab,QAAQ,IAAI,YAAY;IAIxB,cAAc,IAAI,eAAe,EAAE;IAInC,aAAa,IAAI,MAAM;IAIvB,OAAO,CAAC,SAAS;CAKlB"}
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Voice session manager.
3
+ *
4
+ * Manages per-session state: audio ingestion, VAD segmentation,
5
+ * STT transcription, and event publishing back to the client.
6
+ *
7
+ * Each voice WebSocket connection gets one VoiceSession instance.
8
+ */
9
+ import { VadSegmenter } from './vad-segmenter.js';
10
+ let utteranceCounter = 0;
11
+ function nextUtteranceId() {
12
+ return `u${++utteranceCounter}`;
13
+ }
14
+ export class VoiceSession {
15
+ sessionId;
16
+ ws;
17
+ sttAdapter;
18
+ segmenter;
19
+ config;
20
+ state = 'LISTENING';
21
+ transcripts = [];
22
+ chunkCount = 0;
23
+ createdAt;
24
+ currentUtteranceId = null;
25
+ logger;
26
+ constructor(sessionId, ws, sttAdapter, config, logger) {
27
+ this.sessionId = sessionId;
28
+ this.ws = ws;
29
+ this.sttAdapter = sttAdapter;
30
+ this.config = config;
31
+ this.segmenter = new VadSegmenter(config.vad);
32
+ this.createdAt = Date.now();
33
+ this.logger = logger;
34
+ }
35
+ /**
36
+ * Process an incoming binary audio chunk from the client.
37
+ */
38
+ async processAudioChunk(chunk) {
39
+ if (this.state === 'CLOSED')
40
+ return;
41
+ this.chunkCount++;
42
+ const { events, finalizedUtterance } = this.segmenter.processChunk(chunk);
43
+ // Update our state to mirror the segmenter
44
+ const segmenterState = this.segmenter.getState();
45
+ if (segmenterState !== 'PROCESSING') {
46
+ this.state = segmenterState;
47
+ }
48
+ // Emit VAD events to the client
49
+ for (const event of events) {
50
+ switch (event.type) {
51
+ case 'speech_start':
52
+ this.currentUtteranceId = nextUtteranceId();
53
+ this.sendEvent({
54
+ type: 'speech.start',
55
+ sessionId: this.sessionId,
56
+ utteranceId: this.currentUtteranceId,
57
+ timestamp: event.timestamp,
58
+ });
59
+ break;
60
+ case 'silence_timeout':
61
+ case 'max_duration':
62
+ // Speech ended — utterance will be finalized
63
+ break;
64
+ }
65
+ }
66
+ // If the segmenter finalized an utterance, transcribe it
67
+ if (finalizedUtterance) {
68
+ this.state = 'PROCESSING';
69
+ const utteranceId = this.currentUtteranceId ?? nextUtteranceId();
70
+ try {
71
+ const transcript = await this.sttAdapter.transcribe(finalizedUtterance, this.config.sampleRate, this.config.language);
72
+ const entry = {
73
+ utteranceId,
74
+ text: transcript.text,
75
+ timestamp: Date.now(),
76
+ durationMs: transcript.durationMs,
77
+ };
78
+ this.transcripts.push(entry);
79
+ // Send final transcript
80
+ this.sendEvent({
81
+ type: 'transcript.final',
82
+ sessionId: this.sessionId,
83
+ utteranceId,
84
+ text: transcript.text,
85
+ durationMs: transcript.durationMs,
86
+ });
87
+ // Send speech end
88
+ this.sendEvent({
89
+ type: 'speech.end',
90
+ sessionId: this.sessionId,
91
+ utteranceId,
92
+ timestamp: Date.now(),
93
+ });
94
+ }
95
+ catch (err) {
96
+ this.sendEvent({
97
+ type: 'error',
98
+ sessionId: this.sessionId,
99
+ code: 'PROVIDER_ERROR',
100
+ message: err.message,
101
+ });
102
+ }
103
+ finally {
104
+ this.segmenter.doneProcessing();
105
+ this.state = 'LISTENING';
106
+ this.currentUtteranceId = null;
107
+ }
108
+ }
109
+ }
110
+ /**
111
+ * Close the session and clean up resources.
112
+ */
113
+ close() {
114
+ this.state = 'CLOSED';
115
+ this.segmenter.reset();
116
+ this.logger.info({
117
+ chunks: this.chunkCount,
118
+ transcripts: this.transcripts.length,
119
+ durationMs: Date.now() - this.createdAt,
120
+ }, 'voice session closed');
121
+ }
122
+ getState() {
123
+ return this.state;
124
+ }
125
+ getTranscripts() {
126
+ return [...this.transcripts];
127
+ }
128
+ getChunkCount() {
129
+ return this.chunkCount;
130
+ }
131
+ sendEvent(event) {
132
+ if (this.ws.readyState === 1 /* OPEN */) {
133
+ this.ws.send(JSON.stringify(event));
134
+ }
135
+ }
136
+ }
137
+ //# sourceMappingURL=voice-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice-session.js","sourceRoot":"","sources":["../../../src/services/voice/voice-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ export interface SerializableActionDefinition {
2
+ name: string;
3
+ description: string;
4
+ params?: Record<string, {
5
+ type: 'string' | 'number' | 'boolean';
6
+ description?: string;
7
+ required?: boolean;
8
+ }>;
9
+ }
10
+ /**
11
+ * Tiling tree node types (mirrored from frontend tiling-tree.ts for persistence).
12
+ */
13
+ export interface LeafNode {
14
+ type: 'leaf';
15
+ windowId: string;
16
+ }
17
+ export interface ContainerNode {
18
+ type: 'container';
19
+ split: 'horizontal' | 'vertical';
20
+ ratio: number;
21
+ children: [TilingNode, TilingNode];
22
+ }
23
+ export type TilingNode = LeafNode | ContainerNode;
24
+ export interface PersistedWindow {
25
+ id: string;
26
+ miniAppId: string;
27
+ title: string;
28
+ args?: Record<string, unknown>;
29
+ }
30
+ export interface PersistedWindowState {
31
+ version: 2;
32
+ windows: PersistedWindow[];
33
+ focusedWindowId: string | null;
34
+ fullscreenWindowId: string | null;
35
+ windowIdCounter: number;
36
+ nextSplitDirection: 'horizontal' | 'vertical' | 'auto';
37
+ tree: TilingNode | null;
38
+ }
39
+ /**
40
+ * Backend window manager service — persistence-only.
41
+ *
42
+ * The frontend Zustand store is the live source of truth.
43
+ * This service:
44
+ * - Loads persisted state on startup for the initial `window:state` message
45
+ * - Receives synced state from the frontend and persists it
46
+ * - Keeps window actions metadata for the AI system prompt
47
+ * - Provides `getSystemPromptContext()` for dynamic AI prompt injection
48
+ */
49
+ export declare class WindowManagerService {
50
+ private state;
51
+ private readonly windowActions;
52
+ private filePath;
53
+ constructor(filePath: string);
54
+ /**
55
+ * Switch the backing file path (e.g. when a different user connects)
56
+ * and reload persisted state from the new location.
57
+ */
58
+ switchUser(newFilePath: string): void;
59
+ private load;
60
+ /**
61
+ * Get the persisted state to send to the frontend on initial connect.
62
+ */
63
+ getPersistedState(): PersistedWindowState;
64
+ /**
65
+ * Receive the full state from the frontend and persist it.
66
+ * Called when the frontend sends `window:sync`.
67
+ */
68
+ syncState(payload: PersistedWindowState): void;
69
+ /**
70
+ * Get the current windows (from last synced state).
71
+ */
72
+ getWindows(): PersistedWindow[];
73
+ getFocusedWindow(): PersistedWindow | undefined;
74
+ getWindowActions(windowId: string): SerializableActionDefinition[];
75
+ setWindowActions(windowId: string, actions: SerializableActionDefinition[]): void;
76
+ /**
77
+ * Activate persisted MiniApps on startup.
78
+ */
79
+ activatePersistedMiniApps(activate: (miniAppId: string, launchArgs: Array<Record<string, unknown>>) => Promise<void>): Promise<void>;
80
+ /**
81
+ * Build a dynamic desktop context block to prepend to user messages.
82
+ *
83
+ * This is injected per-prompt so the AI always sees the latest state
84
+ * without polluting the cacheable system prompt.
85
+ */
86
+ getDesktopContext(availableMiniApps: Array<{
87
+ id: string;
88
+ name: string;
89
+ }>, availableLiveApps: Array<{
90
+ id: string;
91
+ name: string;
92
+ }>, userHomeDir: string): string;
93
+ }
94
+ //# sourceMappingURL=window-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"window-manager.d.ts","sourceRoot":"","sources":["../../src/services/window-manager.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CACb,MAAM,EACN;QACE,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;QACtC,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,CACF,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,YAAY,GAAG,UAAU,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;CACpC;AAED,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,aAAa,CAAC;AAElD,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,YAAY,GAAG,UAAU,GAAG,MAAM,CAAC;IACvD,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;CACzB;AAkJD;;;;;;;;;GASG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsD;IACpF,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,EAAE,MAAM;IAK5B;;;OAGG;IACH,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAMrC,OAAO,CAAC,IAAI;IAuCZ;;OAEG;IACH,iBAAiB,IAAI,oBAAoB;IAIzC;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAmB9C;;OAEG;IACH,UAAU,IAAI,eAAe,EAAE;IAI/B,gBAAgB,IAAI,eAAe,GAAG,SAAS;IAI/C,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,4BAA4B,EAAE;IAIlE,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,4BAA4B,EAAE,GAAG,IAAI;IAIjF;;OAEG;IACG,yBAAyB,CAC7B,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GACzF,OAAO,CAAC,IAAI,CAAC;IAchB;;;;;OAKG;IACH,iBAAiB,CACf,iBAAiB,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,EACtD,iBAAiB,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,EACtD,WAAW,EAAE,MAAM,GAClB,MAAM;CA8DV"}