@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
@@ -2,9 +2,12 @@ import { z } from "zod";
2
2
  export const unloadModelParamsSchema = z.object({
3
3
  modelId: z.string(),
4
4
  clearStorage: z.boolean().default(false),
5
+ autoClose: z.boolean().optional(),
5
6
  });
6
- export const unloadModelRequestSchema = unloadModelParamsSchema.extend({
7
+ export const unloadModelRequestSchema = z.object({
7
8
  type: z.literal("unloadModel"),
9
+ modelId: z.string(),
10
+ clearStorage: z.boolean().default(false),
8
11
  });
9
12
  export const unloadModelResponseSchema = z.object({
10
13
  type: z.literal("unloadModel"),
@@ -4,10 +4,23 @@ import { spawnSync } from "child_process";
4
4
  import { fileURLToPath } from "url";
5
5
  const __dirname = dirname(fileURLToPath(import.meta.url));
6
6
  const testDir = join(__dirname, "..", "test", "unit");
7
- const testFiles = readdirSync(testDir).filter((f) => f.endsWith(".test.ts"));
7
+ function collectTestFiles(dir) {
8
+ const files = [];
9
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
10
+ const fullPath = join(dir, entry.name);
11
+ if (entry.isDirectory()) {
12
+ files.push(...collectTestFiles(fullPath));
13
+ }
14
+ else if (entry.isFile() && entry.name.endsWith(".test.ts")) {
15
+ files.push(fullPath);
16
+ }
17
+ }
18
+ return files;
19
+ }
20
+ const testFiles = collectTestFiles(testDir);
8
21
  let hasFailure = false;
9
22
  for (const file of testFiles) {
10
- const result = spawnSync("bun", ["run", join(testDir, file)], {
23
+ const result = spawnSync("bun", ["run", file], {
11
24
  stdio: "inherit",
12
25
  });
13
26
  if (result.status !== 0) {
@@ -136,14 +136,16 @@ async function ensureRPCConnection(publicKey, timeout, healthCheckTimeout) {
136
136
  let conn;
137
137
  try {
138
138
  logger.info(`🔗 Establishing direct DHT connection to peer: ${publicKey}${timeout ? `, timeout: ${timeout}ms` : ""}`);
139
- // Ensure the DHT routing table is populated before attempting to look up
140
- // the peer. On a cold swarm the table is nearly empty and findPeer can
141
- // return PEER_NOT_FOUND immediately even when the provider is reachable.
142
- const bootstrapStart = nowMs();
143
- const swarm = getSwarm();
144
- logger.info(`⏳ Waiting for DHT to fully bootstrap before connect...`);
145
- await withTimeout(swarm.dht.fullyBootstrapped(), getRemainingTimeout());
146
- logger.info(`✅ DHT bootstrapped in ${(nowMs() - bootstrapStart).toFixed(0)}ms`);
139
+ // We deliberately do NOT `await swarm.dht.fullyBootstrapped()` here. The
140
+ // earlier guard (added with #1729 to side-step a theoretical PEER_NOT_FOUND
141
+ // on a fully-cold swarm) added a serial 1-3s wait on every first delegated
142
+ // call — measurably regressing `loadModel.delegation.connection` vs 0.9.0
143
+ // (≈3.2× slower in local benches). `getSwarm()` is invoked early during
144
+ // SDK init (registry/runtime), so by the time the consumer reaches this
145
+ // path the routing table is already warm enough; `dht.connect()` also
146
+ // bootstraps on demand if it isn't, so we lose nothing by skipping the
147
+ // explicit await.
148
+ getSwarm();
147
149
  conn = openDhtConnection(publicKey);
148
150
  await waitForOpen(conn, getRemainingTimeout());
149
151
  logger.info(`🍺 Peer connection opened: ${publicKey}`);
@@ -1,3 +1,29 @@
1
1
  import { type CancelInferenceBaseParams } from "../../../schemas/index";
2
- export declare function cancel(params: CancelInferenceBaseParams): Promise<void>;
2
+ import type { RequestKind } from "../runtime/index";
3
+ /**
4
+ * Broad cancel: abort every in-flight request matching `modelId` (and
5
+ * optionally a `kind`). Maps onto `RequestRegistry.cancel({ modelId })`
6
+ * — the registry walks active contexts and aborts each one's signal,
7
+ * which each handler has wired to its own addon-level / async unwind
8
+ * via the registry's `await using ctx = registry.begin(...)` block.
9
+ *
10
+ * Kept as a stable surface alongside the new `cancel({ requestId })`
11
+ * path: the caller may not have a `requestId` to hand (model unload,
12
+ * app shutdown, admin sweeps), and the escape hatch is cheap because
13
+ * the registry already does the matching.
14
+ *
15
+ * Returns the number of contexts whose abort was triggered by *this*
16
+ * call (already-cancelled contexts are skipped so callers can rely on
17
+ * the count to log "n requests cancelled" once). Used by the RPC
18
+ * cancel handler to populate `CancelResponse.cancelled` and by
19
+ * internal server-side callers that want to know whether anything
20
+ * landed.
21
+ *
22
+ * The legacy pre-registry addon-cancel fallback was removed in 0.11.0
23
+ * once every handler had been migrated onto the registry; the function
24
+ * now does exactly one thing — a registry walk.
25
+ */
26
+ export declare function cancel(params: CancelInferenceBaseParams, opts?: {
27
+ kind?: RequestKind;
28
+ }): number;
3
29
  //# sourceMappingURL=cancel.d.ts.map
@@ -1,20 +1,46 @@
1
1
  import { getModel } from "../registry/model-registry.js";
2
2
  import { cancelInferenceBaseSchema, } from "../../../schemas/index.js";
3
3
  import { ModelNotLoadedError } from "../../../utils/errors-server.js";
4
- import { noteCancelRequested } from "../plugins/llamacpp-completion/ops/kv-cache-state.js";
5
- export async function cancel(params) {
4
+ import { getRequestRegistry } from "../runtime/index.js";
5
+ import { getServerLogger } from "../../../logging/index.js";
6
+ const logger = getServerLogger();
7
+ /**
8
+ * Broad cancel: abort every in-flight request matching `modelId` (and
9
+ * optionally a `kind`). Maps onto `RequestRegistry.cancel({ modelId })`
10
+ * — the registry walks active contexts and aborts each one's signal,
11
+ * which each handler has wired to its own addon-level / async unwind
12
+ * via the registry's `await using ctx = registry.begin(...)` block.
13
+ *
14
+ * Kept as a stable surface alongside the new `cancel({ requestId })`
15
+ * path: the caller may not have a `requestId` to hand (model unload,
16
+ * app shutdown, admin sweeps), and the escape hatch is cheap because
17
+ * the registry already does the matching.
18
+ *
19
+ * Returns the number of contexts whose abort was triggered by *this*
20
+ * call (already-cancelled contexts are skipped so callers can rely on
21
+ * the count to log "n requests cancelled" once). Used by the RPC
22
+ * cancel handler to populate `CancelResponse.cancelled` and by
23
+ * internal server-side callers that want to know whether anything
24
+ * landed.
25
+ *
26
+ * The legacy pre-registry addon-cancel fallback was removed in 0.11.0
27
+ * once every handler had been migrated onto the registry; the function
28
+ * now does exactly one thing — a registry walk.
29
+ */
30
+ export function cancel(params, opts) {
6
31
  const { modelId } = cancelInferenceBaseSchema.parse(params);
7
32
  const model = getModel(modelId);
8
33
  if (!model) {
9
34
  throw new ModelNotLoadedError(modelId);
10
35
  }
11
- // Must be recorded *before* `addon.cancel()` so the in-flight
12
- // `completion()` for this model sees the bumped counter when it
13
- // snapshots after `processModelResponse` returns. This is the signal
14
- // that tells `completion()` not to record a `savedCount` for the
15
- // kv-cache on a cancelled turn.
16
- noteCancelRequested(modelId);
17
- if (model.addon && model.addon.cancel) {
18
- await model.addon.cancel();
36
+ const registry = getRequestRegistry();
37
+ const target = opts?.kind ? { modelId, kind: opts.kind } : { modelId };
38
+ const cancelled = registry.cancel(target);
39
+ if (cancelled === 0) {
40
+ // Callers (workbench "Stop" button, app shutdown sweeps) often
41
+ // fire-and-forget; log so operators can see when a broad cancel
42
+ // landed against a registry with nothing in flight on this model.
43
+ logger.debug(`[cancel] no in-flight request matched modelId=${modelId}${opts?.kind ? ` kind=${opts.kind}` : ""}`);
19
44
  }
45
+ return cancelled;
20
46
  }
@@ -6,11 +6,11 @@ export interface EmbedResult {
6
6
  export declare function embed(params: {
7
7
  modelId: string;
8
8
  text: string;
9
- }): Promise<EmbedResult>;
9
+ }, requestId?: string): Promise<EmbedResult>;
10
10
  export declare function embed(params: {
11
11
  modelId: string;
12
12
  text: string[];
13
- }): Promise<EmbedResult>;
14
- export declare function embed(params: EmbedParams): Promise<EmbedResult>;
13
+ }, requestId?: string): Promise<EmbedResult>;
14
+ export declare function embed(params: EmbedParams, requestId?: string): Promise<EmbedResult>;
15
15
  export declare function normalizeVector(vector: Float32Array): number[];
16
16
  //# sourceMappingURL=embed.d.ts.map
@@ -1,40 +1,156 @@
1
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2
+ if (value !== null && value !== void 0) {
3
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
+ var dispose, inner;
5
+ if (async) {
6
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
+ dispose = value[Symbol.asyncDispose];
8
+ }
9
+ if (dispose === void 0) {
10
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
+ dispose = value[Symbol.dispose];
12
+ if (async) inner = dispose;
13
+ }
14
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
15
+ if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
16
+ env.stack.push({ value: value, dispose: dispose, async: async });
17
+ }
18
+ else if (async) {
19
+ env.stack.push({ async: true });
20
+ }
21
+ return value;
22
+ };
23
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
24
+ return function (env) {
25
+ function fail(e) {
26
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
27
+ env.hasError = true;
28
+ }
29
+ var r, s = 0;
30
+ function next() {
31
+ while (r = env.stack.pop()) {
32
+ try {
33
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
34
+ if (r.dispose) {
35
+ var result = r.dispose.call(r.value);
36
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
37
+ }
38
+ else s |= 1;
39
+ }
40
+ catch (e) {
41
+ fail(e);
42
+ }
43
+ }
44
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
45
+ if (env.hasError) throw env.error;
46
+ }
47
+ return next();
48
+ };
49
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
50
+ var e = new Error(message);
51
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
52
+ });
1
53
  import { getModel } from "../registry/model-registry.js";
2
54
  import { embedParamsSchema } from "../../../schemas/index.js";
3
55
  import { buildUnaryResult } from "../../../profiling/model-execution.js";
4
- import { EmbedNoEmbeddingsError, EmbedFailedError, } from "../../../utils/errors-server.js";
56
+ import { EmbedNoEmbeddingsError, EmbedFailedError, InferenceCancelledError, } from "../../../utils/errors-server.js";
5
57
  import { nowMs } from "../../../profiling/index.js";
6
- export async function embed(params) {
7
- const { modelId, text } = embedParamsSchema.parse(params);
8
- const model = getModel(modelId);
9
- const modelStart = nowMs();
10
- const response = (await model.run(text));
11
- const rawEmbeddings = await response.await();
12
- const modelExecutionMs = nowMs() - modelStart;
13
- const stats = {
14
- ...(response.stats?.total_time_ms !== undefined && { totalTime: response.stats.total_time_ms }),
15
- ...(response.stats?.tokens_per_second !== undefined && { tokensPerSecond: response.stats.tokens_per_second }),
16
- ...(response.stats?.total_tokens !== undefined && { totalTokens: response.stats.total_tokens }),
17
- ...(response.stats?.backendDevice !== undefined && { backendDevice: response.stats.backendDevice }),
18
- };
19
- const embeddingsArray = rawEmbeddings[0];
20
- if (Array.isArray(text)) {
21
- if (!embeddingsArray || embeddingsArray.length === 0) {
22
- throw new EmbedNoEmbeddingsError();
58
+ import { getRequestRegistry, withRequestContext, } from "../runtime/index.js";
59
+ import { generateServerRequestId } from "../runtime/request-id.js";
60
+ import { getServerLogger } from "../../../logging/index.js";
61
+ export async function embed(params, requestId) {
62
+ const env_1 = { stack: [], error: void 0, hasError: false };
63
+ try {
64
+ const { modelId, text } = embedParamsSchema.parse(params);
65
+ // Open a request-scoped lifecycle. The registry routes
66
+ // `cancel({ requestId })` and broad `cancel({ modelId, kind: "embeddings" })`
67
+ // straight to this context's signal. Falls back to a server-generated
68
+ // id if the client didn't send one (older releases).
69
+ const ctx = __addDisposableResource(env_1, getRequestRegistry().begin({
70
+ requestId: requestId ?? generateServerRequestId(),
71
+ kind: "embeddings",
72
+ modelId,
73
+ }), true);
74
+ // `requestLogger` is intentionally referenced once so the
75
+ // request-scoped logger is built at handler entry per the canonical
76
+ // shape, even when this op has no per-step emits beyond the
77
+ // registry's own lifecycle lines. Future addon-level warns inside
78
+ // this body should route through `requestLogger`.
79
+ const requestLogger = withRequestContext(getServerLogger(), ctx);
80
+ const model = getModel(modelId);
81
+ // Hard-cancel wiring: llamacpp-embedding declares
82
+ // `cancel: { scope: "model", hard: true }`. The signal listener
83
+ // forwards an abort to the addon so C++ work stops as soon as the
84
+ // user cancels — mirrors the canonical handler shape documented in
85
+ // `request-lifecycle-primitives.mdc`. The post-await
86
+ // `signal.aborted` checks below are the soft-cancel safety net for
87
+ // the case where the abort fires between `model.run(...)` returning
88
+ // and `response.await()` resolving (both can take seconds on large
89
+ // batches).
90
+ const onAbort = () => {
91
+ const addon = model.addon;
92
+ if (addon?.cancel) {
93
+ addon.cancel.call(addon).catch((err) => {
94
+ requestLogger.warn(`[cancel] addon.cancel() rejected during abort for modelId=${modelId}: ${err instanceof Error ? err.message : String(err)}`);
95
+ });
96
+ }
97
+ };
98
+ ctx.signal.addEventListener("abort", onAbort, { once: true });
99
+ // `{ once: true }` does not fire if the signal is already aborted at
100
+ // register time. The registry may abort synchronously when a
101
+ // cancel-before-begin race resolves or the parent signal was pre-
102
+ // aborted — re-use `onAbort` so the listener body is the single
103
+ // source of truth for "what cancel does."
104
+ if (ctx.signal.aborted)
105
+ onAbort();
106
+ ctx.scope.defer(() => {
107
+ ctx.signal.removeEventListener("abort", onAbort);
108
+ });
109
+ const modelStart = nowMs();
110
+ const response = (await model.run(text));
111
+ if (ctx.signal.aborted) {
112
+ throw new InferenceCancelledError(ctx.requestId);
113
+ }
114
+ const rawEmbeddings = await response.await();
115
+ if (ctx.signal.aborted) {
116
+ throw new InferenceCancelledError(ctx.requestId);
117
+ }
118
+ const modelExecutionMs = nowMs() - modelStart;
119
+ const stats = {
120
+ ...(response.stats?.total_time_ms !== undefined && { totalTime: response.stats.total_time_ms }),
121
+ ...(response.stats?.tokens_per_second !== undefined && { tokensPerSecond: response.stats.tokens_per_second }),
122
+ ...(response.stats?.total_tokens !== undefined && { totalTokens: response.stats.total_tokens }),
123
+ ...(response.stats?.backendDevice !== undefined && { backendDevice: response.stats.backendDevice }),
124
+ };
125
+ const embeddingsArray = rawEmbeddings[0];
126
+ if (Array.isArray(text)) {
127
+ if (!embeddingsArray || embeddingsArray.length === 0) {
128
+ throw new EmbedNoEmbeddingsError();
129
+ }
130
+ const embedding = embeddingsArray.map((embeddingVector) => {
131
+ if (!embeddingVector || embeddingVector.length === 0) {
132
+ throw new EmbedNoEmbeddingsError();
133
+ }
134
+ return normalizeVector(embeddingVector);
135
+ });
136
+ return buildUnaryResult({ embedding }, modelExecutionMs, stats);
23
137
  }
24
- const embedding = embeddingsArray.map((embeddingVector) => {
138
+ else {
139
+ const embeddingVector = embeddingsArray?.[0];
25
140
  if (!embeddingVector || embeddingVector.length === 0) {
26
141
  throw new EmbedNoEmbeddingsError();
27
142
  }
28
- return normalizeVector(embeddingVector);
29
- });
30
- return buildUnaryResult({ embedding }, modelExecutionMs, stats);
31
- }
32
- else {
33
- const embeddingVector = embeddingsArray?.[0];
34
- if (!embeddingVector || embeddingVector.length === 0) {
35
- throw new EmbedNoEmbeddingsError();
143
+ return buildUnaryResult({ embedding: normalizeVector(embeddingVector) }, modelExecutionMs, stats);
36
144
  }
37
- return buildUnaryResult({ embedding: normalizeVector(embeddingVector) }, modelExecutionMs, stats);
145
+ }
146
+ catch (e_1) {
147
+ env_1.error = e_1;
148
+ env_1.hasError = true;
149
+ }
150
+ finally {
151
+ const result_1 = __disposeResources(env_1);
152
+ if (result_1)
153
+ await result_1;
38
154
  }
39
155
  }
40
156
  export function normalizeVector(vector) {
@@ -1,10 +1,4 @@
1
1
  import { type CacheMessage } from "../../utils/index";
2
- export declare function markCacheInitialized(modelId: string, configHash: string, cacheKey: string): void;
3
- export declare function isCacheInitialized(modelId: string, configHash: string, cacheKey: string): boolean;
4
- export declare function clearCacheRegistry(scope?: {
5
- cacheKey?: string | undefined;
6
- modelId?: string | undefined;
7
- }): void;
8
2
  export declare function extractSystemPrompt(messages: CacheMessage[]): string | null;
9
3
  export declare function generateConfigHash(systemPrompt: string | null, tools?: unknown): string;
10
4
  export declare function generateCacheKey(messages: CacheMessage[]): string;
@@ -18,7 +12,6 @@ export declare function getCurrentCacheInfo(modelId: string, configHash: string,
18
12
  cachePath: string;
19
13
  }>;
20
14
  export declare function renameCacheFile(oldPath: string, newPath: string): Promise<boolean>;
21
- export declare function customCacheExists(modelId: string, configHash: string, cacheKey: string): Promise<boolean>;
22
15
  export declare function deleteCache(options: {
23
16
  all: true;
24
17
  } | {
@@ -4,37 +4,10 @@ import path from "bare-path";
4
4
  import { getAutoCacheLookupHistory, getKVCacheDir, validateAndJoinPath, } from "../../utils/index.js";
5
5
  import { getServerLogger } from "../../../logging/index.js";
6
6
  const logger = getServerLogger();
7
- // In-memory registry tracks caches initialized this session (addon defers disk writes)
8
- const initializedCaches = new Set();
9
- function getCacheRegistryKey(modelId, configHash, cacheKey) {
10
- return `${modelId}:${configHash}:${cacheKey}`;
11
- }
12
- export function markCacheInitialized(modelId, configHash, cacheKey) {
13
- initializedCaches.add(getCacheRegistryKey(modelId, configHash, cacheKey));
14
- }
15
- export function isCacheInitialized(modelId, configHash, cacheKey) {
16
- return initializedCaches.has(getCacheRegistryKey(modelId, configHash, cacheKey));
17
- }
18
- export function clearCacheRegistry(scope) {
19
- if (!scope || (scope.cacheKey === undefined && scope.modelId === undefined)) {
20
- initializedCaches.clear();
21
- return;
22
- }
23
- // key format: "modelId:configHash:cacheKey"
24
- for (const key of initializedCaches) {
25
- const firstSep = key.indexOf(":");
26
- const secondSep = key.indexOf(":", firstSep + 1);
27
- if (firstSep === -1 || secondSep === -1)
28
- continue;
29
- const modelId = key.slice(0, firstSep);
30
- const cacheKey = key.slice(secondSep + 1);
31
- if (scope.cacheKey !== undefined && cacheKey !== scope.cacheKey)
32
- continue;
33
- if (scope.modelId !== undefined && modelId !== scope.modelId)
34
- continue;
35
- initializedCaches.delete(key);
36
- }
37
- }
7
+ // In-memory KV-cache state lives in `KvCacheSession` (the single
8
+ // mutation point for all three KV-cache bookkeeping layers). This
9
+ // module keeps only the pure path / hash utilities that don't touch
10
+ // in-memory state.
38
11
  export function extractSystemPrompt(messages) {
39
12
  const systemMessage = messages.find((msg) => msg.role === "system");
40
13
  return systemMessage ? systemMessage.content : null;
@@ -107,22 +80,10 @@ export async function renameCacheFile(oldPath, newPath) {
107
80
  return false;
108
81
  }
109
82
  }
110
- export async function customCacheExists(modelId, configHash, cacheKey) {
111
- // Check in-memory registry first (addon defers disk writes)
112
- if (isCacheInitialized(modelId, configHash, cacheKey)) {
113
- return true;
114
- }
115
- // Then check file system (for caches from previous runs)
116
- const cachePath = await getCacheFilePath(modelId, configHash, cacheKey);
117
- try {
118
- await fsPromises.access(cachePath);
119
- markCacheInitialized(modelId, configHash, cacheKey);
120
- return true;
121
- }
122
- catch {
123
- return false;
124
- }
125
- }
83
+ // Cache-existence probing (in-memory registry first, fall back to
84
+ // `fs.access`) lives in `KvCacheSession.beginTurn(...)`. Keeping the
85
+ // in-memory `initializedCaches` set private to the session module
86
+ // avoids drift between the two layers.
126
87
  export async function deleteCache(options) {
127
88
  const cacheDir = getKVCacheDir();
128
89
  if ("all" in options) {
@@ -1,4 +1,4 @@
1
- import { type TranscribeParams, type TranscribeSegment, type TranscribeStats } from "../../../schemas/index";
1
+ import { type TranscribeParams, type TranscribeSegment, type TranscribeStats, type TranscribeStreamEvent } from "../../../schemas/index";
2
2
  import { assertMetadataSupported, toTranscribeSegment, type WhisperAddonSegment } from "../utils/transcribe-metadata";
3
3
  export { assertMetadataSupported, toTranscribeSegment, type WhisperAddonSegment, };
4
4
  type TranscribeReturn = {
@@ -7,8 +7,13 @@ type TranscribeReturn = {
7
7
  };
8
8
  export declare function transcribe(params: TranscribeParams & {
9
9
  metadata: true;
10
- }): AsyncGenerator<TranscribeSegment, TranscribeReturn, void>;
11
- export declare function transcribe(params: TranscribeParams): AsyncGenerator<string, TranscribeReturn, void>;
12
- export declare function transcribeStream(modelId: string, audioInputStream: AsyncIterable<Buffer>, prompt: string | undefined, metadata: true): AsyncGenerator<TranscribeSegment, void, void>;
13
- export declare function transcribeStream(modelId: string, audioInputStream: AsyncIterable<Buffer>, prompt?: string, metadata?: boolean): AsyncGenerator<string, void, void>;
10
+ }, requestId?: string): AsyncGenerator<TranscribeSegment, TranscribeReturn, void>;
11
+ export declare function transcribe(params: TranscribeParams, requestId?: string): AsyncGenerator<string, TranscribeReturn, void>;
12
+ export interface TranscribeStreamOpts {
13
+ emitVadEvents?: boolean;
14
+ endOfTurnSilenceMs?: number;
15
+ vadRunIntervalMs?: number;
16
+ }
17
+ export declare function transcribeStream(modelId: string, audioInputStream: AsyncIterable<Buffer>, prompt: string | undefined, metadata: true, opts?: TranscribeStreamOpts, requestId?: string): AsyncGenerator<TranscribeSegment | TranscribeStreamEvent, void, void>;
18
+ export declare function transcribeStream(modelId: string, audioInputStream: AsyncIterable<Buffer>, prompt?: string, metadata?: boolean, opts?: TranscribeStreamOpts, requestId?: string): AsyncGenerator<string | TranscribeStreamEvent, void, void>;
14
19
  //# sourceMappingURL=transcribe.d.ts.map