@qvac/sdk 0.9.2 → 0.10.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 (343) hide show
  1. package/NOTICE +42 -95
  2. package/dist/client/api/cancel.d.ts +1 -1
  3. package/dist/client/api/cancel.js +1 -1
  4. package/dist/client/api/completion-stream.d.ts +51 -12
  5. package/dist/client/api/completion-stream.js +129 -56
  6. package/dist/client/api/delete-cache.d.ts +1 -0
  7. package/dist/client/api/delete-cache.js +1 -0
  8. package/dist/client/api/diffusion.d.ts +17 -2
  9. package/dist/client/api/diffusion.js +21 -4
  10. package/dist/client/api/embed.d.ts +4 -0
  11. package/dist/client/api/finetune.d.ts +21 -0
  12. package/dist/client/api/get-loaded-model-info.d.ts +25 -0
  13. package/dist/client/api/get-loaded-model-info.js +36 -0
  14. package/dist/client/api/get-model-info.d.ts +9 -1
  15. package/dist/client/api/get-model-info.js +8 -0
  16. package/dist/client/api/heartbeat.d.ts +2 -2
  17. package/dist/client/api/heartbeat.js +2 -2
  18. package/dist/client/api/index.d.ts +3 -1
  19. package/dist/client/api/index.js +3 -1
  20. package/dist/client/api/invoke-plugin.d.ts +16 -0
  21. package/dist/client/api/invoke-plugin.js +16 -0
  22. package/dist/client/api/load-model.d.ts +36 -3
  23. package/dist/client/api/load-model.js +31 -10
  24. package/dist/client/api/provide.d.ts +11 -5
  25. package/dist/client/api/provide.js +11 -6
  26. package/dist/client/api/rag.d.ts +9 -0
  27. package/dist/client/api/rag.js +9 -0
  28. package/dist/client/api/registry.d.ts +26 -0
  29. package/dist/client/api/registry.js +26 -0
  30. package/dist/client/api/resume.d.ts +20 -4
  31. package/dist/client/api/resume.js +20 -4
  32. package/dist/client/api/state.d.ts +23 -0
  33. package/dist/client/api/state.js +29 -0
  34. package/dist/client/api/stop-provider.d.ts +11 -5
  35. package/dist/client/api/stop-provider.js +11 -5
  36. package/dist/client/api/suspend.d.ts +21 -3
  37. package/dist/client/api/suspend.js +21 -3
  38. package/dist/client/api/text-to-speech.d.ts +64 -6
  39. package/dist/client/api/text-to-speech.js +423 -47
  40. package/dist/client/api/transcribe.d.ts +29 -4
  41. package/dist/client/api/transcribe.js +86 -28
  42. package/dist/client/api/translate.d.ts +1 -0
  43. package/dist/client/api/translate.js +1 -0
  44. package/dist/client/rpc/bare-client.js +22 -1
  45. package/dist/client/rpc/expo-rpc-client.d.ts +1 -1
  46. package/dist/client/rpc/expo-rpc-client.js +96 -4
  47. package/dist/client/rpc/node-rpc-client.js +36 -0
  48. package/dist/examples/audio/mic-input.d.ts +9 -0
  49. package/dist/examples/audio/mic-input.js +111 -0
  50. package/dist/examples/completion-events.d.ts +18 -0
  51. package/dist/examples/completion-events.js +79 -0
  52. package/dist/examples/delegated-inference/composite.js +12 -18
  53. package/dist/examples/delegated-inference/consumer-profiled.js +4 -11
  54. package/dist/examples/delegated-inference/consumer.js +8 -13
  55. package/dist/examples/delegated-inference/provider.js +11 -16
  56. package/dist/examples/diffusion-flux2-klein-img2img.d.ts +2 -0
  57. package/dist/examples/diffusion-flux2-klein-img2img.js +60 -0
  58. package/dist/examples/diffusion-flux2-klein.js +1 -0
  59. package/dist/examples/diffusion-img2img.d.ts +2 -0
  60. package/dist/examples/diffusion-img2img.js +49 -0
  61. package/dist/examples/diffusion-txt2img.js +2 -1
  62. package/dist/examples/kv-cache-example.js +11 -12
  63. package/dist/examples/llamacpp-cache.d.ts +2 -0
  64. package/dist/examples/llamacpp-cache.js +107 -0
  65. package/dist/examples/llamacpp-dynamic-tools.d.ts +2 -0
  66. package/dist/examples/llamacpp-dynamic-tools.js +144 -0
  67. package/dist/examples/llamacpp-structured-output.d.ts +2 -0
  68. package/dist/examples/llamacpp-structured-output.js +106 -0
  69. package/dist/examples/plugins.js +4 -4
  70. package/dist/examples/suspend-resume.js +21 -4
  71. package/dist/examples/{llamacpp-native-tools.js → tools/llamacpp-native-tools.js} +6 -55
  72. package/dist/examples/tools/llamacpp-tools-harmony-multiturn.d.ts +2 -0
  73. package/dist/examples/tools/llamacpp-tools-harmony-multiturn.js +81 -0
  74. package/dist/examples/tools/llamacpp-tools-pythonic.d.ts +2 -0
  75. package/dist/examples/tools/llamacpp-tools-pythonic.js +50 -0
  76. package/dist/examples/tools/shared.d.ts +21 -0
  77. package/dist/examples/tools/shared.js +42 -0
  78. package/dist/examples/transcription/parakeet-microphone-record.js +6 -33
  79. package/dist/examples/transcription/whispercpp-filesystem-streaming.js +7 -5
  80. package/dist/examples/transcription/whispercpp-filesystem.js +12 -3
  81. package/dist/examples/transcription/whispercpp-microphone-record.js +6 -29
  82. package/dist/examples/translation/translation-stream.js +5 -5
  83. package/dist/examples/tts/llm-to-tts-streaming.d.ts +16 -0
  84. package/dist/examples/tts/llm-to-tts-streaming.js +143 -0
  85. package/dist/examples/tts/supertonic-multilingual.js +3 -3
  86. package/dist/examples/tts/supertonic.js +3 -3
  87. package/dist/examples/tts/utils.d.ts +11 -1
  88. package/dist/examples/tts/utils.js +70 -17
  89. package/dist/examples/voice-assistant/voice-assistant.d.ts +2 -0
  90. package/dist/examples/voice-assistant/voice-assistant.js +207 -0
  91. package/dist/expo/plugins/withMobileBundle.js +1 -1
  92. package/dist/index.d.ts +2 -2
  93. package/dist/index.js +2 -2
  94. package/dist/logging/logger.d.ts +11 -0
  95. package/dist/logging/logger.js +11 -0
  96. package/dist/logging/types.d.ts +18 -0
  97. package/dist/models/registry/models.d.ts +6973 -7457
  98. package/dist/models/registry/models.js +6889 -6855
  99. package/dist/models/update-models/codegen.js +84 -23
  100. package/dist/models/update-models/companions.d.ts +18 -0
  101. package/dist/models/update-models/companions.js +175 -0
  102. package/dist/models/update-models/naming.js +0 -25
  103. package/dist/models/update-models/registry.d.ts +1 -0
  104. package/dist/models/update-models/registry.js +23 -3
  105. package/dist/models/update-models/types.d.ts +37 -9
  106. package/dist/profiling/index.d.ts +49 -0
  107. package/dist/profiling/index.js +49 -0
  108. package/dist/schemas/cancel.d.ts +6 -2
  109. package/dist/schemas/cancel.js +14 -7
  110. package/dist/schemas/common.d.ts +354 -271
  111. package/dist/schemas/common.js +26 -5
  112. package/dist/schemas/completion-event.d.ts +225 -0
  113. package/dist/schemas/completion-event.js +79 -0
  114. package/dist/schemas/completion-stream.d.ts +126 -31
  115. package/dist/schemas/completion-stream.js +138 -36
  116. package/dist/schemas/delegate.d.ts +0 -2
  117. package/dist/schemas/delegate.js +25 -6
  118. package/dist/schemas/download-asset.d.ts +5 -5
  119. package/dist/schemas/embed.js +21 -9
  120. package/dist/schemas/engine-addon-map.d.ts +11 -1
  121. package/dist/schemas/engine-addon-map.js +2 -2
  122. package/dist/schemas/get-loaded-model-info.d.ts +52 -0
  123. package/dist/schemas/get-loaded-model-info.js +44 -0
  124. package/dist/schemas/get-model-info.d.ts +2 -2
  125. package/dist/schemas/get-model-info.js +103 -32
  126. package/dist/schemas/heartbeat.d.ts +0 -1
  127. package/dist/schemas/index.d.ts +4 -1
  128. package/dist/schemas/index.js +4 -1
  129. package/dist/schemas/llamacpp-config.d.ts +14 -4
  130. package/dist/schemas/llamacpp-config.js +5 -0
  131. package/dist/schemas/load-model.d.ts +3233 -1260
  132. package/dist/schemas/load-model.js +23 -16
  133. package/dist/schemas/model-src-utils.d.ts +7 -6
  134. package/dist/schemas/model-src-utils.js +27 -1
  135. package/dist/schemas/model-types.d.ts +4 -4
  136. package/dist/schemas/ocr.d.ts +1 -1
  137. package/dist/schemas/plugin.d.ts +27 -3
  138. package/dist/schemas/plugin.js +27 -2
  139. package/dist/schemas/profiling.js +11 -3
  140. package/dist/schemas/provide.d.ts +1 -3
  141. package/dist/schemas/provide.js +0 -3
  142. package/dist/schemas/rag.d.ts +4 -4
  143. package/dist/schemas/registry.d.ts +10 -10
  144. package/dist/schemas/registry.js +36 -14
  145. package/dist/schemas/reload-config.d.ts +73 -7
  146. package/dist/schemas/sdcpp-config.d.ts +16 -8
  147. package/dist/schemas/sdcpp-config.js +118 -25
  148. package/dist/schemas/sdk-config.d.ts +116 -90
  149. package/dist/schemas/sdk-config.js +16 -0
  150. package/dist/schemas/sdk-errors-client.d.ts +3 -0
  151. package/dist/schemas/sdk-errors-client.js +16 -1
  152. package/dist/schemas/sdk-errors-server.d.ts +3 -0
  153. package/dist/schemas/sdk-errors-server.js +23 -0
  154. package/dist/schemas/state.d.ts +23 -0
  155. package/dist/schemas/state.js +14 -0
  156. package/dist/schemas/stop-provide.d.ts +0 -5
  157. package/dist/schemas/stop-provide.js +2 -6
  158. package/dist/schemas/text-to-speech.d.ts +93 -27
  159. package/dist/schemas/text-to-speech.js +27 -0
  160. package/dist/schemas/tools.d.ts +16 -0
  161. package/dist/schemas/tools.js +15 -0
  162. package/dist/schemas/transcription-config.d.ts +8 -8
  163. package/dist/schemas/transcription.d.ts +33 -0
  164. package/dist/schemas/transcription.js +9 -0
  165. package/dist/schemas/translate.js +59 -19
  166. package/dist/schemas/translation-config.d.ts +157 -133
  167. package/dist/schemas/translation-config.js +34 -11
  168. package/dist/server/bare/delegate-rpc-client.d.ts +1 -1
  169. package/dist/server/bare/delegate-rpc-client.js +131 -122
  170. package/dist/server/bare/hyperswarm.d.ts +2 -2
  171. package/dist/server/bare/hyperswarm.js +12 -7
  172. package/dist/server/bare/ops/cancel.js +7 -0
  173. package/dist/server/bare/ops/kv-cache-utils.d.ts +7 -10
  174. package/dist/server/bare/ops/kv-cache-utils.js +31 -40
  175. package/dist/server/bare/ops/load-model.js +0 -1
  176. package/dist/server/bare/ops/transcribe.d.ts +11 -4
  177. package/dist/server/bare/ops/transcribe.js +25 -4
  178. package/dist/server/bare/ops/translate.js +42 -4
  179. package/dist/server/bare/ops/unload-model.js +21 -19
  180. package/dist/server/bare/plugins/llamacpp-completion/ops/cache-logger.js +1 -2
  181. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.d.ts +13 -8
  182. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +257 -85
  183. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.d.ts +101 -0
  184. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.js +135 -0
  185. package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +80 -22
  186. package/dist/server/bare/plugins/llamacpp-completion/plugin.js +57 -32
  187. package/dist/server/bare/plugins/llamacpp-embedding/plugin.js +10 -16
  188. package/dist/server/bare/plugins/nmtcpp-translation/plugin.d.ts +69 -44
  189. package/dist/server/bare/plugins/nmtcpp-translation/plugin.js +54 -116
  190. package/dist/server/bare/plugins/nmtcpp-translation/resolve-vocab.d.ts +32 -0
  191. package/dist/server/bare/plugins/nmtcpp-translation/resolve-vocab.js +117 -0
  192. package/dist/server/bare/plugins/onnx-ocr/plugin.d.ts +1 -1
  193. package/dist/server/bare/plugins/onnx-ocr/plugin.js +1 -2
  194. package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech-stream.d.ts +7 -0
  195. package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech-stream.js +116 -0
  196. package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech.d.ts +2 -3
  197. package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech.js +71 -9
  198. package/dist/server/bare/plugins/onnx-tts/plugin.d.ts +41 -13
  199. package/dist/server/bare/plugins/onnx-tts/plugin.js +48 -3
  200. package/dist/server/bare/plugins/parakeet-transcription/plugin.d.ts +15 -7
  201. package/dist/server/bare/plugins/parakeet-transcription/plugin.js +5 -6
  202. package/dist/server/bare/plugins/sdcpp-generation/ops/diffusion.js +6 -0
  203. package/dist/server/bare/plugins/sdcpp-generation/plugin.d.ts +8 -5
  204. package/dist/server/bare/plugins/sdcpp-generation/plugin.js +13 -13
  205. package/dist/server/bare/plugins/whispercpp-transcription/plugin.d.ts +17 -1
  206. package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +40 -17
  207. package/dist/server/bare/registry/config-registry.js +14 -3
  208. package/dist/server/bare/registry/model-registry.d.ts +8 -10
  209. package/dist/server/bare/registry/model-registry.js +17 -12
  210. package/dist/server/bare/registry/registry-client.js +79 -19
  211. package/dist/server/bare/runtime-lifecycle.d.ts +2 -1
  212. package/dist/server/bare/runtime-lifecycle.js +13 -2
  213. package/dist/server/bare/types/addon-responses.d.ts +8 -3
  214. package/dist/server/bare/utils/transcribe-metadata.d.ts +21 -0
  215. package/dist/server/bare/utils/transcribe-metadata.js +28 -0
  216. package/dist/server/bare/utils/tts-stats.d.ts +22 -0
  217. package/dist/server/bare/utils/tts-stats.js +10 -0
  218. package/dist/server/rpc/create-server.d.ts +4 -1
  219. package/dist/server/rpc/create-server.js +5 -1
  220. package/dist/server/rpc/delegate-transport.js +36 -29
  221. package/dist/server/rpc/handle-request.js +28 -3
  222. package/dist/server/rpc/handler-registry.js +7 -1
  223. package/dist/server/rpc/handler-utils.d.ts +5 -0
  224. package/dist/server/rpc/handler-utils.js +22 -0
  225. package/dist/server/rpc/handlers/cancel-delegated.js +3 -5
  226. package/dist/server/rpc/handlers/cancelHandler.js +4 -5
  227. package/dist/server/rpc/handlers/completion-stream-delegated.js +14 -5
  228. package/dist/server/rpc/handlers/delete-cache.js +8 -3
  229. package/dist/server/rpc/handlers/download-asset.js +3 -24
  230. package/dist/server/rpc/handlers/get-loaded-model-info.d.ts +3 -0
  231. package/dist/server/rpc/handlers/get-loaded-model-info.js +39 -0
  232. package/dist/server/rpc/handlers/get-model-info.js +93 -84
  233. package/dist/server/rpc/handlers/heartbeat-delegated.js +2 -2
  234. package/dist/server/rpc/handlers/index.d.ts +6 -0
  235. package/dist/server/rpc/handlers/index.js +6 -0
  236. package/dist/server/rpc/handlers/load-model/download-manager.d.ts +35 -9
  237. package/dist/server/rpc/handlers/load-model/download-manager.js +142 -38
  238. package/dist/server/rpc/handlers/load-model/download-stats.d.ts +5 -4
  239. package/dist/server/rpc/handlers/load-model/download-stats.js +49 -8
  240. package/dist/server/rpc/handlers/load-model/handler.js +31 -50
  241. package/dist/server/rpc/handlers/load-model/http.d.ts +2 -2
  242. package/dist/server/rpc/handlers/load-model/http.js +97 -142
  243. package/dist/server/rpc/handlers/load-model/hyperdrive.d.ts +2 -2
  244. package/dist/server/rpc/handlers/load-model/hyperdrive.js +55 -74
  245. package/dist/server/rpc/handlers/load-model/index.d.ts +0 -1
  246. package/dist/server/rpc/handlers/load-model/index.js +0 -1
  247. package/dist/server/rpc/handlers/load-model/registry-client-options.d.ts +27 -0
  248. package/dist/server/rpc/handlers/load-model/registry-client-options.js +19 -0
  249. package/dist/server/rpc/handlers/load-model/registry-companion-set.d.ts +22 -0
  250. package/dist/server/rpc/handlers/load-model/registry-companion-set.js +208 -0
  251. package/dist/server/rpc/handlers/load-model/registry-download-utils.d.ts +24 -0
  252. package/dist/server/rpc/handlers/load-model/registry-download-utils.js +114 -0
  253. package/dist/server/rpc/handlers/load-model/registry.d.ts +2 -20
  254. package/dist/server/rpc/handlers/load-model/registry.js +109 -381
  255. package/dist/server/rpc/handlers/load-model/resolve-session.d.ts +15 -0
  256. package/dist/server/rpc/handlers/load-model/resolve-session.js +61 -0
  257. package/dist/server/rpc/handlers/load-model/resolve.d.ts +3 -3
  258. package/dist/server/rpc/handlers/load-model/resolve.js +14 -23
  259. package/dist/server/rpc/handlers/load-model/types.d.ts +11 -4
  260. package/dist/server/rpc/handlers/load-model/types.js +28 -1
  261. package/dist/server/rpc/handlers/load-model-delegated.js +2 -4
  262. package/dist/server/rpc/handlers/plugin-dispatch.js +9 -5
  263. package/dist/server/rpc/handlers/plugin-invoke.js +1 -1
  264. package/dist/server/rpc/handlers/provideHandler/connection.js +13 -2
  265. package/dist/server/rpc/handlers/provideHandler/handler.js +42 -29
  266. package/dist/server/rpc/handlers/state.d.ts +3 -0
  267. package/dist/server/rpc/handlers/state.js +7 -0
  268. package/dist/server/rpc/handlers/stopProvideHandler.d.ts +2 -2
  269. package/dist/server/rpc/handlers/stopProvideHandler.js +12 -7
  270. package/dist/server/rpc/handlers/text-to-speech-stream.d.ts +3 -0
  271. package/dist/server/rpc/handlers/text-to-speech-stream.js +4 -0
  272. package/dist/server/rpc/handlers/unload-model-delegated.js +3 -3
  273. package/dist/server/rpc/profiling/operation-metrics.js +20 -0
  274. package/dist/server/rpc/rpc-utils.js +1 -1
  275. package/dist/server/rpc/transport-selector.d.ts +3 -0
  276. package/dist/server/rpc/transport-selector.js +18 -0
  277. package/dist/server/utils/cache/auto-history.d.ts +4 -0
  278. package/dist/server/utils/cache/auto-history.js +22 -0
  279. package/dist/server/utils/{cache.d.ts → cache/paths.d.ts} +22 -5
  280. package/dist/server/utils/{cache.js → cache/paths.js} +36 -20
  281. package/dist/server/utils/cache/types.d.ts +8 -0
  282. package/dist/server/utils/cache/types.js +1 -0
  283. package/dist/server/utils/checksum.d.ts +2 -2
  284. package/dist/server/utils/checksum.js +1 -1
  285. package/dist/server/utils/clear-storage.d.ts +5 -0
  286. package/dist/server/utils/clear-storage.js +17 -0
  287. package/dist/server/utils/completion-normalizer.d.ts +17 -0
  288. package/dist/server/utils/completion-normalizer.js +413 -0
  289. package/dist/server/utils/expand-gguf-shards.d.ts +3 -0
  290. package/dist/server/utils/expand-gguf-shards.js +22 -0
  291. package/dist/server/utils/formatting.js +1 -1
  292. package/dist/server/utils/index.d.ts +4 -2
  293. package/dist/server/utils/index.js +4 -2
  294. package/dist/server/utils/qvac-paths.d.ts +2 -0
  295. package/dist/server/utils/qvac-paths.js +5 -0
  296. package/dist/server/utils/response-format.d.ts +3 -0
  297. package/dist/server/utils/response-format.js +20 -0
  298. package/dist/server/utils/tool-integration.d.ts +15 -4
  299. package/dist/server/utils/tool-integration.js +21 -41
  300. package/dist/server/utils/tools/dialect.d.ts +8 -0
  301. package/dist/server/utils/tools/dialect.js +14 -0
  302. package/dist/server/utils/tools/index.d.ts +3 -0
  303. package/dist/server/utils/tools/index.js +2 -0
  304. package/dist/server/utils/tools/parser.d.ts +6 -0
  305. package/dist/server/utils/tools/parser.js +46 -0
  306. package/dist/server/utils/tools/parsers/harmony.d.ts +4 -0
  307. package/dist/server/utils/tools/parsers/harmony.js +59 -0
  308. package/dist/server/utils/tools/parsers/hermes.d.ts +4 -0
  309. package/dist/server/utils/tools/parsers/hermes.js +100 -0
  310. package/dist/server/utils/tools/parsers/json.d.ts +6 -0
  311. package/dist/server/utils/tools/parsers/json.js +115 -0
  312. package/dist/server/utils/tools/parsers/pythonic.d.ts +4 -0
  313. package/dist/server/utils/tools/parsers/pythonic.js +267 -0
  314. package/dist/server/utils/tools/shared.d.ts +18 -0
  315. package/dist/server/utils/tools/shared.js +54 -0
  316. package/dist/server/utils/worker-lock.d.ts +3 -0
  317. package/dist/server/utils/worker-lock.js +67 -0
  318. package/dist/server/worker-core.d.ts +16 -1
  319. package/dist/server/worker-core.js +114 -14
  320. package/dist/utils/aggregate-events.d.ts +16 -0
  321. package/dist/utils/aggregate-events.js +52 -0
  322. package/dist/utils/cache-normalize.d.ts +10 -0
  323. package/dist/utils/cache-normalize.js +23 -0
  324. package/dist/utils/encoding.d.ts +8 -0
  325. package/dist/utils/encoding.js +13 -0
  326. package/dist/utils/errors-client.d.ts +12 -0
  327. package/dist/utils/errors-client.js +20 -0
  328. package/dist/utils/errors-server.d.ts +14 -0
  329. package/dist/utils/errors-server.js +31 -0
  330. package/dist/utils/load-model-validation.d.ts +7 -0
  331. package/dist/utils/load-model-validation.js +18 -0
  332. package/expo/plugins/patches/android-link.mjs +1 -1
  333. package/expo/plugins/patches/ios-link.mjs +1 -1
  334. package/package.json +14 -18
  335. package/dist/examples/translation/translation-opus.d.ts +0 -2
  336. package/dist/examples/translation/translation-opus.js +0 -33
  337. package/dist/server/bare/utils/loader-adapter.d.ts +0 -7
  338. package/dist/server/bare/utils/loader-adapter.js +0 -9
  339. package/dist/server/utils/model-path.d.ts +0 -5
  340. package/dist/server/utils/model-path.js +0 -7
  341. package/dist/server/utils/tool-parser.d.ts +0 -7
  342. package/dist/server/utils/tool-parser.js +0 -248
  343. /package/dist/examples/{llamacpp-native-tools.d.ts → tools/llamacpp-native-tools.d.ts} +0 -0
@@ -1,14 +1,22 @@
1
- import { type TranscribeClientParams, type RPCOptions, type TranscribeStreamClientParams, type TranscribeStreamSession } from "../../schemas/index";
1
+ import { type TranscribeClientParams, type RPCOptions, type TranscribeSegment, type TranscribeStreamClientParams, type TranscribeStreamSession, type TranscribeStreamMetadataSession } from "../../schemas/index";
2
2
  /**
3
3
  * Transcribe audio and return the complete text. Accepts either a file
4
4
  * path or an audio buffer.
5
5
  *
6
+ * @param params - Transcription parameters.
6
7
  * @param params.modelId - The identifier of the transcription model to use
7
8
  * @param params.audioChunk - Audio input as either a file path (string) or audio buffer
8
9
  * @param params.prompt - Optional initial prompt to guide the transcription
10
+ * @param params.metadata - When true, resolves to an array of transcript
11
+ * segments (`{ text, startMs, endMs, append, id }`)
12
+ * instead of joined text. Whisper engine only.
9
13
  * @param options - Optional RPC options including per-call profiling
10
- * @returns The complete transcribed text
14
+ * @returns The complete transcribed text, or — when `metadata` is true —
15
+ * the list of transcript segments in emission order.
11
16
  */
17
+ export declare function transcribe(params: TranscribeClientParams & {
18
+ metadata: true;
19
+ }, options?: RPCOptions): Promise<TranscribeSegment[]>;
12
20
  export declare function transcribe(params: TranscribeClientParams, options?: RPCOptions): Promise<string>;
13
21
  /**
14
22
  * @deprecated Pass audio via `transcribe()` instead. This overload will be
@@ -16,7 +24,15 @@ export declare function transcribe(params: TranscribeClientParams, options?: RPC
16
24
  *
17
25
  * Streaming transcription with upfront audio: sends full audio, yields text
18
26
  * chunks as they arrive.
27
+ *
28
+ * @overloadLabel "Upfront audio (deprecated)"
29
+ * @param params - Transcription parameters including audio source.
30
+ * @param options - Optional RPC options including per-call profiling.
31
+ * @returns An async generator yielding text chunks as they become available.
19
32
  */
33
+ export declare function transcribeStream(params: TranscribeClientParams & {
34
+ metadata: true;
35
+ }, options?: RPCOptions): AsyncGenerator<TranscribeSegment>;
20
36
  export declare function transcribeStream(params: TranscribeClientParams, options?: RPCOptions): AsyncGenerator<string>;
21
37
  /**
22
38
  * Opens a bidirectional streaming transcription session. Audio is streamed
@@ -26,11 +42,20 @@ export declare function transcribeStream(params: TranscribeClientParams, options
26
42
  * The returned session is single-use. Attempting to iterate a second
27
43
  * time will throw a `TranscriptionFailedError`.
28
44
  *
45
+ * @overloadLabel "Bidirectional session"
46
+ * @param params - Streaming transcription parameters.
29
47
  * @param params.modelId - The loaded transcription model to use
30
48
  * @param params.prompt - Optional initial prompt to guide transcription
49
+ * @param params.metadata - When true, the session yields transcript segment
50
+ * objects (`{ text, startMs, endMs, append, id }`)
51
+ * instead of plain text. Whisper engine only.
52
+ * @param options - Optional RPC options including per-call profiling.
31
53
  * @returns A session object: call `write(buffer)` to feed audio,
32
- * iterate with `for await (const text of session)` to receive
33
- * transcription, and `end()` to signal end of audio.
54
+ * iterate with `for await (...)` to receive transcription,
55
+ * and `end()` to signal end of audio.
34
56
  */
57
+ export declare function transcribeStream(params: TranscribeStreamClientParams & {
58
+ metadata: true;
59
+ }, options?: RPCOptions): Promise<TranscribeStreamMetadataSession>;
35
60
  export declare function transcribeStream(params: TranscribeStreamClientParams, options?: RPCOptions): Promise<TranscribeStreamSession>;
36
61
  //# sourceMappingURL=transcribe.d.ts.map
@@ -11,20 +11,26 @@ function buildTranscribeRequest(params) {
11
11
  ? { type: "filePath", value: params.audioChunk }
12
12
  : { type: "base64", value: params.audioChunk.toString("base64") },
13
13
  ...(params.prompt && { prompt: params.prompt }),
14
+ ...(params.metadata === true && { metadata: true }),
14
15
  };
15
16
  }
16
- /**
17
- * Transcribe audio and return the complete text. Accepts either a file
18
- * path or an audio buffer.
19
- *
20
- * @param params.modelId - The identifier of the transcription model to use
21
- * @param params.audioChunk - Audio input as either a file path (string) or audio buffer
22
- * @param params.prompt - Optional initial prompt to guide the transcription
23
- * @param options - Optional RPC options including per-call profiling
24
- * @returns The complete transcribed text
25
- */
26
17
  export async function transcribe(params, options) {
27
18
  const request = buildTranscribeRequest(params);
19
+ if (params.metadata === true) {
20
+ const segments = [];
21
+ for await (const response of stream(request, options)) {
22
+ if (response.type === "transcribe") {
23
+ const parsed = transcribeResponseSchema.parse(response);
24
+ if (parsed.segment) {
25
+ segments.push(parsed.segment);
26
+ }
27
+ if (parsed.done) {
28
+ break;
29
+ }
30
+ }
31
+ }
32
+ return segments;
33
+ }
28
34
  let fullText = "";
29
35
  for await (const response of stream(request, options)) {
30
36
  if (response.type === "transcribe") {
@@ -42,30 +48,57 @@ export async function transcribe(params, options) {
42
48
  export function transcribeStream(params, options) {
43
49
  if ("audioChunk" in params && params.audioChunk !== undefined) {
44
50
  logger.warn("transcribeStream() with audioChunk is deprecated — use transcribe() instead.");
51
+ if (params.metadata === true) {
52
+ return transcribeStreamWithAudioMetadata(params, options);
53
+ }
45
54
  return transcribeStreamWithAudio(params, options);
46
55
  }
47
- return transcribeStreamDuplex(params, options);
56
+ const streamParams = params;
57
+ if (streamParams.metadata === true) {
58
+ return transcribeStreamDuplexMetadata(streamParams, options);
59
+ }
60
+ return transcribeStreamDuplex(streamParams, options);
48
61
  }
49
- async function* transcribeStreamWithAudio(params, options) {
62
+ /**
63
+ * Streams `transcribe` wire responses for an upfront-audio request and yields
64
+ * the value extracted from each response frame until `done` is seen.
65
+ */
66
+ async function* streamTranscribeValues(params, options, extract) {
50
67
  const request = buildTranscribeRequest(params);
51
68
  for await (const response of stream(request, options)) {
52
69
  if (response.type === "transcribe") {
53
70
  const parsed = transcribeResponseSchema.parse(response);
54
- if (parsed.text)
55
- yield parsed.text;
71
+ const value = extract(parsed);
72
+ if (value !== undefined)
73
+ yield value;
56
74
  if (parsed.done)
57
75
  break;
58
76
  }
59
77
  }
60
78
  }
61
- async function transcribeStreamDuplex(params, options) {
62
- const request = {
79
+ function transcribeStreamWithAudio(params, options) {
80
+ return streamTranscribeValues(params, options, (parsed) => parsed.text ? parsed.text : undefined);
81
+ }
82
+ function transcribeStreamWithAudioMetadata(params, options) {
83
+ return streamTranscribeValues(params, options, (parsed) => parsed.segment);
84
+ }
85
+ function buildTranscribeStreamRequest(params) {
86
+ return {
63
87
  type: "transcribeStream",
64
88
  modelId: params.modelId,
65
89
  ...(params.prompt && { prompt: params.prompt }),
90
+ ...(params.metadata === true && { metadata: true }),
66
91
  };
92
+ }
93
+ /**
94
+ * Shared duplex session factory. The per-call line processor decides whether
95
+ * to surface strings or segments; `sessionName` is only used to label the
96
+ * "already iterated" error so callers see the correct session type.
97
+ */
98
+ async function createTranscribeStreamSession(params, options, process, sessionName) {
99
+ const request = buildTranscribeStreamRequest(params);
67
100
  const { requestStream, responseStream } = await duplex(request, options);
68
- const responses = parseResponseLines(responseStream);
101
+ const responses = parseLines(responseStream, process);
69
102
  let consumed = false;
70
103
  return {
71
104
  write(audioChunk) {
@@ -80,21 +113,32 @@ async function transcribeStreamDuplex(params, options) {
80
113
  },
81
114
  [Symbol.asyncIterator]() {
82
115
  if (consumed) {
83
- throw new TranscriptionFailedError("TranscribeStreamSession can only be iterated once");
116
+ throw new TranscriptionFailedError(`${sessionName} can only be iterated once`);
84
117
  }
85
118
  consumed = true;
86
119
  return responses;
87
120
  },
88
121
  };
89
122
  }
90
- async function* parseResponseLines(responseStream) {
123
+ function transcribeStreamDuplex(params, options) {
124
+ return createTranscribeStreamSession(params, options, processLine, "TranscribeStreamSession");
125
+ }
126
+ function transcribeStreamDuplexMetadata(params, options) {
127
+ return createTranscribeStreamSession(params, options, processLineMetadata, "TranscribeStreamMetadataSession");
128
+ }
129
+ /**
130
+ * Line-delimited parser: reads newline-separated frames from a duplex
131
+ * response stream, passes each non-empty line through `process`, and yields
132
+ * whatever values it returns. `null` from `process` terminates the stream.
133
+ */
134
+ async function* parseLines(responseStream, process) {
91
135
  let buf = "";
92
136
  for await (const chunk of responseStream) {
93
137
  buf += chunk.toString();
94
138
  const lines = buf.split("\n");
95
139
  buf = lines.pop() || "";
96
140
  for (const line of lines) {
97
- const result = processLine(line);
141
+ const result = process(line);
98
142
  if (result === null)
99
143
  return;
100
144
  if (result !== undefined)
@@ -103,32 +147,46 @@ async function* parseResponseLines(responseStream) {
103
147
  }
104
148
  // Process any residual data after stream ends
105
149
  if (buf.trim()) {
106
- const result = processLine(buf);
150
+ const result = process(buf);
107
151
  if (result !== null && result !== undefined)
108
152
  yield result;
109
153
  }
110
154
  }
111
- function processLine(line) {
155
+ function parseResponseLine(line) {
112
156
  if (!line.trim())
113
- return undefined;
157
+ return null;
114
158
  let parsed;
115
159
  try {
116
160
  parsed = JSON.parse(line);
117
161
  }
118
162
  catch {
119
163
  logger.warn("transcribeStream: malformed JSON from server:", line);
120
- return undefined;
164
+ return null;
121
165
  }
122
166
  const obj = parsed;
123
167
  if (obj["type"] === "error") {
124
168
  throw new TranscriptionFailedError(obj["message"] ?? "Unknown server error");
125
169
  }
126
- const response = transcribeStreamResponseSchema.parse(parsed);
170
+ return transcribeStreamResponseSchema.parse(parsed);
171
+ }
172
+ /**
173
+ * Shared wire-frame decoder. Returns `null` for the terminal `done` frame,
174
+ * `undefined` for frames the caller should skip, or the value extracted from
175
+ * the frame.
176
+ */
177
+ function processWith(line, extract) {
178
+ const response = parseResponseLine(line);
179
+ if (response === null)
180
+ return undefined;
127
181
  if (response.error)
128
182
  throw new TranscriptionFailedError(response.error);
129
183
  if (response.done)
130
184
  return null;
131
- if (response.text?.trim())
132
- return response.text;
133
- return undefined;
185
+ return extract(response);
186
+ }
187
+ function processLine(line) {
188
+ return processWith(line, (response) => response.text?.trim() ? response.text : undefined);
189
+ }
190
+ function processLineMetadata(line) {
191
+ return processWith(line, (response) => response.segment);
134
192
  }
@@ -9,6 +9,7 @@ import { type TranslateClientParams, type TranslationStats, type RPCOptions } fr
9
9
  * @param params.from - Source language code (optional)
10
10
  * @param params.to - Target language code
11
11
  * @param params.stream - Whether to stream tokens (true) or return complete response (false). Defaults to true.
12
+ * @param options - Optional RPC options (timeout, profiling, force new connection, etc.).
12
13
  * @returns Object with tokenStream generator and text/stats properties
13
14
  * @throws {QvacErrorBase} When translation fails with an error message or when language detection fails
14
15
  * @example
@@ -12,6 +12,7 @@ import { TranslationFailedError } from "../../utils/errors-client.js";
12
12
  * @param params.from - Source language code (optional)
13
13
  * @param params.to - Target language code
14
14
  * @param params.stream - Whether to stream tokens (true) or return complete response (false). Defaults to true.
15
+ * @param options - Optional RPC options (timeout, profiling, force new connection, etc.).
15
16
  * @returns Object with tokenStream generator and text/stats properties
16
17
  * @throws {QvacErrorBase} When translation fails with an error message or when language detection fails
17
18
  * @example
@@ -11,7 +11,8 @@ import { resolveModelConfig } from "../../server/bare/registry/model-config-regi
11
11
  import { resolveConfig } from "../config-loader/resolve-config.bare.js";
12
12
  import { getClientLogger } from "../../logging/index.js";
13
13
  import { getAllPlugins } from "../../server/plugins/index.js";
14
- import { initializeWorkerCore, shutdownBareDirectWorker, } from "../../server/worker-core.js";
14
+ import { initializeWorkerCore, shutdownBareDirectWorker, cleanupForTerminate, } from "../../server/worker-core.js";
15
+ import { assertLifecycleAllowed } from "../../server/bare/runtime-lifecycle.js";
15
16
  const logger = getClientLogger();
16
17
  /**
17
18
  * Load worker entry to register plugins before any SDK calls.
@@ -101,6 +102,7 @@ async function* streamWithProgress(request, handler) {
101
102
  }
102
103
  }
103
104
  export async function send(request) {
105
+ assertLifecycleAllowed(request);
104
106
  const handler = getHandler(request.type);
105
107
  if (!handler)
106
108
  throw new RPCNoHandlerError(request.type);
@@ -108,6 +110,7 @@ export async function send(request) {
108
110
  return (await handler(processedRequest));
109
111
  }
110
112
  async function* stream(request) {
113
+ assertLifecycleAllowed(request);
111
114
  const handler = getHandler(request.type);
112
115
  if (!handler)
113
116
  throw new RPCNoHandlerError(request.type);
@@ -160,6 +163,23 @@ function createMockRPCRequest() {
160
163
  }));
161
164
  }
162
165
  }
166
+ // Handle special pre-terminate cleanup signal. In direct mode the
167
+ // bare runtime is the host JS context, so we run cleanup but never
168
+ // exit the process here.
169
+ if (typeof requestData === "object" &&
170
+ "type" in requestData &&
171
+ requestData.type === "__shutdown__") {
172
+ try {
173
+ await cleanupForTerminate();
174
+ return Buffer.from(JSON.stringify({ success: true }));
175
+ }
176
+ catch (error) {
177
+ return Buffer.from(JSON.stringify({
178
+ success: false,
179
+ error: error instanceof Error ? error.message : String(error),
180
+ }));
181
+ }
182
+ }
163
183
  const response = await send(requestData);
164
184
  return Buffer.from(JSON.stringify(response));
165
185
  },
@@ -203,6 +223,7 @@ export async function createDuplexSession(payload, _commandId) {
203
223
  await getRPC();
204
224
  const { PassThrough } = await import("bare-stream");
205
225
  const request = JSON.parse(payload);
226
+ assertLifecycleAllowed(request);
206
227
  const entry = registry[request.type];
207
228
  if (!entry || entry.type !== "duplex") {
208
229
  throw new RPCNoHandlerError(request.type);
@@ -1,6 +1,6 @@
1
1
  import RPC from "bare-rpc";
2
2
  export declare function getRPC(): Promise<RPC>;
3
- export declare function close(): void;
3
+ export declare function close(): Promise<void>;
4
4
  export declare function createDuplexSession(payload: string, commandId: number): Promise<{
5
5
  requestStream: RPC.OutgoingStream;
6
6
  responseStream: RPC.IncomingStream;
@@ -10,6 +10,10 @@ let rpcPromise = null;
10
10
  let workletInstance = null;
11
11
  let workletInitialized = false;
12
12
  let cachedRuntimeContext;
13
+ // Set while close() is in flight. Concurrent callers share the same
14
+ // promise instead of double-sending __shutdown__ or re-entering the
15
+ // terminate block on already-null state.
16
+ let closingPromise = null;
13
17
  logger.debug("EXPO RPC Client bundle");
14
18
  async function getRuntimeContext() {
15
19
  if (cachedRuntimeContext) {
@@ -93,10 +97,98 @@ export async function getRPC() {
93
97
  rpcPromise = null;
94
98
  }
95
99
  }
96
- export function close() {
97
- logger.info("🧹 Closing RPC client (Expo)");
98
- rpcInstance = null;
99
- rpcPromise = null;
100
+ const SHUTDOWN_RPC_TIMEOUT_MS = 10_000;
101
+ /**
102
+ * Pre-terminate cleanup roundtrip. Sends an internal `__shutdown__` message
103
+ * to the worker so it can clear addon plugin registries (calls each addon's
104
+ * `releaseLogger` → frees env-bound js_ref_t state) and unload all model
105
+ * instances BEFORE we kill the worklet.
106
+ *
107
+ * Without this, the worklet's V8 isolate dies while addon static state still
108
+ * holds js_ref_t handles into it; the next worklet's first `setLogger` call
109
+ * trips a V8 GlobalHandle assertion (brk 0 / SIGTRAP) and the iOS app dies.
110
+ *
111
+ * Best-effort: never throws. Falls through to terminate even on timeout.
112
+ */
113
+ async function sendShutdownMessage(rpc) {
114
+ let timer;
115
+ try {
116
+ await Promise.race([
117
+ (async () => {
118
+ const req = rpc.request(1);
119
+ req.send(JSON.stringify({ type: "__shutdown__" }), "utf8");
120
+ const response = await req.reply("utf8");
121
+ const parsed = JSON.parse(String(response));
122
+ if (!parsed.success) {
123
+ throw new Error(parsed.error ?? "Worker reported cleanup failure");
124
+ }
125
+ })(),
126
+ new Promise((_, reject) => {
127
+ timer = setTimeout(() => reject(new Error(`Worker did not ack __shutdown__ within ${SHUTDOWN_RPC_TIMEOUT_MS}ms`)), SHUTDOWN_RPC_TIMEOUT_MS);
128
+ }),
129
+ ]);
130
+ }
131
+ catch (error) {
132
+ // Best-effort: log but don't block termination if cleanup fails.
133
+ logger.warn(`⚠️ Pre-terminate worker cleanup failed: ${error instanceof Error ? error.message : String(error)}`);
134
+ }
135
+ finally {
136
+ if (timer)
137
+ clearTimeout(timer);
138
+ }
139
+ }
140
+ export async function close() {
141
+ // Concurrent callers (or a getRPC retry that overlaps with a manual
142
+ // close) share the in-flight close promise instead of each sending
143
+ // their own __shutdown__ and racing on the terminate block.
144
+ if (closingPromise)
145
+ return closingPromise;
146
+ closingPromise = (async () => {
147
+ logger.info("🧹 Closing RPC client (Expo)");
148
+ // terminate() crashes on Android (addon dlclose leaves pthread_key_t
149
+ // destructors dangling); iOS dyld no-ops dlclose so it's safe there.
150
+ // Non-iOS: drop refs only -- sending __shutdown__ without a follow-up
151
+ // terminate would clear the worker plugin registry.
152
+ let platform;
153
+ try {
154
+ platform = (await getRuntimeContext()).platform;
155
+ }
156
+ catch (err) {
157
+ logger.debug("Failed to resolve runtime context for close()", { err });
158
+ }
159
+ if (platform !== "ios") {
160
+ rpcInstance = null;
161
+ rpcPromise = null;
162
+ return;
163
+ }
164
+ // iOS: existing pre-terminate cleanup + terminate.
165
+ if (rpcInstance) {
166
+ logger.info("🧹 Requesting worker pre-terminate cleanup");
167
+ await sendShutdownMessage(rpcInstance);
168
+ }
169
+ rpcInstance = null;
170
+ rpcPromise = null;
171
+ if (workletInstance) {
172
+ logger.info("🐻🔫 Terminating bare worklet");
173
+ try {
174
+ workletInstance.terminate();
175
+ }
176
+ catch (error) {
177
+ logger.debug("Failed to terminate worklet", { error });
178
+ }
179
+ workletInstance = null;
180
+ workletInitialized = false;
181
+ }
182
+ })();
183
+ try {
184
+ await closingPromise;
185
+ }
186
+ finally {
187
+ // Reset so a subsequent close() (e.g. after a fresh getRPC spawned
188
+ // a new worklet) can run again. Body guards on rpcInstance / workletInstance
189
+ // make a redundant call a no-op if state is already cleared.
190
+ closingPromise = null;
191
+ }
100
192
  }
101
193
  export async function createDuplexSession(payload, commandId) {
102
194
  const rpc = await getRPC();
@@ -10,6 +10,8 @@ import { fileURLToPath } from "node:url";
10
10
  import { initializeConfig } from "../init-hooks.js";
11
11
  import { resolveConfig } from "../config-loader/resolve-config.node.js";
12
12
  import { getClientLogger } from "../../logging/index.js";
13
+ import { RPCInitTimeoutError } from "../../utils/errors-client.js";
14
+ const RPC_INIT_TIMEOUT_MS = 30_000;
13
15
  const logger = getClientLogger();
14
16
  const __filename = fileURLToPath(import.meta.url);
15
17
  const __dirname = path.dirname(__filename);
@@ -168,11 +170,31 @@ async function ensureRPC() {
168
170
  const socketPath = createSocketPath();
169
171
  currentSocketPath = socketPath;
170
172
  rpcPromise = new Promise((resolve, reject) => {
173
+ let settled = false;
174
+ const timer = setTimeout(() => {
175
+ if (settled)
176
+ return;
177
+ settled = true;
178
+ rpcPromise = null;
179
+ rpcInstance = null;
180
+ bareWorkerProc = null;
181
+ ipcServer = null;
182
+ currentSocketPath = null;
183
+ reject(new RPCInitTimeoutError(RPC_INIT_TIMEOUT_MS));
184
+ }, RPC_INIT_TIMEOUT_MS);
171
185
  ipcServer = createServer((socket) => {
186
+ if (settled)
187
+ return;
188
+ settled = true;
189
+ clearTimeout(timer);
172
190
  rpcInstance = new RPC(socket, () => { });
173
191
  resolve(rpcInstance);
174
192
  });
175
193
  ipcServer.on("error", (error) => {
194
+ if (settled)
195
+ return;
196
+ settled = true;
197
+ clearTimeout(timer);
176
198
  rpcPromise = null;
177
199
  rpcInstance = null;
178
200
  bareWorkerProc = null;
@@ -191,6 +213,20 @@ async function ensureRPC() {
191
213
  ],
192
214
  stdio: ["inherit", "inherit", "inherit"],
193
215
  });
216
+ if (bareWorkerProc) {
217
+ bareWorkerProc.on("exit", (code) => {
218
+ if (settled)
219
+ return;
220
+ settled = true;
221
+ clearTimeout(timer);
222
+ rpcPromise = null;
223
+ rpcInstance = null;
224
+ bareWorkerProc = null;
225
+ ipcServer = null;
226
+ currentSocketPath = null;
227
+ reject(new RPCInitTimeoutError(RPC_INIT_TIMEOUT_MS, new Error(`Worker process exited with code ${code} before IPC connection was established`)));
228
+ });
229
+ }
194
230
  });
195
231
  });
196
232
  const rpc = await rpcPromise;
@@ -0,0 +1,9 @@
1
+ export type MicFormat = "f32le" | "s16le";
2
+ export declare function listWindowsAudioDevices(): string[];
3
+ export declare function getAudioInputArgs(): string[];
4
+ export interface StartMicrophoneOptions {
5
+ sampleRate: number;
6
+ format: MicFormat;
7
+ }
8
+ export declare function startMicrophone(options: StartMicrophoneOptions): import("child_process").ChildProcessByStdio<null, import("stream").Readable, null>;
9
+ //# sourceMappingURL=mic-input.d.ts.map
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Shared microphone-capture helpers for the transcription and
3
+ * voice-assistant examples. Wraps ffmpeg so the examples don't each
4
+ * re-implement device selection.
5
+ *
6
+ * The default device is the system default mic. Override on any OS
7
+ * with the MIC_DEVICE environment variable. On Windows, if no override
8
+ * is set, the first DirectShow audio device reported by ffmpeg is used.
9
+ */
10
+ import { spawn, spawnSync } from "child_process";
11
+ import { platform } from "os";
12
+ // Parses the DirectShow audio device list printed by:
13
+ // ffmpeg -hide_banner -f dshow -list_devices true -i dummy
14
+ // Output goes to stderr; ffmpeg always exits non-zero because `-i dummy`
15
+ // isn't a real device — that's expected.
16
+ //
17
+ // Handles both ffmpeg output formats:
18
+ //
19
+ // Old (ffmpeg ≤ 4.3):
20
+ // [dshow @ ...] DirectShow audio devices
21
+ // [dshow @ ...] "Microphone (Realtek Audio)"
22
+ // [dshow @ ...] Alternative name "@device_cm_..."
23
+ //
24
+ // New (ffmpeg ≥ 4.4):
25
+ // [dshow @ ...] "Integrated Camera" (video)
26
+ // [dshow @ ...] Alternative name "@device_pnp_..."
27
+ // [dshow @ ...] "Microphone (Realtek Audio)" (audio)
28
+ // [dshow @ ...] Alternative name "@device_cm_..."
29
+ //
30
+ // The newer format dropped the "DirectShow audio devices" header and tags
31
+ // each device line with `(audio)` or `(video)` instead.
32
+ export function listWindowsAudioDevices() {
33
+ const result = spawnSync("ffmpeg", ["-hide_banner", "-f", "dshow", "-list_devices", "true", "-i", "dummy"], { encoding: "utf8" });
34
+ const stderr = result.stderr ?? "";
35
+ const devices = [];
36
+ let section = null;
37
+ for (const line of stderr.split(/\r?\n/)) {
38
+ // Old-format section headers.
39
+ if (line.includes("DirectShow audio devices")) {
40
+ section = "audio";
41
+ continue;
42
+ }
43
+ if (line.includes("DirectShow video devices")) {
44
+ section = "video";
45
+ continue;
46
+ }
47
+ // New-format per-line tag wins over the section state.
48
+ const hasAudioTag = /\(audio\)/.test(line);
49
+ const hasVideoTag = /\(video\)/.test(line);
50
+ const lineSection = hasAudioTag ? "audio" : hasVideoTag ? "video" : section;
51
+ if (lineSection !== "audio")
52
+ continue;
53
+ // First quoted token is the device name. Alternative-name lines start
54
+ // with `@device_...` and are filtered out.
55
+ const match = line.match(/"([^"]+)"/);
56
+ if (!match)
57
+ continue;
58
+ const name = match[1];
59
+ if (!name || name.startsWith("@device"))
60
+ continue;
61
+ devices.push(name);
62
+ }
63
+ return devices;
64
+ }
65
+ export function getAudioInputArgs() {
66
+ const env = process.env;
67
+ const override = env["MIC_DEVICE"];
68
+ switch (platform()) {
69
+ case "darwin":
70
+ // AVFoundation device spec is `<video>:<audio>`. `:0` = default audio.
71
+ // Override with e.g. MIC_DEVICE=":1" to pick another device, or run
72
+ // `ffmpeg -f avfoundation -list_devices true -i ""` to enumerate.
73
+ return ["-f", "avfoundation", "-i", override ?? ":0"];
74
+ case "linux":
75
+ // PulseAudio source name. `default` follows the system default mic.
76
+ // Override with MIC_DEVICE="alsa_input.pci-..." etc.; list with
77
+ // `pactl list short sources`.
78
+ return ["-f", "pulse", "-i", override ?? "default"];
79
+ case "win32": {
80
+ if (override)
81
+ return ["-f", "dshow", "-i", `audio=${override}`];
82
+ const devices = listWindowsAudioDevices();
83
+ const deviceName = devices[0];
84
+ if (!deviceName) {
85
+ throw new Error("No Windows audio input device found. List devices with:\n" +
86
+ " ffmpeg -hide_banner -f dshow -list_devices true -i dummy\n" +
87
+ 'Then set MIC_DEVICE="Your Device Name" and retry.');
88
+ }
89
+ return ["-f", "dshow", "-i", `audio=${deviceName}`];
90
+ }
91
+ default:
92
+ throw new Error(`Unsupported platform: ${platform()}`);
93
+ }
94
+ }
95
+ export function startMicrophone(options) {
96
+ const formatArgs = options.format === "f32le"
97
+ ? ["-sample_fmt", "flt", "-f", "f32le"]
98
+ : ["-sample_fmt", "s16", "-f", "s16le"];
99
+ const ffmpeg = spawn("ffmpeg", [
100
+ ...getAudioInputArgs(),
101
+ "-ar",
102
+ String(options.sampleRate),
103
+ "-ac",
104
+ "1",
105
+ ...formatArgs,
106
+ "pipe:1",
107
+ ], { stdio: ["ignore", "pipe", "ignore"] });
108
+ if (!ffmpeg.stdout)
109
+ throw new Error("Failed to open microphone");
110
+ return ffmpeg;
111
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Event-driven completion — demonstrates the unified `CompletionEvent` stream.
3
+ *
4
+ * `completion()` returns a `CompletionRun` with two primary surfaces:
5
+ *
6
+ * - `events` — an `AsyncIterable<CompletionEvent>` of ordered, typed events
7
+ * (`contentDelta`, `thinkingDelta`, `toolCall`, `toolError`,
8
+ * `completionStats`, `completionDone`, `rawDelta`).
9
+ * - `final` — a `Promise<CompletionFinal>` that resolves once the stream
10
+ * ends, providing aggregated `contentText`, `thinkingText`,
11
+ * `toolCalls`, `stats`, and `raw.fullText`.
12
+ *
13
+ * Set `captureThinking: true` to attempt best-effort `<think>` block parsing
14
+ * into dedicated `thinkingDelta` events. `final.raw.fullText` keeps the exact
15
+ * model output.
16
+ */
17
+ export {};
18
+ //# sourceMappingURL=completion-events.d.ts.map