@qvac/sdk 0.10.1 → 0.11.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 (201) hide show
  1. package/NOTICE +92 -54
  2. package/dist/client/api/cancel.d.ts +24 -32
  3. package/dist/client/api/cancel.js +58 -31
  4. package/dist/client/api/client-request-id.d.ts +17 -0
  5. package/dist/client/api/client-request-id.js +27 -0
  6. package/dist/client/api/completion-stream.d.ts +1 -1
  7. package/dist/client/api/completion-stream.js +34 -3
  8. package/dist/client/api/diffusion.d.ts +46 -0
  9. package/dist/client/api/diffusion.js +50 -1
  10. package/dist/client/api/download-asset.d.ts +12 -2
  11. package/dist/client/api/download-asset.js +21 -3
  12. package/dist/client/api/embed.d.ts +8 -4
  13. package/dist/client/api/embed.js +14 -1
  14. package/dist/client/api/get-model-info.d.ts +1 -1
  15. package/dist/client/api/index.d.ts +1 -0
  16. package/dist/client/api/index.js +1 -0
  17. package/dist/client/api/load-model.d.ts +12 -4
  18. package/dist/client/api/load-model.js +25 -1
  19. package/dist/client/api/rag.d.ts +9 -3
  20. package/dist/client/api/rag.js +23 -3
  21. package/dist/client/api/transcribe.d.ts +20 -8
  22. package/dist/client/api/transcribe.js +58 -4
  23. package/dist/client/api/unload-model.d.ts +5 -2
  24. package/dist/client/api/unload-model.js +9 -4
  25. package/dist/client/api/upscale.d.ts +45 -0
  26. package/dist/client/api/upscale.js +99 -0
  27. package/dist/client/rpc/expo-rpc-client.js +2 -1
  28. package/dist/client/rpc/node-rpc-client.js +18 -7
  29. package/dist/client/rpc/rpc-client.d.ts +2 -2
  30. package/dist/client/rpc/rpc-client.js +10 -4
  31. package/dist/client/rpc/rpc-error.d.ts +9 -0
  32. package/dist/client/rpc/rpc-error.js +92 -0
  33. package/dist/examples/cancel-by-request-id.d.ts +38 -0
  34. package/dist/examples/cancel-by-request-id.js +103 -0
  35. package/dist/examples/diffusion-esrgan-upscale.d.ts +2 -0
  36. package/dist/examples/diffusion-esrgan-upscale.js +78 -0
  37. package/dist/examples/download-with-cancel.js +10 -10
  38. package/dist/examples/embed-multi-gpu.d.ts +2 -0
  39. package/dist/examples/embed-multi-gpu.js +46 -0
  40. package/dist/examples/llamacpp-multi-gpu.d.ts +2 -0
  41. package/dist/examples/llamacpp-multi-gpu.js +57 -0
  42. package/dist/examples/rag/rag-hyperdb/cancellation.js +20 -17
  43. package/dist/examples/tools/llamacpp-tools-gemma4.d.ts +2 -0
  44. package/dist/examples/tools/llamacpp-tools-gemma4.js +76 -0
  45. package/dist/examples/tools/llamacpp-tools-qwen35.d.ts +2 -0
  46. package/dist/examples/tools/llamacpp-tools-qwen35.js +70 -0
  47. package/dist/examples/transcription/whispercpp-microphone-conversation.d.ts +2 -0
  48. package/dist/examples/transcription/whispercpp-microphone-conversation.js +102 -0
  49. package/dist/examples/tts/supertonic.js +1 -1
  50. package/dist/expo/plugins/withMobileBundle.d.ts +20 -4
  51. package/dist/expo/plugins/withMobileBundle.js +44 -6
  52. package/dist/index.d.ts +5 -2
  53. package/dist/index.js +21 -1
  54. package/dist/models/registry/models.d.ts +186 -318
  55. package/dist/models/registry/models.js +1522 -1667
  56. package/dist/pear/pre.d.ts +3 -0
  57. package/dist/pear/pre.js +3 -0
  58. package/dist/schemas/cancel.d.ts +167 -28
  59. package/dist/schemas/cancel.js +119 -19
  60. package/dist/schemas/common.d.ts +427 -208
  61. package/dist/schemas/common.js +3 -1
  62. package/dist/schemas/completion-event.d.ts +14 -0
  63. package/dist/schemas/completion-event.js +11 -1
  64. package/dist/schemas/completion-stream.d.ts +15 -1
  65. package/dist/schemas/completion-stream.js +25 -7
  66. package/dist/schemas/download-asset.d.ts +15 -9
  67. package/dist/schemas/download-asset.js +17 -6
  68. package/dist/schemas/embed.d.ts +1 -0
  69. package/dist/schemas/embed.js +5 -0
  70. package/dist/schemas/error.d.ts +31 -0
  71. package/dist/schemas/error.js +29 -1
  72. package/dist/schemas/finetune.d.ts +2 -0
  73. package/dist/schemas/finetune.js +5 -0
  74. package/dist/schemas/get-model-info.d.ts +6 -6
  75. package/dist/schemas/llamacpp-config.d.ts +54 -8
  76. package/dist/schemas/llamacpp-config.js +12 -0
  77. package/dist/schemas/load-model.d.ts +1911 -1260
  78. package/dist/schemas/load-model.js +15 -0
  79. package/dist/schemas/model-src-utils.d.ts +14 -14
  80. package/dist/schemas/model-types.d.ts +10 -10
  81. package/dist/schemas/ocr.d.ts +3 -3
  82. package/dist/schemas/plugin.d.ts +40 -1
  83. package/dist/schemas/plugin.js +10 -1
  84. package/dist/schemas/rag.d.ts +9 -0
  85. package/dist/schemas/rag.js +17 -9
  86. package/dist/schemas/registry.d.ts +30 -30
  87. package/dist/schemas/reload-config.d.ts +14 -14
  88. package/dist/schemas/sdcpp-config.d.ts +131 -17
  89. package/dist/schemas/sdcpp-config.js +163 -1
  90. package/dist/schemas/sdk-config.d.ts +649 -271
  91. package/dist/schemas/sdk-errors-client.d.ts +1 -0
  92. package/dist/schemas/sdk-errors-client.js +5 -0
  93. package/dist/schemas/sdk-errors-server.d.ts +5 -0
  94. package/dist/schemas/sdk-errors-server.js +25 -0
  95. package/dist/schemas/text-to-speech.d.ts +78 -78
  96. package/dist/schemas/transcription-config.d.ts +24 -24
  97. package/dist/schemas/transcription.d.ts +56 -2
  98. package/dist/schemas/transcription.js +27 -0
  99. package/dist/schemas/translate.d.ts +2 -0
  100. package/dist/schemas/translate.js +13 -2
  101. package/dist/schemas/translation-config.d.ts +40 -40
  102. package/dist/schemas/unload-model.d.ts +2 -1
  103. package/dist/schemas/unload-model.js +4 -1
  104. package/dist/scripts/run-unit-tests.js +15 -2
  105. package/dist/server/bare/delegate-rpc-client.js +10 -8
  106. package/dist/server/bare/ops/cancel.d.ts +27 -1
  107. package/dist/server/bare/ops/cancel.js +36 -10
  108. package/dist/server/bare/ops/embed.d.ts +3 -3
  109. package/dist/server/bare/ops/embed.js +144 -28
  110. package/dist/server/bare/ops/kv-cache-utils.d.ts +0 -7
  111. package/dist/server/bare/ops/kv-cache-utils.js +8 -47
  112. package/dist/server/bare/ops/transcribe.d.ts +10 -5
  113. package/dist/server/bare/ops/transcribe.js +196 -41
  114. package/dist/server/bare/ops/translate.d.ts +1 -1
  115. package/dist/server/bare/ops/translate.js +197 -88
  116. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.d.ts +12 -3
  117. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +170 -172
  118. package/dist/server/bare/plugins/llamacpp-completion/ops/finetune.js +125 -21
  119. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-session.d.ts +154 -0
  120. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-session.js +448 -0
  121. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.d.ts +21 -73
  122. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.js +18 -101
  123. package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +30 -3
  124. package/dist/server/bare/plugins/llamacpp-completion/plugin.js +157 -85
  125. package/dist/server/bare/plugins/llamacpp-completion/transform.d.ts +10 -0
  126. package/dist/server/bare/plugins/llamacpp-completion/transform.js +34 -0
  127. package/dist/server/bare/plugins/llamacpp-embedding/plugin.d.ts +7 -0
  128. package/dist/server/bare/plugins/llamacpp-embedding/plugin.js +10 -1
  129. package/dist/server/bare/plugins/nmtcpp-translation/plugin.d.ts +17 -15
  130. package/dist/server/bare/plugins/nmtcpp-translation/plugin.js +5 -1
  131. package/dist/server/bare/plugins/onnx-ocr/plugin.d.ts +3 -3
  132. package/dist/server/bare/plugins/onnx-ocr/plugin.js +3 -0
  133. package/dist/server/bare/plugins/onnx-tts/plugin.d.ts +39 -39
  134. package/dist/server/bare/plugins/onnx-tts/plugin.js +6 -0
  135. package/dist/server/bare/plugins/parakeet-transcription/plugin.d.ts +29 -21
  136. package/dist/server/bare/plugins/parakeet-transcription/plugin.js +4 -1
  137. package/dist/server/bare/plugins/sdcpp-generation/ops/diffusion.js +8 -0
  138. package/dist/server/bare/plugins/sdcpp-generation/ops/upscale.d.ts +3 -0
  139. package/dist/server/bare/plugins/sdcpp-generation/ops/upscale.js +40 -0
  140. package/dist/server/bare/plugins/sdcpp-generation/plugin.d.ts +91 -16
  141. package/dist/server/bare/plugins/sdcpp-generation/plugin.js +97 -7
  142. package/dist/server/bare/plugins/whispercpp-transcription/plugin.d.ts +22 -3
  143. package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +50 -14
  144. package/dist/server/bare/rag-hyperdb/index.d.ts +1 -1
  145. package/dist/server/bare/rag-hyperdb/index.js +1 -1
  146. package/dist/server/bare/rag-hyperdb/rag-operation-manager.d.ts +26 -4
  147. package/dist/server/bare/rag-hyperdb/rag-operation-manager.js +65 -28
  148. package/dist/server/bare/runtime/disposable-scope.d.ts +36 -0
  149. package/dist/server/bare/runtime/disposable-scope.js +69 -0
  150. package/dist/server/bare/runtime/index.d.ts +8 -0
  151. package/dist/server/bare/runtime/index.js +3 -0
  152. package/dist/server/bare/runtime/request-context.d.ts +49 -0
  153. package/dist/server/bare/runtime/request-context.js +1 -0
  154. package/dist/server/bare/runtime/request-id.d.ts +12 -0
  155. package/dist/server/bare/runtime/request-id.js +14 -0
  156. package/dist/server/bare/runtime/request-registry-singleton.d.ts +4 -0
  157. package/dist/server/bare/runtime/request-registry-singleton.js +27 -0
  158. package/dist/server/bare/runtime/request-registry.d.ts +136 -0
  159. package/dist/server/bare/runtime/request-registry.js +297 -0
  160. package/dist/server/bare/runtime/with-request-context.d.ts +22 -0
  161. package/dist/server/bare/runtime/with-request-context.js +53 -0
  162. package/dist/server/bare/types/addon-responses.d.ts +11 -1
  163. package/dist/server/rpc/handler-registry.js +26 -7
  164. package/dist/server/rpc/handlers/cancel-delegated.js +28 -31
  165. package/dist/server/rpc/handlers/cancelHandler.d.ts +30 -1
  166. package/dist/server/rpc/handlers/cancelHandler.js +54 -22
  167. package/dist/server/rpc/handlers/delete-cache.d.ts +9 -0
  168. package/dist/server/rpc/handlers/delete-cache.js +13 -15
  169. package/dist/server/rpc/handlers/download-asset.js +133 -40
  170. package/dist/server/rpc/handlers/index.d.ts +2 -0
  171. package/dist/server/rpc/handlers/index.js +2 -0
  172. package/dist/server/rpc/handlers/load-model/download-manager.d.ts +60 -2
  173. package/dist/server/rpc/handlers/load-model/download-manager.js +141 -8
  174. package/dist/server/rpc/handlers/load-model/handler.js +213 -98
  175. package/dist/server/rpc/handlers/load-model/http.js +3 -3
  176. package/dist/server/rpc/handlers/load-model/hyperdrive.js +1 -1
  177. package/dist/server/rpc/handlers/load-model/registry.js +1 -1
  178. package/dist/server/rpc/handlers/load-model/resolve-session.d.ts +20 -1
  179. package/dist/server/rpc/handlers/load-model/resolve-session.js +6 -5
  180. package/dist/server/rpc/handlers/load-model/resolve.d.ts +3 -2
  181. package/dist/server/rpc/handlers/load-model/resolve.js +9 -6
  182. package/dist/server/rpc/handlers/load-model/types.d.ts +24 -0
  183. package/dist/server/rpc/handlers/rag.js +133 -15
  184. package/dist/server/rpc/handlers/upscale-stream.d.ts +3 -0
  185. package/dist/server/rpc/handlers/upscale-stream.js +4 -0
  186. package/dist/server/utils/completion-normalizer.js +8 -0
  187. package/dist/server/utils/tools/dialect.js +4 -0
  188. package/dist/server/utils/tools/parser.js +16 -1
  189. package/dist/server/utils/tools/parsers/gemma4native.d.ts +4 -0
  190. package/dist/server/utils/tools/parsers/gemma4native.js +60 -0
  191. package/dist/server/utils/tools/parsers/qwen35.d.ts +4 -0
  192. package/dist/server/utils/tools/parsers/qwen35.js +120 -0
  193. package/dist/utils/aggregate-events.d.ts +9 -0
  194. package/dist/utils/aggregate-events.js +18 -3
  195. package/dist/utils/decorate-promise.d.ts +34 -0
  196. package/dist/utils/decorate-promise.js +35 -0
  197. package/dist/utils/errors-client.d.ts +3 -0
  198. package/dist/utils/errors-client.js +5 -0
  199. package/dist/utils/errors-server.d.ts +85 -0
  200. package/dist/utils/errors-server.js +97 -0
  201. package/package.json +20 -15
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=diffusion-esrgan-upscale.d.ts.map
@@ -0,0 +1,78 @@
1
+ import { loadModel, unloadModel, diffusion, SD_V2_1_1B_Q8_0, REALESRGAN_X4PLUS_ANIME_6B, } from "@qvac/sdk";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ // ESRGAN upscale example.
5
+ //
6
+ // Usage:
7
+ // bun run examples/diffusion-esrgan-upscale.ts [esrganSrc] [prompt] [outputDir]
8
+ const esrganArg = process.argv[2];
9
+ const promptArg = process.argv[3];
10
+ const outputDirArg = process.argv[4];
11
+ const esrganModelSrc = esrganArg ??
12
+ REALESRGAN_X4PLUS_ANIME_6B;
13
+ const prompt = promptArg ??
14
+ "an illustrated red fox portrait, clean line art, soft watercolor background, detailed fur, crisp eyes";
15
+ const negative_prompt = "blurry, low quality, watermark, text";
16
+ const outputDir = outputDirArg ?? ".";
17
+ const seed = 42;
18
+ try {
19
+ console.log("Loading SD 2.1 + ESRGAN upscaler...");
20
+ const modelId = await loadModel({
21
+ modelSrc: SD_V2_1_1B_Q8_0,
22
+ modelType: "diffusion",
23
+ modelConfig: {
24
+ prediction: "v",
25
+ upscaler: {
26
+ type: "esrgan",
27
+ model_src: esrganModelSrc,
28
+ tile_size: 128,
29
+ },
30
+ },
31
+ onProgress: (p) => console.log(`Loading: ${p.percentage.toFixed(1)}%`),
32
+ });
33
+ console.log(`Model loaded: ${modelId}`);
34
+ // Source size is intentionally small — each ESRGAN repeat multiplies dimensions.
35
+ const baseParams = {
36
+ modelId,
37
+ prompt,
38
+ negative_prompt,
39
+ width: 128,
40
+ height: 128,
41
+ steps: 5,
42
+ cfg_scale: 7.5,
43
+ seed,
44
+ };
45
+ console.log(`\nGenerating ESRGAN x4 upscale: "${prompt}"`);
46
+ const single = diffusion({ ...baseParams, upscale: true });
47
+ for await (const { step, totalSteps } of single.progressStream) {
48
+ process.stdout.write(`\rStep ${step}/${totalSteps}\x1b[K`);
49
+ }
50
+ console.log();
51
+ const singleBuffers = await single.outputs;
52
+ for (let i = 0; i < singleBuffers.length; i++) {
53
+ const out = path.join(outputDir, `sd2_esrgan_x4_seed${seed}_${i}.png`);
54
+ fs.writeFileSync(out, singleBuffers[i]);
55
+ console.log(`Saved: ${out}`);
56
+ }
57
+ console.log("Stats:", await single.stats);
58
+ console.log("\nGenerating ESRGAN two-pass x16 upscale...");
59
+ const twoPass = diffusion({ ...baseParams, upscale: { repeats: 2 } });
60
+ for await (const { step, totalSteps } of twoPass.progressStream) {
61
+ process.stdout.write(`\rStep ${step}/${totalSteps}\x1b[K`);
62
+ }
63
+ console.log();
64
+ const twoPassBuffers = await twoPass.outputs;
65
+ for (let i = 0; i < twoPassBuffers.length; i++) {
66
+ const out = path.join(outputDir, `sd2_esrgan_x16_seed${seed}_${i}.png`);
67
+ fs.writeFileSync(out, twoPassBuffers[i]);
68
+ console.log(`Saved: ${out}`);
69
+ }
70
+ console.log("Stats:", await twoPass.stats);
71
+ await unloadModel({ modelId, clearStorage: false });
72
+ console.log("Done.");
73
+ process.exit(0);
74
+ }
75
+ catch (error) {
76
+ console.error("❌ Error:", error);
77
+ process.exit(1);
78
+ }
@@ -4,8 +4,11 @@ console.log(`\n💡 Press Ctrl+C to pause the download (it will resume on restar
4
4
  let modelId;
5
5
  let cancelled = false;
6
6
  try {
7
- // Download model with progress tracking and cancellation
8
- await downloadAsset({
7
+ // Download model with progress tracking and cancellation. The
8
+ // `downloadAsset(...)` call returns a *decorated* promise: the
9
+ // promise resolves to the modelId, and the same value carries a
10
+ // synchronous `requestId` field so we can cancel before it settles.
11
+ const download = downloadAsset({
9
12
  assetSrc: LLAMA_3_2_1B_INST_Q4_0,
10
13
  onProgress: (progress) => {
11
14
  const downloadedMB = (progress.downloaded / 1024 / 1024).toFixed(2);
@@ -18,17 +21,14 @@ try {
18
21
  console.log(`📊 Progress: ${percentage}% (${downloadedMB}MB / ${totalMB}MB)`);
19
22
  console.log(progress);
20
23
  cancelled = true;
21
- // Use the downloadKey to cancel
22
- if (progress.downloadKey) {
23
- void cancel({
24
- operation: "downloadAsset",
25
- downloadKey: progress.downloadKey,
26
- // clearCache: true, // Uncomment to delete partial file instead of resuming
27
- });
28
- }
24
+ void cancel({
25
+ requestId: download.requestId,
26
+ // clearCache: true, // Uncomment to delete partial file instead of resuming
27
+ });
29
28
  }
30
29
  },
31
30
  });
31
+ await download;
32
32
  console.log(`\n✅ Model downloaded successfully! Model ID: ${modelId}`);
33
33
  console.log("🎯 Download completed without interruption");
34
34
  void close();
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=embed-multi-gpu.d.ts.map
@@ -0,0 +1,46 @@
1
+ import { loadModel, embed, unloadModel, EMBEDDINGGEMMA_300M_Q8_0 } from "@qvac/sdk";
2
+ // Multi-GPU embedding distributes model layers across multiple GPUs using
3
+ // llama.cpp's built-in split modes. Two strategies are available:
4
+ //
5
+ // - "layer": splits layers and KV cache across GPUs.
6
+ // - "row": splits layers and KV cache across GPUs, and uses tensor parallelism
7
+ // where supported.
8
+ //
9
+ // tensorSplit controls the proportion of work assigned to each GPU.
10
+ // "1,1" distributes evenly across two GPUs; "3,1" assigns 75% to GPU 0.
11
+ //
12
+ // mainGpu selects which GPU is used for the entire model when splitMode is
13
+ // "none", and pins the primary device in multi-GPU mode.
14
+ // Accepts an integer device index (0, 1, ...) or "integrated" / "dedicated".
15
+ try {
16
+ const modelId = await loadModel({
17
+ modelSrc: EMBEDDINGGEMMA_300M_Q8_0,
18
+ modelType: "llamacpp-embedding",
19
+ modelConfig: {
20
+ splitMode: "layer",
21
+ tensorSplit: "1,1",
22
+ mainGpu: 0,
23
+ gpuLayers: 99,
24
+ verbosity: 0,
25
+ },
26
+ });
27
+ const texts = [
28
+ "Multi-GPU embedding distributes layer computation across GPUs.",
29
+ "Each GPU handles a subset of layers, improving throughput for large models.",
30
+ "The tensor-split ratio controls how much work each GPU receives.",
31
+ ];
32
+ for (const text of texts) {
33
+ const { embedding, stats } = await embed({ modelId, text });
34
+ console.log(`Embedded ${text.slice(0, 50)}...`);
35
+ console.log(` Dimensions: ${embedding.length}`);
36
+ if (stats) {
37
+ console.log(` Backend: ${stats.backendDevice}, TPS: ${stats.tokensPerSecond?.toFixed(1)}`);
38
+ }
39
+ }
40
+ await unloadModel({ modelId, clearStorage: false });
41
+ process.exit(0);
42
+ }
43
+ catch (error) {
44
+ console.error("Error:", error);
45
+ process.exit(1);
46
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=llamacpp-multi-gpu.d.ts.map
@@ -0,0 +1,57 @@
1
+ import { completion, loadModel, unloadModel, VERBOSITY, LLAMA_3_2_1B_INST_Q4_0 } from "@qvac/sdk";
2
+ // Multi-GPU inference distributes a model across multiple GPUs using llama.cpp's
3
+ // built-in split modes. Two strategies are available:
4
+ //
5
+ // - "layer": splits layers and KV cache across GPUs.
6
+ // - "row": splits layers and KV cache across GPUs, and uses tensor parallelism
7
+ // where supported.
8
+ //
9
+ // tensor-split controls the proportion of work assigned to each GPU.
10
+ // "1,1" distributes evenly across two GPUs; "3,1" assigns 75% to GPU 0.
11
+ //
12
+ // Usage:
13
+ // bun run bare:example dist/examples/llamacpp-multi-gpu.js
14
+ // bun run bare:example dist/examples/llamacpp-multi-gpu.js '<model-url>'
15
+ const modelSrc = process.argv[2] ?? LLAMA_3_2_1B_INST_Q4_0;
16
+ try {
17
+ const modelId = await loadModel({
18
+ modelSrc,
19
+ modelType: "llm",
20
+ modelConfig: {
21
+ "split-mode": "layer",
22
+ "tensor-split": "1,1",
23
+ "main-gpu": 0,
24
+ ctx_size: 4096,
25
+ gpu_layers: 99,
26
+ verbosity: VERBOSITY.ERROR,
27
+ },
28
+ onProgress: (progress) => {
29
+ if (progress.shardInfo) {
30
+ const { shardInfo } = progress;
31
+ console.log(`Downloading ${shardInfo.shardName} (${shardInfo.currentShard}/${shardInfo.totalShards}) ` +
32
+ `— overall: ${shardInfo.overallPercentage.toFixed(1)}%`);
33
+ }
34
+ else {
35
+ console.log(`Downloading: ${progress.percentage.toFixed(1)}%`);
36
+ }
37
+ },
38
+ });
39
+ const history = [
40
+ {
41
+ role: "user",
42
+ content: "Explain the difference between pipeline and tensor parallelism in one paragraph.",
43
+ },
44
+ ];
45
+ const result = completion({ modelId, history, stream: true });
46
+ for await (const token of result.tokenStream) {
47
+ process.stdout.write(token);
48
+ }
49
+ const stats = await result.stats;
50
+ console.log("\n\nStats:", stats);
51
+ await unloadModel({ modelId, clearStorage: false });
52
+ process.exit(0);
53
+ }
54
+ catch (error) {
55
+ console.error("Error:", error);
56
+ process.exit(1);
57
+ }
@@ -31,24 +31,27 @@ try {
31
31
  console.log(`📄 Processing ${documents.length} documents...\n`);
32
32
  let progressCount = 0;
33
33
  let cancelled = false;
34
+ // Capture the decorated promise so we can cancel by `requestId` (the
35
+ // primary cancel path). For a "cancel everything RAG on this model"
36
+ // sweep, use `cancel({ modelId, kind: "rag" })` instead.
37
+ const ingest = ragIngest({
38
+ modelId,
39
+ workspace: WORKSPACE,
40
+ documents,
41
+ progressInterval: 50,
42
+ onProgress: (stage, current, total) => {
43
+ progressCount++;
44
+ const pct = total > 0 ? Math.round((current / total) * 100) : 0;
45
+ console.log(` [${stage}] ${current}/${total} (${pct}%)`);
46
+ if (!cancelled && stage === "embedding" && current > 10) {
47
+ console.log("\n🛑 Triggering cancellation...\n");
48
+ cancelled = true;
49
+ void cancel({ requestId: ingest.requestId });
50
+ }
51
+ },
52
+ });
34
53
  try {
35
- await ragIngest({
36
- modelId,
37
- workspace: WORKSPACE,
38
- documents,
39
- progressInterval: 50,
40
- onProgress: (stage, current, total) => {
41
- progressCount++;
42
- const pct = total > 0 ? Math.round((current / total) * 100) : 0;
43
- console.log(` [${stage}] ${current}/${total} (${pct}%)`);
44
- // Cancel during embedding stage after a few updates
45
- if (!cancelled && stage === "embedding" && current > 10) {
46
- console.log("\n🛑 Triggering cancellation...\n");
47
- cancelled = true;
48
- void cancel({ operation: "rag", workspace: WORKSPACE });
49
- }
50
- },
51
- });
54
+ await ingest;
52
55
  console.log("\n⚠️ Ingest completed (cancellation didn't interrupt in time)");
53
56
  }
54
57
  catch (error) {
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=llamacpp-tools-gemma4.d.ts.map
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Tool-calling example using the Gemma4 native dialect.
3
+ *
4
+ * Gemma4 emits tool calls in a JS-literal format with custom quote tokens:
5
+ * <|tool_call>call:NAME{key:<|"|>val<|"|>,...}<tool_call|>
6
+ *
7
+ * Reasoning output (thinking) is emitted inside <|channel>thought...<channel|>
8
+ * frames, which are stripped from contentDelta and forwarded as thinkingDelta
9
+ * when captureThinking is true.
10
+ *
11
+ * The dialect is auto-detected from the model name/path when the file name
12
+ * contains "gemma4" or "gemma-4". Pass toolDialect: "gemma4" explicitly to
13
+ * completion() if auto-detection does not pick it up for a given file name.
14
+ *
15
+ * Usage:
16
+ * bun run bare:example dist/examples/tools/llamacpp-tools-gemma4.js <model-url>
17
+ */
18
+ import { completion, loadModel, unloadModel, } from "@qvac/sdk";
19
+ import { tools, mockExecute } from "./shared.js";
20
+ // bartowski's pack tags <eos> as the EOG token (matching the base tokenizer),
21
+ // ensuring generation stops correctly; unsloth's variant maps it differently.
22
+ const GEMMA4_HF = "https://huggingface.co/bartowski/google_gemma-4-E2B-it-GGUF/resolve/main/google_gemma-4-E2B-it-Q4_K_M.gguf";
23
+ const modelSrc = process.argv[2] ?? GEMMA4_HF;
24
+ let modelId;
25
+ try {
26
+ modelId = await loadModel({
27
+ modelSrc,
28
+ modelType: "llm",
29
+ modelConfig: { ctx_size: 4096, tools: true },
30
+ onProgress: (progress) => console.log(`Loading: ${progress.percentage.toFixed(1)}%`),
31
+ });
32
+ console.log(`Model loaded: ${modelId}`);
33
+ const history = [
34
+ {
35
+ role: "system",
36
+ content: "You are a helpful assistant that can call tools to look up weather and horoscopes.",
37
+ },
38
+ {
39
+ role: "user",
40
+ content: "What's the weather in Tokyo and my horoscope for Aquarius?",
41
+ },
42
+ ];
43
+ const result = completion({ modelId, history, stream: true, tools });
44
+ const tokensTask = (async () => {
45
+ for await (const token of result.tokenStream) {
46
+ process.stdout.write(token);
47
+ }
48
+ })();
49
+ const toolsTask = (async () => {
50
+ for await (const evt of result.toolCallStream) {
51
+ if (evt.type === "toolCall") {
52
+ console.log(`\n-> ${evt.call.name}(${JSON.stringify(evt.call.arguments)})`);
53
+ }
54
+ }
55
+ })();
56
+ await Promise.all([tokensTask, toolsTask]);
57
+ const toolCalls = await result.toolCalls;
58
+ console.log("\n\nFinal tool calls:");
59
+ if (toolCalls.length > 0) {
60
+ for (const call of toolCalls) {
61
+ console.log(` - ${call.name}(${JSON.stringify(call.arguments)})`);
62
+ const toolResult = mockExecute(call.name, call.arguments);
63
+ console.log(` result: ${toolResult}`);
64
+ }
65
+ }
66
+ else {
67
+ console.log(" (none)");
68
+ }
69
+ await unloadModel({ modelId, clearStorage: false });
70
+ }
71
+ catch (error) {
72
+ console.error("Error:", error);
73
+ if (modelId)
74
+ await unloadModel({ modelId, clearStorage: false }).catch(() => { });
75
+ process.exit(1);
76
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=llamacpp-tools-qwen35.d.ts.map
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Tool-calling example using the Qwen3.5 dialect.
3
+ *
4
+ * Qwen3.5 emits tool calls in a Pythonic-XML format:
5
+ * <tool_call><function=NAME><parameter=KEY>VALUE</parameter></function></tool_call>
6
+ *
7
+ * The dialect is auto-detected from the model name/path when the model file
8
+ * contains "qwen3.5", "qwen3-5", "qwen3.6", or "qwen3-6". Pass
9
+ * toolDialect: "qwen35" explicitly if auto-detection does not pick it up.
10
+ *
11
+ * Usage:
12
+ * bun run bare:example dist/examples/tools/llamacpp-tools-qwen35.js <model-url>
13
+ */
14
+ import { completion, loadModel, unloadModel, } from "@qvac/sdk";
15
+ import { tools, mockExecute } from "./shared.js";
16
+ const QWEN35_HF = "https://huggingface.co/unsloth/Qwen3.5-0.8B-GGUF/resolve/main/Qwen3.5-0.8B-Q8_0.gguf";
17
+ const modelSrc = process.argv[2] ?? QWEN35_HF;
18
+ let modelId;
19
+ try {
20
+ modelId = await loadModel({
21
+ modelSrc,
22
+ modelType: "llm",
23
+ modelConfig: { ctx_size: 4096, tools: true },
24
+ onProgress: (progress) => console.log(`Loading: ${progress.percentage.toFixed(1)}%`),
25
+ });
26
+ console.log(`Model loaded: ${modelId}`);
27
+ const history = [
28
+ {
29
+ role: "system",
30
+ content: "You are a helpful assistant that can call tools to look up weather and horoscopes.",
31
+ },
32
+ {
33
+ role: "user",
34
+ content: "What's the weather in Tokyo and my horoscope for Aquarius?",
35
+ },
36
+ ];
37
+ const result = completion({ modelId, history, stream: true, tools });
38
+ const tokensTask = (async () => {
39
+ for await (const token of result.tokenStream) {
40
+ process.stdout.write(token);
41
+ }
42
+ })();
43
+ const toolsTask = (async () => {
44
+ for await (const evt of result.toolCallStream) {
45
+ if (evt.type === "toolCall") {
46
+ console.log(`\n-> ${evt.call.name}(${JSON.stringify(evt.call.arguments)})`);
47
+ }
48
+ }
49
+ })();
50
+ await Promise.all([tokensTask, toolsTask]);
51
+ const toolCalls = await result.toolCalls;
52
+ console.log("\n\nFinal tool calls:");
53
+ if (toolCalls.length > 0) {
54
+ for (const call of toolCalls) {
55
+ console.log(` - ${call.name}(${JSON.stringify(call.arguments)})`);
56
+ const toolResult = mockExecute(call.name, call.arguments);
57
+ console.log(` result: ${toolResult}`);
58
+ }
59
+ }
60
+ else {
61
+ console.log(" (none)");
62
+ }
63
+ await unloadModel({ modelId, clearStorage: false });
64
+ }
65
+ catch (error) {
66
+ console.error("Error:", error);
67
+ if (modelId)
68
+ await unloadModel({ modelId, clearStorage: false }).catch(() => { });
69
+ process.exit(1);
70
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=whispercpp-microphone-conversation.d.ts.map
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Microphone → Whisper streaming transcription with conversation events
3
+ * (VAD state updates + end-of-turn detection).
4
+ *
5
+ * Demonstrates the opt-in conversation API:
6
+ * transcribeStream({ modelId, emitVadEvents: true, endOfTurnSilenceMs: N })
7
+ *
8
+ * The session yields a discriminated union of events:
9
+ * - { type: "text", text } transcript chunks
10
+ * - { type: "vad", speaking, probability } VAD state updates
11
+ * - { type: "endOfTurn", silenceDurationMs } silence boundary
12
+ *
13
+ * Speak into your mic; transcripts appear as you pause, VAD ticks while
14
+ * you speak, and an end-of-turn event fires after 800ms of silence.
15
+ * Press Ctrl+C to quit.
16
+ *
17
+ * Requirements: FFmpeg installed, microphone access.
18
+ */
19
+ import { loadModel, unloadModel, transcribeStream, WHISPER_TINY, VAD_SILERO_5_1_2, } from "@qvac/sdk";
20
+ import { spawnSync } from "child_process";
21
+ import { startMicrophone } from "../audio/mic-input";
22
+ const SAMPLE_RATE = 16000;
23
+ try {
24
+ const r = spawnSync("ffmpeg", ["-version"], { stdio: "ignore" });
25
+ if (r.error || r.status !== 0)
26
+ throw new Error("FFmpeg not found");
27
+ }
28
+ catch {
29
+ console.error("❌ Error: FFmpeg is required. Install it and try again.");
30
+ process.exit(1);
31
+ }
32
+ let modelId = null;
33
+ let ffmpeg = null;
34
+ async function cleanup() {
35
+ console.log("\n\nStopping...");
36
+ ffmpeg?.kill();
37
+ if (modelId)
38
+ await unloadModel({ modelId });
39
+ console.log("Done.");
40
+ }
41
+ process.on("SIGINT", () => {
42
+ void cleanup().finally(() => process.exit(0));
43
+ });
44
+ process.on("SIGTERM", () => {
45
+ void cleanup().finally(() => process.exit(0));
46
+ });
47
+ try {
48
+ console.log("Loading model (whisper-tiny + Silero VAD)...");
49
+ modelId = await loadModel({
50
+ modelSrc: WHISPER_TINY,
51
+ modelType: "whisper",
52
+ modelConfig: {
53
+ vadModelSrc: VAD_SILERO_5_1_2,
54
+ audio_format: "f32le",
55
+ strategy: "greedy",
56
+ n_threads: 4,
57
+ language: "en",
58
+ no_timestamps: true,
59
+ suppress_blank: true,
60
+ suppress_nst: true,
61
+ temperature: 0.0,
62
+ vad_params: {
63
+ threshold: 0.6,
64
+ min_speech_duration_ms: 250,
65
+ min_silence_duration_ms: 300,
66
+ max_speech_duration_s: 15.0,
67
+ speech_pad_ms: 100,
68
+ },
69
+ },
70
+ });
71
+ console.log("Model loaded.\n");
72
+ ffmpeg = startMicrophone({ sampleRate: SAMPLE_RATE, format: "f32le" });
73
+ const session = await transcribeStream({
74
+ modelId,
75
+ emitVadEvents: true,
76
+ endOfTurnSilenceMs: 800,
77
+ });
78
+ ffmpeg.stdout.on("data", (chunk) => session.write(chunk));
79
+ console.log("Listening... speak and pause to see transcripts, VAD events, and end-of-turn signals.\n");
80
+ let lastSpeaking = false;
81
+ for await (const event of session) {
82
+ switch (event.type) {
83
+ case "text":
84
+ console.log(`> ${event.text.trim()}`);
85
+ break;
86
+ case "vad":
87
+ if (event.speaking !== lastSpeaking) {
88
+ console.log(`[vad] speaking=${event.speaking} probability=${event.probability.toFixed(2)}`);
89
+ lastSpeaking = event.speaking;
90
+ }
91
+ break;
92
+ case "endOfTurn":
93
+ console.log(`[endOfTurn] silence ${event.silenceDurationMs}ms — turn complete\n`);
94
+ break;
95
+ }
96
+ }
97
+ }
98
+ catch (error) {
99
+ console.error("❌ Error:", error);
100
+ await cleanup();
101
+ process.exit(1);
102
+ }
@@ -12,7 +12,7 @@ try {
12
12
  language: "en",
13
13
  ttsSpeed: 1.05,
14
14
  ttsNumInferenceSteps: 5,
15
- ttsSupertonicMultilingual: false, //false for English quality.
15
+ ttsSupertonicMultilingual: true,
16
16
  ttsTextEncoderSrc: TTS_SUPERTONIC2_OFFICIAL_TEXT_ENCODER_SUPERTONE_FP32.src,
17
17
  ttsDurationPredictorSrc: TTS_SUPERTONIC2_OFFICIAL_DURATION_PREDICTOR_SUPERTONE_FP32.src,
18
18
  ttsVectorEstimatorSrc: TTS_SUPERTONIC2_OFFICIAL_VECTOR_ESTIMATOR_SUPERTONE_FP32.src,
@@ -1,11 +1,27 @@
1
1
  import type { ExpoConfig } from "expo/config";
2
+ declare const MOBILE_HOSTS: string[];
2
3
  /**
3
- * Expo plugin that automatically generates the mobile worker bundle during build.
4
+ * Expo plugin: bundle, verify, then copy the mobile worker bundle.
4
5
  *
5
- * Runs qvac CLI (prefers local @qvac/cli, falls back to npx).
6
- * Uses qvac.config.* if exists, else includes all built-in plugins.
7
- * Output: node_modules/<sdk-package>/dist/worker.mobile.bundle.js
6
+ * Flow: `bundle sdk` -> assert `qvac/worker.bundle.js` exists ->
7
+ * `verify bundle` -> copy to `<sdkPackageDir>/dist/worker.mobile.bundle.js`.
8
+ * Requires a local `@qvac/cli` install. Uses `qvac.config.*` if present.
8
9
  */
9
10
  declare function withMobileBundle(config: ExpoConfig): ExpoConfig;
11
+ /**
12
+ * Resolves the qvac CLI command.
13
+ *
14
+ * Prefers local @qvac/cli installation for version consistency,
15
+ * falls back to npx for convenience when CLI is not installed.
16
+ */
17
+ export declare function resolveCliCommand(projectRoot: string): string;
18
+ /** Builds the `qvac verify bundle` command string (pure helper for tests). */
19
+ export declare function buildVerifyBundleCommand(opts: {
20
+ cliCommand: string;
21
+ bundlePath: string;
22
+ hosts: string[];
23
+ configPath?: string;
24
+ }): string;
25
+ export { MOBILE_HOSTS };
10
26
  export default withMobileBundle;
11
27
  //# sourceMappingURL=withMobileBundle.d.ts.map