@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
@@ -1,10 +1,11 @@
1
1
  import { stream as streamRpc } from "../rpc/rpc-client.js";
2
2
  import { getClientLogger } from "../../logging/index.js";
3
3
  import { completionStreamResponseSchema, } from "../../schemas/index.js";
4
- import { CompletionFailedError } from "../../utils/errors-server.js";
4
+ import { CompletionFailedError, InferenceCancelledError, } from "../../utils/errors-server.js";
5
5
  import { getMcpToolsWithHandlers } from "../../utils/mcp-adapter.js";
6
6
  import { validateTools, } from "../../utils/tool-helpers.js";
7
7
  import { buildFinalFromEvents } from "../../utils/aggregate-events.js";
8
+ import { generateClientRequestId } from "./client-request-id.js";
8
9
  const logger = getClientLogger();
9
10
  /**
10
11
  * Generates completion from a language model based on conversation history.
@@ -27,7 +28,7 @@ const logger = getClientLogger();
27
28
  * @param params.mcp - Optional array of MCP client inputs for tool integration
28
29
  * @param params.captureThinking - Best-effort parsing of `<think>` blocks into `thinkingDelta` events; `final.raw.fullText` always preserves the original output
29
30
  * @param params.emitRawDeltas - When true, every raw model token is also emitted as a `rawDelta` event
30
- * @param params.toolDialect - Override the SDK's name-based dialect detection. Use when your model emits a known format (`"hermes"`, `"pythonic"`, or `"json"`) the auto-router doesn't recognise. Drives both streaming frame detection and finalization parsing.
31
+ * @param params.toolDialect - Override the SDK's name-based dialect detection. Supported values: `"hermes"`, `"pythonic"`, `"json"`, `"harmony"`, `"qwen35"` (Qwen3.5/3.6), `"gemma4"`. Use when the auto-router doesn't recognise your model name. Drives both streaming frame detection and finalization parsing.
31
32
  * Common override case: Llama 3.x tool-calling fine-tunes that emit the native pythonic header (`<|start_header_id|>tool_call<|end_header_id|>...<|eot_id|>`).
32
33
  * @param params.responseFormat - Optional structured-output constraint applied to the model's output:
33
34
  * - `{ type: "text" }` — no constraint (default behavior)
@@ -102,6 +103,13 @@ const logger = getClientLogger();
102
103
  * ```
103
104
  */
104
105
  export function completion(params) {
106
+ // Stable identity for this run, generated client-side so it's
107
+ // available synchronously the moment we return — before the first
108
+ // network round-trip and therefore before the user could possibly
109
+ // have a "stop" handler. Surfaced on the returned `CompletionRun`
110
+ // (`run.requestId`) so callers can `cancel({ requestId })` at any
111
+ // point during the stream.
112
+ const requestId = generateClientRequestId();
105
113
  let statsResolver = () => { };
106
114
  let statsRejecter = () => { };
107
115
  const statsPromise = new Promise((resolve, reject) => {
@@ -182,6 +190,7 @@ export function completion(params) {
182
190
  emitRawDeltas: params.emitRawDeltas,
183
191
  toolDialect: params.toolDialect,
184
192
  responseFormat: params.responseFormat,
193
+ requestId,
185
194
  };
186
195
  const responses = streamRpc(request, params.rpcOptions);
187
196
  for await (const response of responses) {
@@ -202,13 +211,33 @@ export function completion(params) {
202
211
  }
203
212
  notifyWaiters();
204
213
  if (streamResponse.done) {
205
- const { final, error } = buildFinalFromEvents(allEvents, allHandlers);
214
+ const { final, error, cancelled } = buildFinalFromEvents(allEvents, allHandlers);
206
215
  if (error) {
207
216
  const err = new CompletionFailedError(error.message, error);
208
217
  finalRejecter(err);
209
218
  statsRejecter(err);
210
219
  toolCallsRejecter(err);
211
220
  }
221
+ else if (cancelled) {
222
+ // The wire stream ended with `stopReason: "cancelled"` — the
223
+ // run was aborted mid-flight. Cancellation contract: `events`
224
+ // ends normally (consumers iterating `run.events` see the
225
+ // cancelled `completionDone` and exit naturally), and the
226
+ // promise-aggregates reject with `InferenceCancelledError`
227
+ // carrying whatever the aggregator accumulated up to the
228
+ // cancel point. Consumers do `instanceof
229
+ // InferenceCancelledError` and read `.partial.text` /
230
+ // `.partial.toolCalls` / `.partial.stats` if they want the
231
+ // partial output.
232
+ const err = new InferenceCancelledError(requestId, {
233
+ text: final.contentText,
234
+ toolCalls: final.toolCalls,
235
+ ...(final.stats && { stats: final.stats }),
236
+ });
237
+ finalRejecter(err);
238
+ statsRejecter(err);
239
+ toolCallsRejecter(err);
240
+ }
212
241
  else {
213
242
  finalResolver(final);
214
243
  statsResolver(final.stats);
@@ -291,6 +320,7 @@ export function completion(params) {
291
320
  }
292
321
  })();
293
322
  return {
323
+ requestId,
294
324
  events: eventStream,
295
325
  final: finalPromise,
296
326
  tokenStream,
@@ -308,6 +338,7 @@ export function completion(params) {
308
338
  //Empty generator for non-streaming mode
309
339
  })();
310
340
  return {
341
+ requestId,
311
342
  events: eventStream,
312
343
  final: finalPromise,
313
344
  tokenStream,
@@ -34,6 +34,52 @@ interface DiffusionResult {
34
34
  * // modelConfig: { prediction: "flux2_flow" } })`).
35
35
  * const { outputs } = diffusion({ modelId, prompt: "turn into watercolor", init_image: initImage });
36
36
  *
37
+ * // FLUX.2 multi-reference fusion
38
+ * // IMPORTANT: requires the model loaded with `modelConfig: { prediction: "flux2_flow" }`
39
+ * // and a Qwen3 text encoder via `llmModelSrc` (same loadModel requirements as the
40
+ * // FLUX.2 img2img example above). `init_image` and `init_images` are mutually
41
+ * // exclusive — pass one or the other, not both.
42
+ * const refA = fs.readFileSync("scientist-a.jpg");
43
+ * const refB = fs.readFileSync("scientist-b.jpg");
44
+ * const { outputs } = diffusion({
45
+ * modelId,
46
+ * prompt: "a portrait using most visual traits from @image1 and the eyes from @image2",
47
+ * init_images: [refA, refB],
48
+ * width: 768,
49
+ * height: 768,
50
+ * });
51
+ *
52
+ * // LoRA adapter for this generation (absolute path required).
53
+ * // Persistence across subsequent diffusion() calls is controlled at
54
+ * // loadModel time via `modelConfig.lora_apply_mode`.
55
+ * const { outputs } = diffusion({
56
+ * modelId,
57
+ * prompt: "a watercolor cat",
58
+ * lora: "/home/user/loras/watercolor.safetensors",
59
+ * });
60
+ *
61
+ * // ESRGAN upscale; requires the model to be loaded with `modelConfig.upscaler.model_src` set.
62
+ * const { outputs: singleOutputs } = diffusion({
63
+ * modelId,
64
+ * prompt: "a fox portrait",
65
+ * width: 128,
66
+ * height: 128,
67
+ * upscale: true, // one native-scale pass
68
+ * });
69
+ * const single = await singleOutputs;
70
+ * fs.writeFileSync("upscaled.png", single[0]);
71
+ *
72
+ * // Repeat upscale passes when needed.
73
+ * const { outputs: hiresOutputs } = diffusion({
74
+ * modelId,
75
+ * prompt: "a fox portrait",
76
+ * width: 128,
77
+ * height: 128,
78
+ * upscale: { repeats: 2 },
79
+ * });
80
+ * const hires = await hiresOutputs;
81
+ * fs.writeFileSync("hires.png", hires[0]);
82
+ *
37
83
  * // With progress tracking
38
84
  * const { progressStream, outputs } = diffusion({ modelId, prompt: "a cat" });
39
85
  * for await (const { step, totalSteps } of progressStream) {
@@ -26,6 +26,52 @@ import { decodeBase64, encodeBase64 } from "../../utils/encoding.js";
26
26
  * // modelConfig: { prediction: "flux2_flow" } })`).
27
27
  * const { outputs } = diffusion({ modelId, prompt: "turn into watercolor", init_image: initImage });
28
28
  *
29
+ * // FLUX.2 multi-reference fusion
30
+ * // IMPORTANT: requires the model loaded with `modelConfig: { prediction: "flux2_flow" }`
31
+ * // and a Qwen3 text encoder via `llmModelSrc` (same loadModel requirements as the
32
+ * // FLUX.2 img2img example above). `init_image` and `init_images` are mutually
33
+ * // exclusive — pass one or the other, not both.
34
+ * const refA = fs.readFileSync("scientist-a.jpg");
35
+ * const refB = fs.readFileSync("scientist-b.jpg");
36
+ * const { outputs } = diffusion({
37
+ * modelId,
38
+ * prompt: "a portrait using most visual traits from @image1 and the eyes from @image2",
39
+ * init_images: [refA, refB],
40
+ * width: 768,
41
+ * height: 768,
42
+ * });
43
+ *
44
+ * // LoRA adapter for this generation (absolute path required).
45
+ * // Persistence across subsequent diffusion() calls is controlled at
46
+ * // loadModel time via `modelConfig.lora_apply_mode`.
47
+ * const { outputs } = diffusion({
48
+ * modelId,
49
+ * prompt: "a watercolor cat",
50
+ * lora: "/home/user/loras/watercolor.safetensors",
51
+ * });
52
+ *
53
+ * // ESRGAN upscale; requires the model to be loaded with `modelConfig.upscaler.model_src` set.
54
+ * const { outputs: singleOutputs } = diffusion({
55
+ * modelId,
56
+ * prompt: "a fox portrait",
57
+ * width: 128,
58
+ * height: 128,
59
+ * upscale: true, // one native-scale pass
60
+ * });
61
+ * const single = await singleOutputs;
62
+ * fs.writeFileSync("upscaled.png", single[0]);
63
+ *
64
+ * // Repeat upscale passes when needed.
65
+ * const { outputs: hiresOutputs } = diffusion({
66
+ * modelId,
67
+ * prompt: "a fox portrait",
68
+ * width: 128,
69
+ * height: 128,
70
+ * upscale: { repeats: 2 },
71
+ * });
72
+ * const hires = await hiresOutputs;
73
+ * fs.writeFileSync("hires.png", hires[0]);
74
+ *
29
75
  * // With progress tracking
30
76
  * const { progressStream, outputs } = diffusion({ modelId, prompt: "a cat" });
31
77
  * for await (const { step, totalSteps } of progressStream) {
@@ -35,10 +81,13 @@ import { decodeBase64, encodeBase64 } from "../../utils/encoding.js";
35
81
  * ```
36
82
  */
37
83
  export function diffusion(params) {
38
- const { init_image, ...rest } = params;
84
+ const { init_image, init_images, ...rest } = params;
39
85
  const request = {
40
86
  ...rest,
41
87
  ...(init_image !== undefined && { init_image: encodeBase64(init_image) }),
88
+ ...(init_images !== undefined && {
89
+ init_images: init_images.map(encodeBase64),
90
+ }),
42
91
  type: "diffusionStream",
43
92
  };
44
93
  let statsResolver = () => { };
@@ -13,7 +13,9 @@ export type DownloadAssetOptions = BaseDownloadAssetOptions;
13
13
  * - onProgress: Optional callback for download progress
14
14
  * @param rpcOptions - Optional RPC options including per-call profiling configuration
15
15
  *
16
- * @returns Promise that resolves to the asset ID (either the provided assetSrc or a generated ID)
16
+ * @returns Promise that resolves to the asset ID (either the provided assetSrc or a generated ID),
17
+ * decorated with a synchronous `requestId` field for use with
18
+ * `cancel({ requestId: op.requestId })` before the promise resolves.
17
19
  *
18
20
  * @throws {QvacErrorBase} When asset download fails, with details in the error message
19
21
  * @throws {QvacErrorBase} When streaming ends unexpectedly (only when using onProgress)
@@ -34,7 +36,15 @@ export type DownloadAssetOptions = BaseDownloadAssetOptions;
34
36
  * console.log(`Downloaded: ${progress.percentage}%`);
35
37
  * }
36
38
  * });
39
+ *
40
+ * // Targeted cancel by requestId — grab the id synchronously, then
41
+ * // cancel before the download resolves.
42
+ * const op = downloadAsset({ assetSrc: "https://example.com/large.gguf" });
43
+ * setTimeout(() => cancel({ requestId: op.requestId }), 1000);
44
+ * await op; // rejects with `InferenceCancelledError`
37
45
  * ```
38
46
  */
39
- export declare function downloadAsset(options: DownloadAssetOptions, rpcOptions?: RPCOptions): Promise<string>;
47
+ export declare function downloadAsset(options: DownloadAssetOptions, rpcOptions?: RPCOptions): Promise<string> & {
48
+ requestId: string;
49
+ };
40
50
  //# sourceMappingURL=download-asset.d.ts.map
@@ -1,6 +1,8 @@
1
1
  import { send, stream } from "../rpc/rpc-client.js";
2
2
  import { downloadAssetOptionsToRequestSchema, } from "../../schemas/index.js";
3
3
  import { DownloadAssetFailedError, StreamEndedError, InvalidResponseError, } from "../../utils/errors-client.js";
4
+ import { decoratePromise } from "../../utils/decorate-promise.js";
5
+ import { generateClientRequestId } from "./client-request-id.js";
4
6
  /**
5
7
  * Downloads an asset (model file) without loading it into memory.
6
8
  *
@@ -14,7 +16,9 @@ import { DownloadAssetFailedError, StreamEndedError, InvalidResponseError, } fro
14
16
  * - onProgress: Optional callback for download progress
15
17
  * @param rpcOptions - Optional RPC options including per-call profiling configuration
16
18
  *
17
- * @returns Promise that resolves to the asset ID (either the provided assetSrc or a generated ID)
19
+ * @returns Promise that resolves to the asset ID (either the provided assetSrc or a generated ID),
20
+ * decorated with a synchronous `requestId` field for use with
21
+ * `cancel({ requestId: op.requestId })` before the promise resolves.
18
22
  *
19
23
  * @throws {QvacErrorBase} When asset download fails, with details in the error message
20
24
  * @throws {QvacErrorBase} When streaming ends unexpectedly (only when using onProgress)
@@ -35,10 +39,24 @@ import { DownloadAssetFailedError, StreamEndedError, InvalidResponseError, } fro
35
39
  * console.log(`Downloaded: ${progress.percentage}%`);
36
40
  * }
37
41
  * });
42
+ *
43
+ * // Targeted cancel by requestId — grab the id synchronously, then
44
+ * // cancel before the download resolves.
45
+ * const op = downloadAsset({ assetSrc: "https://example.com/large.gguf" });
46
+ * setTimeout(() => cancel({ requestId: op.requestId }), 1000);
47
+ * await op; // rejects with `InferenceCancelledError`
38
48
  * ```
39
49
  */
40
- export async function downloadAsset(options, rpcOptions) {
41
- const request = downloadAssetOptionsToRequestSchema.parse(options);
50
+ export function downloadAsset(options, rpcOptions) {
51
+ const requestId = generateClientRequestId();
52
+ const inner = runDownloadAsset(options, requestId, rpcOptions);
53
+ return decoratePromise(inner, { requestId });
54
+ }
55
+ async function runDownloadAsset(options, requestId, rpcOptions) {
56
+ const request = downloadAssetOptionsToRequestSchema.parse({
57
+ ...options,
58
+ requestId,
59
+ });
42
60
  if (options.onProgress) {
43
61
  // Use streaming for progress updates
44
62
  for await (const response of stream(request, rpcOptions)) {
@@ -7,7 +7,7 @@ import { type EmbedStats, type RPCOptions } from "../../schemas/index";
7
7
  * @param params.modelId - The identifier of the embedding model to use
8
8
  * @param params.text - The input text to embed
9
9
  * @param options - Optional RPC options including per-call profiling
10
- * @returns A promise resolving to an object with `embedding` (a single `number[]` vector) and optional `stats` performance data.
10
+ * @returns A promise (decorated with `requestId`) resolving to an object with `embedding` (a single `number[]` vector) and optional `stats` performance data.
11
11
  * @throws {QvacErrorBase} When the response type is invalid or when the embedding fails
12
12
  */
13
13
  export declare function embed(params: {
@@ -16,7 +16,9 @@ export declare function embed(params: {
16
16
  }, options?: RPCOptions): Promise<{
17
17
  embedding: number[];
18
18
  stats?: EmbedStats;
19
- }>;
19
+ }> & {
20
+ requestId: string;
21
+ };
20
22
  /**
21
23
  * Generates embeddings for multiple texts using a specified model.
22
24
  *
@@ -25,7 +27,7 @@ export declare function embed(params: {
25
27
  * @param params.modelId - The identifier of the embedding model to use
26
28
  * @param params.text - The input texts to embed
27
29
  * @param options - Optional RPC options including per-call profiling
28
- * @returns A promise resolving to an object with `embedding` (one `number[]` vector per input text, i.e. `number[][]`) and optional `stats` performance data.
30
+ * @returns A promise (decorated with `requestId`) resolving to an object with `embedding` (one `number[]` vector per input text, i.e. `number[][]`) and optional `stats` performance data.
29
31
  * @throws {QvacErrorBase} When the response type is invalid or when the embedding fails
30
32
  */
31
33
  export declare function embed(params: {
@@ -34,5 +36,7 @@ export declare function embed(params: {
34
36
  }, options?: RPCOptions): Promise<{
35
37
  embedding: number[][];
36
38
  stats?: EmbedStats;
37
- }>;
39
+ }> & {
40
+ requestId: string;
41
+ };
38
42
  //# sourceMappingURL=embed.d.ts.map
@@ -1,10 +1,23 @@
1
1
  import { send } from "../rpc/rpc-client.js";
2
2
  import {} from "../../schemas/index.js";
3
3
  import { InvalidResponseError } from "../../utils/errors-client.js";
4
- export async function embed(params, options) {
4
+ import { decoratePromise } from "../../utils/decorate-promise.js";
5
+ import { generateClientRequestId } from "./client-request-id.js";
6
+ export function embed(params, options) {
7
+ // Client-generated `requestId` is surfaced synchronously on the
8
+ // returned promise so the caller can `cancel({ requestId })` before
9
+ // `await` resolves. The same id is threaded onto the wire envelope so
10
+ // the server's registry entry uses it as the canonical key —
11
+ // matching the `loadModel` / `downloadAsset` / `completion` shape.
12
+ const requestId = generateClientRequestId();
13
+ const inner = runEmbed(params, requestId, options);
14
+ return decoratePromise(inner, { requestId });
15
+ }
16
+ async function runEmbed(params, requestId, options) {
5
17
  const request = {
6
18
  type: "embed",
7
19
  ...params,
20
+ requestId,
8
21
  };
9
22
  const response = await send(request, options);
10
23
  if (response.type !== "embed") {
@@ -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" | "llm" | "whisper" | "nmt" | "parakeet" | "tts" | "ocr" | "diffusion" | "vad" | "other";
15
+ addon: "embeddings" | "diffusion" | "tts" | "ocr" | "llm" | "whisper" | "nmt" | "parakeet" | "vad" | "other";
16
16
  isCached: boolean;
17
17
  isLoaded: boolean;
18
18
  cacheFiles: {
@@ -19,6 +19,7 @@ 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 { upscale } from "./upscale";
22
23
  export { modelRegistryList, modelRegistrySearch, modelRegistryGetModel, type ModelRegistrySearchParams, } from "./registry";
23
24
  export { suspend } from "./suspend";
24
25
  export { resume } from "./resume";
@@ -19,6 +19,7 @@ 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 { upscale } from "./upscale.js";
22
23
  export { modelRegistryList, modelRegistrySearch, modelRegistryGetModel, } from "./registry.js";
23
24
  export { suspend } from "./suspend.js";
24
25
  export { resume } from "./resume.js";
@@ -17,7 +17,9 @@ import { type LoadModelOptions, type LoadCustomPluginModelOptions, type LoadMode
17
17
  * await loadModel({ modelSrc: WHISPER_TINY });
18
18
  * ```
19
19
  */
20
- export declare function loadModel<S extends ModelDescriptor>(options: LoadModelDescriptorParam<S>, rpcOptions?: RPCOptions): Promise<string>;
20
+ export declare function loadModel<S extends ModelDescriptor>(options: LoadModelDescriptorParam<S>, rpcOptions?: RPCOptions): Promise<string> & {
21
+ requestId: string;
22
+ };
21
23
  /**
22
24
  * Loads a machine learning model from a local path, remote URL, or Hyperdrive key.
23
25
  *
@@ -110,7 +112,9 @@ export declare function loadModel<S extends ModelDescriptor>(options: LoadModelD
110
112
  * });
111
113
  * ```
112
114
  */
113
- export declare function loadModel(options: LoadModelOptions, rpcOptions?: RPCOptions): Promise<string>;
115
+ export declare function loadModel(options: LoadModelOptions, rpcOptions?: RPCOptions): Promise<string> & {
116
+ requestId: string;
117
+ };
114
118
  /**
115
119
  * Loads a custom plugin model (any non-built-in `modelType` string).
116
120
  * `modelConfig` is plugin-defined; the SDK does not narrow it.
@@ -122,7 +126,9 @@ export declare function loadModel(options: LoadModelOptions, rpcOptions?: RPCOpt
122
126
  * @param rpcOptions - Optional RPC options including per-call profiling.
123
127
  * @returns Promise that resolves to the loaded model ID.
124
128
  */
125
- export declare function loadModel<T extends string>(options: LoadCustomPluginModelOptions<T>, rpcOptions?: RPCOptions): Promise<string>;
129
+ export declare function loadModel<T extends string>(options: LoadCustomPluginModelOptions<T>, rpcOptions?: RPCOptions): Promise<string> & {
130
+ requestId: string;
131
+ };
126
132
  /**
127
133
  * Hot-reloads configuration on an already loaded model.
128
134
  *
@@ -155,5 +161,7 @@ export declare function loadModel<T extends string>(options: LoadCustomPluginMod
155
161
  * });
156
162
  * ```
157
163
  */
158
- export declare function loadModel(options: ReloadConfigOptions, rpcOptions?: RPCOptions): Promise<string>;
164
+ export declare function loadModel(options: ReloadConfigOptions, rpcOptions?: RPCOptions): Promise<string> & {
165
+ requestId: string;
166
+ };
159
167
  //# sourceMappingURL=load-model.d.ts.map
@@ -4,8 +4,26 @@ import { loadModelOptionsToRequestSchema, reloadConfigOptionsToRequestSchema, is
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
+ import { decoratePromise } from "../../utils/decorate-promise.js";
8
+ import { generateClientRequestId } from "./client-request-id.js";
7
9
  const logger = getClientLogger();
8
- export async function loadModel(options, rpcOptions) {
10
+ export function loadModel(options, rpcOptions) {
11
+ // Generate a stable `requestId` once, synchronously, before kicking
12
+ // off any async work. The same id is:
13
+ // - threaded onto the request envelope (`request.requestId`) so the
14
+ // server's `registry.begin(...)` records it on the registry
15
+ // entry; and
16
+ // - attached to the returned promise via `decoratePromise` so the
17
+ // caller can target this exact call with `cancel({ requestId })`
18
+ // before `await` resolves. Generating client-side and surfacing
19
+ // it synchronously is what closes the "stop-button race" gap for
20
+ // `loadModel` / `downloadAsset` callers — same shape as the
21
+ // `CompletionRun.requestId` contract.
22
+ const requestId = generateClientRequestId();
23
+ const inner = runLoadModel(options, requestId, rpcOptions);
24
+ return decoratePromise(inner, { requestId });
25
+ }
26
+ async function runLoadModel(options, requestId, rpcOptions) {
9
27
  const isReloadConfig = "modelId" in options && !("modelSrc" in options);
10
28
  // Infer `modelType` from `modelSrc` when omitted; the schema still validates
11
29
  // the resolved options below.
@@ -28,6 +46,12 @@ export async function loadModel(options, rpcOptions) {
28
46
  logger.warn(`Model type "${modelType}" is an alias and will be deprecated. Use "${canonical}" instead.`);
29
47
  }
30
48
  }
49
+ // Splice the client-generated `requestId` onto the resolved options so
50
+ // the wire envelope carries it. The server uses the same value as the
51
+ // registry-entry key — that match is what makes
52
+ // `cancel({ requestId: op.requestId })` a no-op when no match exists
53
+ // and a precise abort when it does.
54
+ resolvedOptions = { ...resolvedOptions, requestId };
31
55
  const request = isReloadConfig
32
56
  ? reloadConfigOptionsToRequestSchema.parse(resolvedOptions)
33
57
  : loadModelOptionsToRequestSchema.parse(resolvedOptions);
@@ -65,7 +65,9 @@ export declare function ragChunk(params: RagChunkParams, options?: RPCOptions):
65
65
  export declare function ragIngest(params: RagIngestParams, options?: RPCOptions): Promise<{
66
66
  processed: RagSaveEmbeddingsResult[];
67
67
  droppedIndices: number[];
68
- }>;
68
+ }> & {
69
+ requestId: string;
70
+ };
69
71
  /**
70
72
  * Saves pre-embedded documents to the RAG vector database.
71
73
  * Part of the segregated flow: chunk() → embed() → saveEmbeddings()
@@ -99,7 +101,9 @@ export declare function ragIngest(params: RagIngestParams, options?: RPCOptions)
99
101
  * });
100
102
  * ```
101
103
  */
102
- export declare function ragSaveEmbeddings(params: RagSaveEmbeddingsParams, options?: RPCOptions): Promise<RagSaveEmbeddingsResult[]>;
104
+ export declare function ragSaveEmbeddings(params: RagSaveEmbeddingsParams, options?: RPCOptions): Promise<RagSaveEmbeddingsResult[]> & {
105
+ requestId: string;
106
+ };
103
107
  /**
104
108
  * Searches for similar documents in the RAG vector database.
105
109
  *
@@ -186,7 +190,9 @@ export declare function ragDeleteEmbeddings(params: RagDeleteEmbeddingsParams, o
186
190
  * });
187
191
  * ```
188
192
  */
189
- export declare function ragReindex(params: RagReindexParams, options?: RPCOptions): Promise<RagReindexResult>;
193
+ export declare function ragReindex(params: RagReindexParams, options?: RPCOptions): Promise<RagReindexResult> & {
194
+ requestId: string;
195
+ };
190
196
  /**
191
197
  * Lists all RAG workspaces with their open status.
192
198
  *
@@ -1,5 +1,7 @@
1
1
  import { send, stream } from "../rpc/rpc-client.js";
2
2
  import { InvalidResponseError, InvalidOperationError, StreamEndedError, RAGChunkFailedError, RAGSaveFailedError, RAGSearchFailedError, RAGDeleteFailedError, RAGCloseWorkspaceFailedError, RAGListWorkspacesFailedError, } from "../../utils/errors-client.js";
3
+ import { generateClientRequestId } from "./client-request-id.js";
4
+ import { decoratePromise } from "../../utils/decorate-promise.js";
3
5
  // ============== Chunk ==============
4
6
  /**
5
7
  * Chunks documents into smaller pieces for embedding.
@@ -82,7 +84,12 @@ export async function ragChunk(params, options) {
82
84
  * });
83
85
  * ```
84
86
  */
85
- export async function ragIngest(params, options) {
87
+ export function ragIngest(params, options) {
88
+ const requestId = generateClientRequestId();
89
+ const inner = runRagIngest(params, requestId, options);
90
+ return decoratePromise(inner, { requestId });
91
+ }
92
+ async function runRagIngest(params, requestId, options) {
86
93
  const { onProgress, ...requestParams } = params;
87
94
  const request = {
88
95
  type: "rag",
@@ -90,6 +97,7 @@ export async function ragIngest(params, options) {
90
97
  ...requestParams,
91
98
  chunk: requestParams.chunk ?? true,
92
99
  withProgress: onProgress ? true : undefined,
100
+ requestId,
93
101
  };
94
102
  if (onProgress) {
95
103
  // Use streaming for progress updates
@@ -160,13 +168,19 @@ export async function ragIngest(params, options) {
160
168
  * });
161
169
  * ```
162
170
  */
163
- export async function ragSaveEmbeddings(params, options) {
171
+ export function ragSaveEmbeddings(params, options) {
172
+ const requestId = generateClientRequestId();
173
+ const inner = runRagSaveEmbeddings(params, requestId, options);
174
+ return decoratePromise(inner, { requestId });
175
+ }
176
+ async function runRagSaveEmbeddings(params, requestId, options) {
164
177
  const { onProgress, ...requestParams } = params;
165
178
  const request = {
166
179
  type: "rag",
167
180
  operation: "saveEmbeddings",
168
181
  ...requestParams,
169
182
  withProgress: onProgress ? true : undefined,
183
+ requestId,
170
184
  };
171
185
  if (onProgress) {
172
186
  for await (const event of stream(request, options)) {
@@ -321,13 +335,19 @@ export async function ragDeleteEmbeddings(params, options) {
321
335
  * });
322
336
  * ```
323
337
  */
324
- export async function ragReindex(params, options) {
338
+ export function ragReindex(params, options) {
339
+ const requestId = generateClientRequestId();
340
+ const inner = runRagReindex(params, requestId, options);
341
+ return decoratePromise(inner, { requestId });
342
+ }
343
+ async function runRagReindex(params, requestId, options) {
325
344
  const { onProgress, ...requestParams } = params;
326
345
  const request = {
327
346
  type: "rag",
328
347
  operation: "reindex",
329
348
  ...requestParams,
330
349
  withProgress: onProgress ? true : undefined,
350
+ requestId,
331
351
  };
332
352
  if (onProgress) {
333
353
  for await (const event of stream(request, options)) {
@@ -1,4 +1,4 @@
1
- import { type TranscribeClientParams, type RPCOptions, type TranscribeSegment, type TranscribeStreamClientParams, type TranscribeStreamSession, type TranscribeStreamMetadataSession } from "../../schemas/index";
1
+ import { type TranscribeClientParams, type RPCOptions, type TranscribeSegment, type TranscribeStreamClientParams, type TranscribeStreamSession, type TranscribeStreamMetadataSession, type TranscribeStreamConversationSession } 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.
@@ -11,13 +11,21 @@ import { type TranscribeClientParams, type RPCOptions, type TranscribeSegment, t
11
11
  * segments (`{ text, startMs, endMs, append, id }`)
12
12
  * instead of joined text. Whisper engine only.
13
13
  * @param options - Optional RPC options including per-call profiling
14
- * @returns The complete transcribed text, or — when `metadata` is true —
15
- * the list of transcript segments in emission order.
14
+ * @returns A promise (decorated with `requestId`) resolving to the
15
+ * complete transcribed text, or — when `metadata` is true —
16
+ * the list of transcript segments in emission order. The
17
+ * `requestId` is reachable synchronously so callers can target
18
+ * this in-flight transcription with `cancel({ requestId })`
19
+ * before `await` resolves.
16
20
  */
17
21
  export declare function transcribe(params: TranscribeClientParams & {
18
22
  metadata: true;
19
- }, options?: RPCOptions): Promise<TranscribeSegment[]>;
20
- export declare function transcribe(params: TranscribeClientParams, options?: RPCOptions): Promise<string>;
23
+ }, options?: RPCOptions): Promise<TranscribeSegment[]> & {
24
+ requestId: string;
25
+ };
26
+ export declare function transcribe(params: TranscribeClientParams, options?: RPCOptions): Promise<string> & {
27
+ requestId: string;
28
+ };
21
29
  /**
22
30
  * @deprecated Pass audio via `transcribe()` instead. This overload will be
23
31
  * removed in the next major version.
@@ -50,10 +58,14 @@ export declare function transcribeStream(params: TranscribeClientParams, options
50
58
  * objects (`{ text, startMs, endMs, append, id }`)
51
59
  * instead of plain text. Whisper engine only.
52
60
  * @param options - Optional RPC options including per-call profiling.
53
- * @returns A session object: call `write(buffer)` to feed audio,
54
- * iterate with `for await (...)` to receive transcription,
55
- * and `end()` to signal end of audio.
61
+ * @returns A session object: call `write(audioChunk)` with a `Uint8Array`
62
+ * (Node `Buffer` is a `Uint8Array` subtype) to feed audio,
63
+ * iterate with `for await (...)` to receive transcription, and
64
+ * `end()` to signal end of audio.
56
65
  */
66
+ export declare function transcribeStream(params: TranscribeStreamClientParams & {
67
+ emitVadEvents: true;
68
+ }, options?: RPCOptions): Promise<TranscribeStreamConversationSession>;
57
69
  export declare function transcribeStream(params: TranscribeStreamClientParams & {
58
70
  metadata: true;
59
71
  }, options?: RPCOptions): Promise<TranscribeStreamMetadataSession>;