@qvac/sdk 0.11.0 → 0.12.0

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 (205) hide show
  1. package/NOTICE +1427 -39
  2. package/README.md +2 -0
  3. package/dist/client/api/classify.d.ts +23 -0
  4. package/dist/client/api/classify.js +43 -0
  5. package/dist/client/api/get-model-info.d.ts +1 -1
  6. package/dist/client/api/index.d.ts +4 -0
  7. package/dist/client/api/index.js +4 -0
  8. package/dist/client/api/load-model.js +24 -1
  9. package/dist/client/api/transcribe.d.ts +3 -0
  10. package/dist/client/api/transcribe.js +13 -2
  11. package/dist/client/api/video.d.ts +64 -0
  12. package/dist/client/api/video.js +147 -0
  13. package/dist/client/api/vla-helpers.d.ts +45 -0
  14. package/dist/client/api/vla-helpers.js +130 -0
  15. package/dist/client/api/vla.d.ts +65 -0
  16. package/dist/client/api/vla.js +109 -0
  17. package/dist/client/config-loader/resolve-config.node.d.ts +16 -0
  18. package/dist/client/config-loader/resolve-config.node.js +77 -23
  19. package/dist/client/plugins-factory.d.ts +8 -0
  20. package/dist/client/plugins-factory.js +10 -0
  21. package/dist/client/rpc/bare-client.js +62 -66
  22. package/dist/client/rpc/ensure-worker-ready.d.ts +9 -0
  23. package/dist/client/rpc/ensure-worker-ready.js +17 -0
  24. package/dist/client/rpc/node-rpc-client.js +4 -1
  25. package/dist/client/rpc/rpc-error.js +14 -1
  26. package/dist/commands/bundle/bare-pack.d.ts +13 -0
  27. package/dist/commands/bundle/bare-pack.js +54 -0
  28. package/dist/commands/bundle/constants.d.ts +7 -0
  29. package/dist/commands/bundle/constants.js +23 -0
  30. package/dist/commands/bundle/entry-gen.d.ts +2 -0
  31. package/dist/commands/bundle/entry-gen.js +48 -0
  32. package/dist/commands/bundle/index.d.ts +20 -0
  33. package/dist/commands/bundle/index.js +141 -0
  34. package/dist/commands/bundle/manifest.d.ts +21 -0
  35. package/dist/commands/bundle/manifest.js +193 -0
  36. package/dist/commands/bundle/plugins.d.ts +9 -0
  37. package/dist/commands/bundle/plugins.js +51 -0
  38. package/dist/commands/index.d.ts +5 -0
  39. package/dist/commands/index.js +2 -0
  40. package/dist/commands/verify/abi.d.ts +52 -0
  41. package/dist/commands/verify/abi.js +125 -0
  42. package/dist/commands/verify/addon-source.d.ts +43 -0
  43. package/dist/commands/verify/addon-source.js +75 -0
  44. package/dist/commands/verify/bundle-source.d.ts +12 -0
  45. package/dist/commands/verify/bundle-source.js +53 -0
  46. package/dist/commands/verify/index.d.ts +59 -0
  47. package/dist/commands/verify/index.js +371 -0
  48. package/dist/commands/verify/node-modules-source.d.ts +11 -0
  49. package/dist/commands/verify/node-modules-source.js +76 -0
  50. package/dist/commands/verify/prebuilds.d.ts +15 -0
  51. package/dist/commands/verify/prebuilds.js +39 -0
  52. package/dist/examples/classification/classify-image.d.ts +2 -0
  53. package/dist/examples/classification/classify-image.js +23 -0
  54. package/dist/examples/diffusion-txt2vid.d.ts +2 -0
  55. package/dist/examples/diffusion-txt2vid.js +81 -0
  56. package/dist/examples/plugins.js +3 -7
  57. package/dist/examples/tools/llamacpp-tools-gemma4.js +2 -5
  58. package/dist/examples/tools/llamacpp-tools-qwen35.js +2 -3
  59. package/dist/examples/transcription/parakeet-ctc-filesystem.js +18 -12
  60. package/dist/examples/transcription/parakeet-microphone-record.js +7 -12
  61. package/dist/examples/transcription/parakeet-microphone-stream.d.ts +2 -0
  62. package/dist/examples/transcription/parakeet-microphone-stream.js +79 -0
  63. package/dist/examples/transcription/parakeet-sortformer-streaming.d.ts +2 -0
  64. package/dist/examples/transcription/parakeet-sortformer-streaming.js +121 -0
  65. package/dist/examples/transcription/parakeet-sortformer.js +58 -55
  66. package/dist/examples/transcription/parakeet-tdt-filesystem.js +18 -15
  67. package/dist/examples/transcription/whispercpp-microphone-conversation.js +6 -1
  68. package/dist/examples/tts/chatterbox.js +7 -16
  69. package/dist/examples/tts/llm-to-tts-streaming.js +3 -10
  70. package/dist/examples/tts/supertonic-multilingual.js +4 -12
  71. package/dist/examples/tts/supertonic.js +5 -12
  72. package/dist/examples/vla-smolvla.d.ts +2 -0
  73. package/dist/examples/vla-smolvla.js +75 -0
  74. package/dist/examples/voice-assistant/voice-assistant.js +3 -10
  75. package/dist/expo/plugins/find-in-ancestor-node-modules.d.ts +14 -0
  76. package/dist/expo/plugins/find-in-ancestor-node-modules.js +24 -0
  77. package/dist/expo/plugins/get-project-root.d.ts +22 -0
  78. package/dist/expo/plugins/get-project-root.js +23 -0
  79. package/dist/expo/plugins/index.d.ts +4 -0
  80. package/dist/expo/plugins/index.js +4 -0
  81. package/dist/expo/plugins/resolve-sdk-package-dir.d.ts +9 -2
  82. package/dist/expo/plugins/resolve-sdk-package-dir.js +38 -11
  83. package/dist/expo/plugins/withDeviceInfo.js +2 -1
  84. package/dist/expo/plugins/withMobileBundle.d.ts +2 -17
  85. package/dist/expo/plugins/withMobileBundle.js +31 -85
  86. package/dist/index.d.ts +4 -3
  87. package/dist/index.js +4 -3
  88. package/dist/models/registry/models.d.ts +3711 -368
  89. package/dist/models/registry/models.js +7066 -3562
  90. package/dist/models/update-models/naming.js +22 -8
  91. package/dist/pear/pre.js +6 -2
  92. package/dist/schemas/cancel.d.ts +5 -0
  93. package/dist/schemas/cancel.js +1 -0
  94. package/dist/schemas/classification.d.ts +53 -0
  95. package/dist/schemas/classification.js +33 -0
  96. package/dist/schemas/common.d.ts +1001 -1739
  97. package/dist/schemas/common.js +6 -1
  98. package/dist/schemas/completion-event.d.ts +3 -0
  99. package/dist/schemas/completion-event.js +1 -0
  100. package/dist/schemas/completion-stream.d.ts +1 -0
  101. package/dist/schemas/download-asset.d.ts +13 -3
  102. package/dist/schemas/engine-addon-map.d.ts +3 -0
  103. package/dist/schemas/engine-addon-map.js +18 -5
  104. package/dist/schemas/get-model-info.d.ts +4 -0
  105. package/dist/schemas/get-model-info.js +2 -0
  106. package/dist/schemas/index.d.ts +3 -0
  107. package/dist/schemas/index.js +3 -0
  108. package/dist/schemas/llamacpp-config.d.ts +12 -2
  109. package/dist/schemas/load-model.d.ts +6152 -10764
  110. package/dist/schemas/load-model.js +75 -7
  111. package/dist/schemas/model-src-utils.d.ts +22 -2
  112. package/dist/schemas/model-types.d.ts +46 -6
  113. package/dist/schemas/model-types.js +28 -5
  114. package/dist/schemas/ocr.d.ts +5 -0
  115. package/dist/schemas/plugin.d.ts +20 -5
  116. package/dist/schemas/plugin.js +21 -4
  117. package/dist/schemas/registry.d.ts +44 -0
  118. package/dist/schemas/registry.js +5 -0
  119. package/dist/schemas/reload-config.d.ts +22 -2
  120. package/dist/schemas/sdcpp-config.d.ts +316 -1
  121. package/dist/schemas/sdcpp-config.js +232 -33
  122. package/dist/schemas/sdk-config.d.ts +654 -1324
  123. package/dist/schemas/sdk-config.js +16 -1
  124. package/dist/schemas/sdk-errors-client.d.ts +5 -0
  125. package/dist/schemas/sdk-errors-client.js +26 -1
  126. package/dist/schemas/sdk-errors-server.d.ts +3 -1
  127. package/dist/schemas/sdk-errors-server.js +20 -5
  128. package/dist/schemas/text-to-speech.d.ts +79 -696
  129. package/dist/schemas/text-to-speech.js +46 -19
  130. package/dist/schemas/transcription-config.d.ts +37 -226
  131. package/dist/schemas/transcription-config.js +76 -15
  132. package/dist/schemas/transcription.d.ts +63 -11
  133. package/dist/schemas/transcription.js +56 -2
  134. package/dist/schemas/translation-config.d.ts +60 -10
  135. package/dist/schemas/vla.d.ts +87 -0
  136. package/dist/schemas/vla.js +108 -0
  137. package/dist/scripts/run-unit-tests.js +8 -2
  138. package/dist/server/bare/ops/transcribe.d.ts +2 -1
  139. package/dist/server/bare/ops/transcribe.js +59 -34
  140. package/dist/server/bare/plugins/ggml-classification/ops/classify.d.ts +6 -0
  141. package/dist/server/bare/plugins/ggml-classification/ops/classify.js +30 -0
  142. package/dist/server/bare/plugins/ggml-classification/plugin.d.ts +32 -0
  143. package/dist/server/bare/plugins/ggml-classification/plugin.js +55 -0
  144. package/dist/server/bare/plugins/ggml-vla/ops/vla-hparams.d.ts +3 -0
  145. package/dist/server/bare/plugins/ggml-vla/ops/vla-hparams.js +12 -0
  146. package/dist/server/bare/plugins/ggml-vla/ops/vla-run.d.ts +3 -0
  147. package/dist/server/bare/plugins/ggml-vla/ops/vla-run.js +75 -0
  148. package/dist/server/bare/plugins/ggml-vla/plugin.d.ts +54 -0
  149. package/dist/server/bare/plugins/ggml-vla/plugin.js +57 -0
  150. package/dist/server/bare/plugins/index.d.ts +3 -1
  151. package/dist/server/bare/plugins/index.js +3 -1
  152. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +3 -0
  153. package/dist/server/bare/plugins/llamacpp-completion/ops/context-overflow.d.ts +29 -0
  154. package/dist/server/bare/plugins/llamacpp-completion/ops/context-overflow.js +65 -0
  155. package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +6 -0
  156. package/dist/server/bare/plugins/llamacpp-completion/plugin.js +26 -0
  157. package/dist/server/bare/plugins/nmtcpp-translation/plugin.d.ts +25 -0
  158. package/dist/server/bare/plugins/onnx-ocr/plugin.d.ts +5 -0
  159. package/dist/server/bare/plugins/parakeet-transcription/plugin.d.ts +67 -246
  160. package/dist/server/bare/plugins/parakeet-transcription/plugin.js +66 -97
  161. package/dist/server/bare/plugins/sdcpp-generation/ops/video.d.ts +3 -0
  162. package/dist/server/bare/plugins/sdcpp-generation/ops/video.js +199 -0
  163. package/dist/server/bare/plugins/sdcpp-generation/plugin.d.ts +200 -2
  164. package/dist/server/bare/plugins/sdcpp-generation/plugin.js +61 -8
  165. package/dist/server/bare/plugins/{onnx-tts → tts-ggml}/ops/text-to-speech-stream.js +2 -15
  166. package/dist/server/bare/plugins/{onnx-tts → tts-ggml}/ops/text-to-speech.js +2 -1
  167. package/dist/server/bare/plugins/tts-ggml/plugin.d.ts +75 -0
  168. package/dist/server/bare/plugins/tts-ggml/plugin.js +189 -0
  169. package/dist/server/bare/plugins/whispercpp-transcription/plugin.d.ts +29 -4
  170. package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +12 -1
  171. package/dist/server/bare/registry/model-config-utils.js +7 -0
  172. package/dist/server/bare/runtime/request-context.d.ts +1 -1
  173. package/dist/server/bare/runtime-lifecycle.js +9 -9
  174. package/dist/server/bare/types/addon-responses.d.ts +1 -0
  175. package/dist/server/env.js +4 -1
  176. package/dist/server/plugins/index.d.ts +1 -1
  177. package/dist/server/plugins/index.js +1 -1
  178. package/dist/server/plugins/registry.d.ts +1 -0
  179. package/dist/server/plugins/registry.js +5 -0
  180. package/dist/server/rpc/handler-registry.js +4 -0
  181. package/dist/server/rpc/handler-selection.d.ts +9 -0
  182. package/dist/server/rpc/handler-selection.js +14 -0
  183. package/dist/server/rpc/handler-utils.js +5 -13
  184. package/dist/server/rpc/handlers/classify.d.ts +3 -0
  185. package/dist/server/rpc/handlers/classify.js +4 -0
  186. package/dist/server/rpc/handlers/index.d.ts +2 -0
  187. package/dist/server/rpc/handlers/index.js +2 -0
  188. package/dist/server/rpc/handlers/load-model/handler.js +4 -1
  189. package/dist/server/rpc/handlers/load-model/resolve.js +9 -0
  190. package/dist/server/rpc/handlers/video-stream.d.ts +3 -0
  191. package/dist/server/rpc/handlers/video-stream.js +4 -0
  192. package/dist/server/rpc/profiling/operation-metrics.js +23 -0
  193. package/dist/server/utils/config-transform.js +1 -1
  194. package/dist/server/worker.js +14 -11
  195. package/dist/utils/errors-client.d.ts +15 -0
  196. package/dist/utils/errors-client.js +26 -0
  197. package/dist/utils/errors-server.d.ts +30 -2
  198. package/dist/utils/errors-server.js +51 -3
  199. package/package.json +66 -80
  200. package/dist/server/bare/plugins/onnx-tts/plugin.d.ts +0 -490
  201. package/dist/server/bare/plugins/onnx-tts/plugin.js +0 -272
  202. package/dist/server/bare/plugins/onnx-tts/wav-helper.d.ts +0 -14
  203. package/dist/server/bare/plugins/onnx-tts/wav-helper.js +0 -107
  204. /package/dist/server/bare/plugins/{onnx-tts → tts-ggml}/ops/text-to-speech-stream.d.ts +0 -0
  205. /package/dist/server/bare/plugins/{onnx-tts → tts-ggml}/ops/text-to-speech.d.ts +0 -0
package/README.md CHANGED
@@ -16,6 +16,8 @@ See [https://docs.qvac.tether.io/sdk/getting-started](https://docs.qvac.tether.i
16
16
 
17
17
  For AI/LLM tools, use [https://docs.qvac.tether.io/llms-full.txt](https://docs.qvac.tether.io/llms-full.txt) as the consolidated plaintext documentation export.
18
18
 
19
+ > **Assembling a custom worker on Bare?** See [`@qvac/bare-sdk`](../bare-sdk/README.md) — the same SDK surface with no built-in plugin addons, designed for consumers wiring their own worker entry (Pear apps, bare-expo apps, direct Bare scripts).
20
+
19
21
  ## Supported environments and installation
20
22
 
21
23
  See https://docs.qvac.tether.io/sdk/getting-started/installation
@@ -0,0 +1,23 @@
1
+ import { type ClassifyClientParams, type ClassificationResult } from "../../schemas/index";
2
+ /**
3
+ * Classifies an image using a loaded classification model.
4
+ *
5
+ * The bundled MobileNetV3-Small model produces 3 labels: `"food"`, `"report"`, `"other"`.
6
+ * Custom models may emit different labels sourced from the GGUF metadata.
7
+ *
8
+ * @param params.modelId - The identifier of the loaded classification model
9
+ * @param params.image - JPEG or PNG buffer; raw RGB bytes also accepted with `width`, `height`, `channels`
10
+ * @param params.topK - Limit results to top-K classes (default: all)
11
+ * @returns Sorted classification results, highest confidence first
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const modelId = await loadModel({ modelType: "ggml-classification" });
16
+ * const jpeg = fs.readFileSync("photo.jpg");
17
+ * const results = await classify({ modelId, image: jpeg });
18
+ * // [ { label: "food", confidence: 0.93 }, { label: "other", confidence: 0.05 }, ... ]
19
+ * await unloadModel({ modelId });
20
+ * ```
21
+ */
22
+ export declare function classify(params: ClassifyClientParams): Promise<ClassificationResult[]>;
23
+ //# sourceMappingURL=classify.d.ts.map
@@ -0,0 +1,43 @@
1
+ import { classifyResponseSchema, } from "../../schemas/index.js";
2
+ import { stream as streamRpc } from "../rpc/rpc-client.js";
3
+ import { encodeBase64 } from "../../utils/encoding.js";
4
+ /**
5
+ * Classifies an image using a loaded classification model.
6
+ *
7
+ * The bundled MobileNetV3-Small model produces 3 labels: `"food"`, `"report"`, `"other"`.
8
+ * Custom models may emit different labels sourced from the GGUF metadata.
9
+ *
10
+ * @param params.modelId - The identifier of the loaded classification model
11
+ * @param params.image - JPEG or PNG buffer; raw RGB bytes also accepted with `width`, `height`, `channels`
12
+ * @param params.topK - Limit results to top-K classes (default: all)
13
+ * @returns Sorted classification results, highest confidence first
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const modelId = await loadModel({ modelType: "ggml-classification" });
18
+ * const jpeg = fs.readFileSync("photo.jpg");
19
+ * const results = await classify({ modelId, image: jpeg });
20
+ * // [ { label: "food", confidence: 0.93 }, { label: "other", confidence: 0.05 }, ... ]
21
+ * await unloadModel({ modelId });
22
+ * ```
23
+ */
24
+ export async function classify(params) {
25
+ const request = {
26
+ type: "classify",
27
+ modelId: params.modelId,
28
+ image: encodeBase64(params.image),
29
+ ...(params.topK !== undefined && { topK: params.topK }),
30
+ ...(params.width !== undefined && { width: params.width }),
31
+ ...(params.height !== undefined && { height: params.height }),
32
+ ...(params.channels !== undefined && { channels: params.channels }),
33
+ };
34
+ for await (const response of streamRpc(request)) {
35
+ if (response && typeof response === "object" && "type" in response && response.type === "classify") {
36
+ const parsed = classifyResponseSchema.parse(response);
37
+ if (parsed.done) {
38
+ return parsed.results;
39
+ }
40
+ }
41
+ }
42
+ return [];
43
+ }
@@ -12,7 +12,7 @@ export declare function getModelInfo(params: GetModelInfoParams): Promise<{
12
12
  modelId: string;
13
13
  expectedSize: number;
14
14
  sha256Checksum: string;
15
- addon: "embeddings" | "diffusion" | "tts" | "ocr" | "llm" | "whisper" | "nmt" | "parakeet" | "vad" | "other";
15
+ addon: "embeddings" | "diffusion" | "tts" | "ocr" | "vla" | "llm" | "whisper" | "nmt" | "parakeet" | "classification" | "vad" | "other";
16
16
  isCached: boolean;
17
17
  isLoaded: boolean;
18
18
  cacheFiles: {
@@ -19,9 +19,13 @@ export { getLoadedModelInfo } from "./get-loaded-model-info";
19
19
  export { ocr } from "./ocr";
20
20
  export { invokePlugin, invokePluginStream } from "./invoke-plugin";
21
21
  export { diffusion, type DiffusionProgressTick } from "./diffusion";
22
+ export { classify } from "./classify";
23
+ export { video, type VideoProgressTick } from "./video";
22
24
  export { upscale } from "./upscale";
23
25
  export { modelRegistryList, modelRegistrySearch, modelRegistryGetModel, type ModelRegistrySearchParams, } from "./registry";
24
26
  export { suspend } from "./suspend";
25
27
  export { resume } from "./resume";
26
28
  export { state } from "./state";
29
+ export { vla, vlaHparams } from "./vla";
30
+ export { vlaPreprocessImage, vlaPadState, VLA_DEFAULT_IMAGE_SIZE, } from "./vla-helpers";
27
31
  //# sourceMappingURL=index.d.ts.map
@@ -19,8 +19,12 @@ export { getLoadedModelInfo } from "./get-loaded-model-info.js";
19
19
  export { ocr } from "./ocr.js";
20
20
  export { invokePlugin, invokePluginStream } from "./invoke-plugin.js";
21
21
  export { diffusion } from "./diffusion.js";
22
+ export { classify } from "./classify.js";
23
+ export { video } from "./video.js";
22
24
  export { upscale } from "./upscale.js";
23
25
  export { modelRegistryList, modelRegistrySearch, modelRegistryGetModel, } from "./registry.js";
24
26
  export { suspend } from "./suspend.js";
25
27
  export { resume } from "./resume.js";
26
28
  export { state } from "./state.js";
29
+ export { vla, vlaHparams } from "./vla.js";
30
+ export { vlaPreprocessImage, vlaPadState, VLA_DEFAULT_IMAGE_SIZE, } from "./vla-helpers.js";
@@ -1,12 +1,17 @@
1
1
  import { send, stream } from "../rpc/rpc-client.js";
2
2
  import { startLoggingStreamForModel } from "../logging-stream-registry.js";
3
- import { loadModelOptionsToRequestSchema, reloadConfigOptionsToRequestSchema, isModelTypeAlias, normalizeModelType, inferModelTypeFromModelSrc, } from "../../schemas/index.js";
3
+ import { loadModelOptionsToRequestSchema, reloadConfigOptionsToRequestSchema, isModelTypeAlias, normalizeModelType, inferModelTypeFromModelSrc, ModelType, } from "../../schemas/index.js";
4
4
  import { ModelLoadFailedError, ModelTypeRequiredError, StreamEndedError, InvalidResponseError, } from "../../utils/errors-client.js";
5
5
  import { assertModelSrcMatchesModelType } from "../../utils/load-model-validation.js";
6
6
  import { getClientLogger } from "../../logging/index.js";
7
7
  import { decoratePromise } from "../../utils/decorate-promise.js";
8
8
  import { generateClientRequestId } from "./client-request-id.js";
9
9
  const logger = getClientLogger();
10
+ function isReactNativeRuntime() {
11
+ const runtime = globalThis;
12
+ return runtime.navigator?.product === "ReactNative";
13
+ }
14
+ let warnedLocalVideoModelLoad = false;
10
15
  export function loadModel(options, rpcOptions) {
11
16
  // Generate a stable `requestId` once, synchronously, before kicking
12
17
  // off any async work. The same id is:
@@ -45,6 +50,24 @@ async function runLoadModel(options, requestId, rpcOptions) {
45
50
  const canonical = normalizeModelType(modelType);
46
51
  logger.warn(`Model type "${modelType}" is an alias and will be deprecated. Use "${canonical}" instead.`);
47
52
  }
53
+ const canonicalModelType = typeof modelType === "string" ? normalizeModelType(modelType) : modelType;
54
+ const modelConfig = resolvedOptions["modelConfig"];
55
+ if (isReactNativeRuntime() &&
56
+ canonicalModelType === ModelType.sdcppGeneration &&
57
+ modelConfig?.mode === "video" &&
58
+ resolvedOptions["delegate"] === undefined &&
59
+ !warnedLocalVideoModelLoad) {
60
+ warnedLocalVideoModelLoad = true;
61
+ const message = "QVAC video generation works on React Native, but loading the video " +
62
+ "model on-device will usually fail or take several minutes — the video " +
63
+ "diffusion models currently shipped by the SDK are too large to load " +
64
+ "on typical mobile devices. Pass a `delegate` to `loadModel(...)` to " +
65
+ "run generation on a desktop peer instead.";
66
+ logger.warn(message);
67
+ // Surface via console too - if an RN host app doesn't wire getClientLogger()
68
+ // to a visible transport, logger.warn alone won't reach the dev.
69
+ console.warn(message);
70
+ }
48
71
  }
49
72
  // Splice the client-generated `requestId` onto the resolved options so
50
73
  // the wire envelope carries it. The server uses the same value as the
@@ -66,6 +66,9 @@ export declare function transcribeStream(params: TranscribeClientParams, options
66
66
  export declare function transcribeStream(params: TranscribeStreamClientParams & {
67
67
  emitVadEvents: true;
68
68
  }, options?: RPCOptions): Promise<TranscribeStreamConversationSession>;
69
+ export declare function transcribeStream(params: TranscribeStreamClientParams & {
70
+ parakeetStreamingConfig: NonNullable<TranscribeStreamClientParams["parakeetStreamingConfig"]>;
71
+ }, options?: RPCOptions): Promise<TranscribeStreamConversationSession>;
69
72
  export declare function transcribeStream(params: TranscribeStreamClientParams & {
70
73
  metadata: true;
71
74
  }, options?: RPCOptions): Promise<TranscribeStreamMetadataSession>;
@@ -67,7 +67,8 @@ export function transcribeStream(params, options) {
67
67
  return transcribeStreamWithAudio(params, options);
68
68
  }
69
69
  const streamParams = params;
70
- if (streamParams.emitVadEvents === true) {
70
+ if (streamParams.emitVadEvents === true ||
71
+ streamParams.parakeetStreamingConfig !== undefined) {
71
72
  return transcribeStreamDuplexConversation(streamParams, options);
72
73
  }
73
74
  if (streamParams.metadata === true) {
@@ -111,6 +112,9 @@ function buildTranscribeStreamRequest(params) {
111
112
  ...(params.vadRunIntervalMs !== undefined && {
112
113
  vadRunIntervalMs: params.vadRunIntervalMs,
113
114
  }),
115
+ ...(params.parakeetStreamingConfig && {
116
+ parakeetStreamingConfig: params.parakeetStreamingConfig,
117
+ }),
114
118
  };
115
119
  }
116
120
  /**
@@ -227,9 +231,16 @@ function processLineConversation(line, wantsMetadata) {
227
231
  };
228
232
  }
229
233
  if (response.endOfTurn) {
234
+ if (response.endOfTurn.source === "whisper") {
235
+ return {
236
+ type: "endOfTurn",
237
+ source: "whisper",
238
+ silenceDurationMs: response.endOfTurn.silenceDurationMs,
239
+ };
240
+ }
230
241
  return {
231
242
  type: "endOfTurn",
232
- silenceDurationMs: response.endOfTurn.silenceDurationMs,
243
+ source: "parakeet",
233
244
  };
234
245
  }
235
246
  if (wantsMetadata) {
@@ -0,0 +1,64 @@
1
+ import { type VideoClientParams, type VideoStats } from "../../schemas/index";
2
+ export interface VideoProgressTick {
3
+ step: number;
4
+ totalSteps: number;
5
+ elapsedMs: number;
6
+ }
7
+ export interface VideoResult {
8
+ requestId: string;
9
+ progressStream: AsyncGenerator<VideoProgressTick>;
10
+ outputs: Promise<Uint8Array[]>;
11
+ stats: Promise<VideoStats | undefined>;
12
+ }
13
+ /**
14
+ * Generates a video using a loaded video diffusion model.
15
+ *
16
+ * @param params - Video request parameters (model, prompt, dimensions, frame count, fps, sampler, seed, etc.).
17
+ * @returns A result object exposing `requestId` (stable identifier for this in-flight generation), `progressStream` (async iterator of `{ step, totalSteps, elapsedMs }`), `outputs` (promise of the generated video buffers, typically a single AVI file), and `stats` (promise of generation statistics).
18
+ *
19
+ * Only `txt2vid` mode is supported today. On React Native, prefer a `modelId` loaded with a `delegate` since the bundled video diffusion models are too large for typical mobile devices.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * // Basic txt2vid generation
24
+ * const { outputs, stats } = video({
25
+ * modelId,
26
+ * mode: "txt2vid",
27
+ * prompt: "a cat surfing a wave at sunset",
28
+ * width: 480,
29
+ * height: 832,
30
+ * video_frames: 17, // must satisfy (4*k + 1)
31
+ * fps: 16,
32
+ * });
33
+ * const buffers = await outputs;
34
+ * fs.writeFileSync("output.avi", buffers[0]);
35
+ *
36
+ * // With progress tracking
37
+ * const { progressStream, outputs } = video({
38
+ * modelId,
39
+ * mode: "txt2vid",
40
+ * prompt: "a sunset over the ocean",
41
+ * });
42
+ * for await (const { step, totalSteps } of progressStream) {
43
+ * console.log(`${step}/${totalSteps}`);
44
+ * }
45
+ * const buffers = await outputs;
46
+ *
47
+ * // With control frames (e.g. for guided generation)
48
+ * const frameA = fs.readFileSync("frame-a.png");
49
+ * const frameB = fs.readFileSync("frame-b.png");
50
+ * const { outputs } = video({
51
+ * modelId,
52
+ * mode: "txt2vid",
53
+ * prompt: "smooth transition between scenes",
54
+ * control_frames: [frameA, frameB],
55
+ * });
56
+ *
57
+ * // Cancellation via requestId
58
+ * const { requestId, outputs } = video({ modelId, mode: "txt2vid", prompt: "..." });
59
+ * // ...later
60
+ * await cancel(requestId);
61
+ * ```
62
+ */
63
+ export declare function video(params: VideoClientParams): VideoResult;
64
+ //# sourceMappingURL=video.d.ts.map
@@ -0,0 +1,147 @@
1
+ import { videoStreamResponseSchema, } from "../../schemas/index.js";
2
+ import { stream as streamRpc } from "../rpc/rpc-client.js";
3
+ import { generateClientRequestId } from "./client-request-id.js";
4
+ import { decodeBase64, encodeBase64 } from "../../utils/encoding.js";
5
+ /**
6
+ * Generates a video using a loaded video diffusion model.
7
+ *
8
+ * @param params - Video request parameters (model, prompt, dimensions, frame count, fps, sampler, seed, etc.).
9
+ * @returns A result object exposing `requestId` (stable identifier for this in-flight generation), `progressStream` (async iterator of `{ step, totalSteps, elapsedMs }`), `outputs` (promise of the generated video buffers, typically a single AVI file), and `stats` (promise of generation statistics).
10
+ *
11
+ * Only `txt2vid` mode is supported today. On React Native, prefer a `modelId` loaded with a `delegate` since the bundled video diffusion models are too large for typical mobile devices.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // Basic txt2vid generation
16
+ * const { outputs, stats } = video({
17
+ * modelId,
18
+ * mode: "txt2vid",
19
+ * prompt: "a cat surfing a wave at sunset",
20
+ * width: 480,
21
+ * height: 832,
22
+ * video_frames: 17, // must satisfy (4*k + 1)
23
+ * fps: 16,
24
+ * });
25
+ * const buffers = await outputs;
26
+ * fs.writeFileSync("output.avi", buffers[0]);
27
+ *
28
+ * // With progress tracking
29
+ * const { progressStream, outputs } = video({
30
+ * modelId,
31
+ * mode: "txt2vid",
32
+ * prompt: "a sunset over the ocean",
33
+ * });
34
+ * for await (const { step, totalSteps } of progressStream) {
35
+ * console.log(`${step}/${totalSteps}`);
36
+ * }
37
+ * const buffers = await outputs;
38
+ *
39
+ * // With control frames (e.g. for guided generation)
40
+ * const frameA = fs.readFileSync("frame-a.png");
41
+ * const frameB = fs.readFileSync("frame-b.png");
42
+ * const { outputs } = video({
43
+ * modelId,
44
+ * mode: "txt2vid",
45
+ * prompt: "smooth transition between scenes",
46
+ * control_frames: [frameA, frameB],
47
+ * });
48
+ *
49
+ * // Cancellation via requestId
50
+ * const { requestId, outputs } = video({ modelId, mode: "txt2vid", prompt: "..." });
51
+ * // ...later
52
+ * await cancel(requestId);
53
+ * ```
54
+ */
55
+ export function video(params) {
56
+ const { control_frames, ...rest } = params;
57
+ const requestId = generateClientRequestId();
58
+ const request = {
59
+ ...rest,
60
+ ...(control_frames !== undefined && {
61
+ control_frames: control_frames.map(encodeBase64),
62
+ }),
63
+ type: "videoStream",
64
+ requestId,
65
+ };
66
+ let statsResolver = () => { };
67
+ let statsRejecter = () => { };
68
+ const statsPromise = new Promise((resolve, reject) => {
69
+ statsResolver = resolve;
70
+ statsRejecter = reject;
71
+ });
72
+ statsPromise.catch(() => { });
73
+ const progressQueue = [];
74
+ const collectedBuffers = [];
75
+ let progressDone = false;
76
+ let progressResolve = null;
77
+ let streamError = null;
78
+ let outputsResolver = () => { };
79
+ let outputsRejecter = () => { };
80
+ const outputsPromise = new Promise((resolve, reject) => {
81
+ outputsResolver = resolve;
82
+ outputsRejecter = reject;
83
+ });
84
+ outputsPromise.catch(() => { });
85
+ async function processResponses() {
86
+ try {
87
+ for await (const response of streamRpc(request)) {
88
+ if (response &&
89
+ typeof response === "object" &&
90
+ "type" in response &&
91
+ response.type === "videoStream") {
92
+ const parsed = videoStreamResponseSchema.parse(response);
93
+ if (parsed.step != null && parsed.totalSteps != null && parsed.elapsedMs != null) {
94
+ progressQueue.push({
95
+ step: parsed.step,
96
+ totalSteps: parsed.totalSteps,
97
+ elapsedMs: parsed.elapsedMs,
98
+ });
99
+ if (progressResolve) {
100
+ progressResolve();
101
+ progressResolve = null;
102
+ }
103
+ }
104
+ if (parsed.data) {
105
+ collectedBuffers.push(decodeBase64(parsed.data));
106
+ }
107
+ if (parsed.done) {
108
+ statsResolver(parsed.stats);
109
+ outputsResolver(collectedBuffers);
110
+ }
111
+ }
112
+ }
113
+ }
114
+ catch (error) {
115
+ streamError = error instanceof Error ? error : new Error(String(error));
116
+ statsRejecter(streamError);
117
+ outputsRejecter(streamError);
118
+ }
119
+ progressDone = true;
120
+ if (progressResolve) {
121
+ progressResolve();
122
+ progressResolve = null;
123
+ }
124
+ }
125
+ void processResponses();
126
+ const progressStream = (async function* () {
127
+ while (true) {
128
+ if (progressQueue.length > 0) {
129
+ yield progressQueue.shift();
130
+ }
131
+ else if (progressDone) {
132
+ if (streamError)
133
+ throw streamError;
134
+ return;
135
+ }
136
+ else {
137
+ await new Promise((resolve) => { progressResolve = resolve; });
138
+ }
139
+ }
140
+ })();
141
+ return {
142
+ requestId,
143
+ progressStream,
144
+ outputs: outputsPromise,
145
+ stats: statsPromise,
146
+ };
147
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Pure-JS helpers for preparing VLA inference inputs on the client side.
3
+ *
4
+ * Mirrors `preprocessImage` / `padState` / `DEFAULT_IMAGE_SIZE` from
5
+ * `@qvac/vla-ggml/addon.js`. Kept inlined (not re-exported from the addon)
6
+ * so the SDK's client surface never loads the addon's native binding —
7
+ * consumers running under Node / Bun / Expo without VLA prebuilds can still
8
+ * use the SDK to drive a remote VLA worker.
9
+ *
10
+ * This file is a verbatim port of the addon's JS implementation; keep them
11
+ * in sync so the wire-format tensors stay byte-identical regardless of
12
+ * where preprocessing runs (consumer process vs worker vs addon).
13
+ */
14
+ /** Default vision tower image size used by SmolVLA-LIBERO. */
15
+ export declare const VLA_DEFAULT_IMAGE_SIZE = 512;
16
+ type PixelsInput = Float32Array | Uint8Array | number[];
17
+ type ImageLayout = "hwc" | "chw";
18
+ export interface VlaPreprocessImageOptions {
19
+ size?: number;
20
+ layout?: ImageLayout;
21
+ /**
22
+ * Skip the [0,255] vs [0,1] auto-detection heuristic when the caller knows
23
+ * the range. `1` = pixels already in [0,1] (no rescale). `1/255` = pixels
24
+ * in [0,255] (rescale to [0,1]). Any other value (including the literal
25
+ * `'auto'`) falls back to the heuristic.
26
+ */
27
+ scale?: number | "auto";
28
+ }
29
+ /**
30
+ * Resize + letterbox + normalize a camera frame to `(3, size, size)` Float32
31
+ * in `[-1, 1]`. Drop-in equivalent of `@qvac/vla-ggml`'s `preprocessImage`.
32
+ *
33
+ * Letterbox places the resized content at the **bottom-right** with padding
34
+ * at top/left (`padLeft = size - newW`, `padTop = size - newH`), matching
35
+ * the reference smolvla.cpp behavior.
36
+ */
37
+ export declare function vlaPreprocessImage(pixels: PixelsInput, width: number, height: number, opts?: VlaPreprocessImageOptions): Float32Array;
38
+ /**
39
+ * Zero-pad a state vector to `targetDim`. Extra entries are zero-initialised;
40
+ * input longer than `targetDim` raises. Mirrors how smolvla.cpp expects the
41
+ * state tensor (`max_state_dim` = 32 by default).
42
+ */
43
+ export declare function vlaPadState(state: ArrayLike<number>, targetDim?: number): Float32Array;
44
+ export {};
45
+ //# sourceMappingURL=vla-helpers.d.ts.map
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Pure-JS helpers for preparing VLA inference inputs on the client side.
3
+ *
4
+ * Mirrors `preprocessImage` / `padState` / `DEFAULT_IMAGE_SIZE` from
5
+ * `@qvac/vla-ggml/addon.js`. Kept inlined (not re-exported from the addon)
6
+ * so the SDK's client surface never loads the addon's native binding —
7
+ * consumers running under Node / Bun / Expo without VLA prebuilds can still
8
+ * use the SDK to drive a remote VLA worker.
9
+ *
10
+ * This file is a verbatim port of the addon's JS implementation; keep them
11
+ * in sync so the wire-format tensors stay byte-identical regardless of
12
+ * where preprocessing runs (consumer process vs worker vs addon).
13
+ */
14
+ /** Default vision tower image size used by SmolVLA-LIBERO. */
15
+ export const VLA_DEFAULT_IMAGE_SIZE = 512;
16
+ function detectScale(pixels) {
17
+ if (pixels instanceof Uint8Array)
18
+ return 1 / 255;
19
+ // Float/Number arrays: scan a small window to decide whether it's [0,255] or [0,1].
20
+ const limit = Math.min(pixels.length, 256);
21
+ let maxVal = 0;
22
+ for (let i = 0; i < limit; i++) {
23
+ const v = pixels[i];
24
+ if (v > maxVal)
25
+ maxVal = v;
26
+ }
27
+ return maxVal > 1.001 ? 1 / 255 : 1;
28
+ }
29
+ /**
30
+ * Resize + letterbox + normalize a camera frame to `(3, size, size)` Float32
31
+ * in `[-1, 1]`. Drop-in equivalent of `@qvac/vla-ggml`'s `preprocessImage`.
32
+ *
33
+ * Letterbox places the resized content at the **bottom-right** with padding
34
+ * at top/left (`padLeft = size - newW`, `padTop = size - newH`), matching
35
+ * the reference smolvla.cpp behavior.
36
+ */
37
+ export function vlaPreprocessImage(pixels, width, height, opts = {}) {
38
+ const size = opts.size ?? VLA_DEFAULT_IMAGE_SIZE;
39
+ const layout = opts.layout ?? "hwc";
40
+ if (!Number.isInteger(width) ||
41
+ !Number.isInteger(height) ||
42
+ width <= 0 ||
43
+ height <= 0) {
44
+ throw new TypeError("vlaPreprocessImage: width/height must be positive integers");
45
+ }
46
+ const expected = width * height * 3;
47
+ if (pixels.length !== expected) {
48
+ throw new RangeError(`vlaPreprocessImage: expected ${expected} pixel values, got ${pixels.length}`);
49
+ }
50
+ const normalize = opts.scale === 1 || opts.scale === 1 / 255
51
+ ? opts.scale
52
+ : detectScale(pixels);
53
+ // Letterbox target size (aspect-ratio preserving).
54
+ const ratio = Math.max(width / size, height / size);
55
+ const newW = Math.max(1, Math.floor(width / ratio));
56
+ const newH = Math.max(1, Math.floor(height / ratio));
57
+ const padLeft = size - newW;
58
+ const padTop = size - newH;
59
+ const xScale = width / newW;
60
+ const yScale = height / newH;
61
+ // Output starts at -1 so the pad region is already in [-1, 1] and we only
62
+ // need to overwrite the (newH × newW) inner region with the resized content.
63
+ const out = new Float32Array(3 * size * size);
64
+ out.fill(-1);
65
+ const planeStride = size * size;
66
+ const widthHeight = width * height;
67
+ for (let yy = 0; yy < newH; yy++) {
68
+ const yIn = (yy + 0.5) * yScale - 0.5;
69
+ const y0 = Math.max(0, Math.floor(yIn));
70
+ const y1 = Math.min(height - 1, y0 + 1);
71
+ const dy = Math.min(1, Math.max(0, yIn - y0));
72
+ const dyInv = 1 - dy;
73
+ const outY = yy + padTop;
74
+ for (let xx = 0; xx < newW; xx++) {
75
+ const xIn = (xx + 0.5) * xScale - 0.5;
76
+ const x0 = Math.max(0, Math.floor(xIn));
77
+ const x1 = Math.min(width - 1, x0 + 1);
78
+ const dx = Math.min(1, Math.max(0, xIn - x0));
79
+ const dxInv = 1 - dx;
80
+ const outX = xx + padLeft;
81
+ const w00 = dxInv * dyInv;
82
+ const w10 = dx * dyInv;
83
+ const w01 = dxInv * dy;
84
+ const w11 = dx * dy;
85
+ const outIdx = outY * size + outX;
86
+ if (layout === "hwc") {
87
+ const i00 = (y0 * width + x0) * 3;
88
+ const i10 = (y0 * width + x1) * 3;
89
+ const i01 = (y1 * width + x0) * 3;
90
+ const i11 = (y1 * width + x1) * 3;
91
+ for (let c = 0; c < 3; c++) {
92
+ const v = pixels[i00 + c] * w00 +
93
+ pixels[i10 + c] * w10 +
94
+ pixels[i01 + c] * w01 +
95
+ pixels[i11 + c] * w11;
96
+ // Apply scale and shift into [-1, 1] in one fused multiply-add.
97
+ out[c * planeStride + outIdx] = v * normalize * 2 - 1;
98
+ }
99
+ }
100
+ else {
101
+ for (let c = 0; c < 3; c++) {
102
+ const plane = c * widthHeight;
103
+ const v = pixels[plane + y0 * width + x0] * w00 +
104
+ pixels[plane + y0 * width + x1] * w10 +
105
+ pixels[plane + y1 * width + x0] * w01 +
106
+ pixels[plane + y1 * width + x1] * w11;
107
+ out[c * planeStride + outIdx] = v * normalize * 2 - 1;
108
+ }
109
+ }
110
+ }
111
+ }
112
+ return out;
113
+ }
114
+ /**
115
+ * Zero-pad a state vector to `targetDim`. Extra entries are zero-initialised;
116
+ * input longer than `targetDim` raises. Mirrors how smolvla.cpp expects the
117
+ * state tensor (`max_state_dim` = 32 by default).
118
+ */
119
+ export function vlaPadState(state, targetDim = 32) {
120
+ if (!Number.isInteger(targetDim) || targetDim <= 0) {
121
+ throw new TypeError("vlaPadState: targetDim must be a positive integer");
122
+ }
123
+ if (state.length > targetDim) {
124
+ throw new RangeError(`vlaPadState: input length ${state.length} exceeds targetDim ${targetDim}`);
125
+ }
126
+ const out = new Float32Array(targetDim);
127
+ for (let i = 0; i < state.length; i++)
128
+ out[i] = state[i];
129
+ return out;
130
+ }
@@ -0,0 +1,65 @@
1
+ import { type VlaClientRunParams, type VlaClientRunResult, type VlaHparams } from "../../schemas/index";
2
+ /**
3
+ * Run SmolVLA inference on a loaded VLA model and return the produced action
4
+ * chunk plus per-stage timings.
5
+ *
6
+ * @param params - Inference inputs.
7
+ * @param params.modelId - Identifier of the loaded VLA model (returned by
8
+ * `loadModel({ modelType: "vla", ... })`).
9
+ * @param params.images - One or more preprocessed camera frames; each is a
10
+ * `Float32Array` of length `3 * imgWidth * imgHeight` in CHW layout, range
11
+ * `[-1, 1]`. Use the addon's `preprocessImage()` (re-exported as
12
+ * `vlaPreprocessImage`) to produce them.
13
+ * @param params.imgWidth - Width of each preprocessed image; must equal
14
+ * `hparams.visionImageSize`.
15
+ * @param params.imgHeight - Height of each preprocessed image; must equal
16
+ * `hparams.visionImageSize`.
17
+ * @param params.state - Robot end-effector / gripper state padded to
18
+ * `hparams.maxStateDim` (use `vlaPadState`).
19
+ * @param params.tokens - Tokenized instruction (`Int32Array` of length
20
+ * `hparams.tokenizerMaxLength`). Tokenize on the consumer side with the
21
+ * SmolVLM2 tokenizer.
22
+ * @param params.mask - Token attention mask (`Uint8Array` matching `tokens`).
23
+ * @param params.noise - Optional seeded noise prior
24
+ * (`Float32Array` of length `hparams.chunkSize * hparams.maxActionDim`).
25
+ * When omitted the addon samples its own prior.
26
+ * @returns A `VlaClientRunResult` with the produced `actions` Float32Array
27
+ * (length `chunkSize * actionDim`), the corresponding `chunkSize` /
28
+ * `actionDim` returned by the addon, and optional per-stage `stats`.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * import { loadModel, vla, vlaPreprocessImage, vlaPadState, vlaHparams } from "@qvac/sdk";
33
+ *
34
+ * const modelId = await loadModel({ modelSrc: "/path/to/smolvla.gguf", modelType: "vla" });
35
+ * const { hparams } = await vlaHparams({ modelId });
36
+ * const size = hparams.visionImageSize;
37
+ * const front = vlaPreprocessImage(frontPixels, frontW, frontH, { size });
38
+ * const wrist = vlaPreprocessImage(wristPixels, wristW, wristH, { size });
39
+ * const state = vlaPadState(robotState, hparams.maxStateDim);
40
+ * const tokens = new Int32Array(hparams.tokenizerMaxLength);
41
+ * const mask = new Uint8Array(hparams.tokenizerMaxLength);
42
+ * // ...tokenize the instruction into tokens/mask...
43
+ * const { actions } = await vla({
44
+ * modelId, images: [front, wrist], imgWidth: size, imgHeight: size,
45
+ * state, tokens, mask,
46
+ * });
47
+ * ```
48
+ */
49
+ export declare function vla(params: VlaClientRunParams): Promise<VlaClientRunResult>;
50
+ /**
51
+ * Fetch the loaded VLA model's hyperparameters and the active ggml backend
52
+ * name. Useful to size token / state / noise buffers before calling `vla()`.
53
+ *
54
+ * @param params - Identifier of the loaded VLA model.
55
+ * @returns The model's hparams and the human-readable backend name
56
+ * (`"CPU"` / `"Vulkan"` / `"Metal"` / `"OpenCL"` / `null` if the addon
57
+ * has not surfaced one).
58
+ */
59
+ export declare function vlaHparams(params: {
60
+ modelId: string;
61
+ }): Promise<{
62
+ hparams: VlaHparams;
63
+ backendName: string | null;
64
+ }>;
65
+ //# sourceMappingURL=vla.d.ts.map