@qvac/sdk 0.6.0 → 0.7.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 (278) hide show
  1. package/LICENSE +1 -24
  2. package/NOTICE +632 -0
  3. package/README.md +2 -1
  4. package/dist/client/api/embed.js +1 -4
  5. package/dist/client/api/get-model-info.d.ts +10 -3
  6. package/dist/client/api/index.d.ts +2 -0
  7. package/dist/client/api/index.js +2 -0
  8. package/dist/client/api/invoke-plugin.d.ts +14 -0
  9. package/dist/client/api/invoke-plugin.js +38 -0
  10. package/dist/client/api/registry.d.ts +14 -0
  11. package/dist/client/api/registry.js +37 -0
  12. package/dist/client/api/transcribe.js +0 -4
  13. package/dist/client/api/unload-model.js +1 -1
  14. package/dist/client/config-loader/resolve-config.node.d.ts +3 -2
  15. package/dist/client/config-loader/resolve-config.node.js +31 -4
  16. package/dist/client/init-hooks.js +2 -1
  17. package/dist/client/rpc/bare-client.d.ts +2 -0
  18. package/dist/client/rpc/bare-client.js +48 -7
  19. package/dist/client/rpc/expo-device-info.d.ts +6 -0
  20. package/dist/client/rpc/expo-device-info.js +32 -0
  21. package/dist/client/rpc/expo-rpc-client.js +9 -32
  22. package/dist/client/rpc/node-rpc-client.d.ts +1 -1
  23. package/dist/client/rpc/node-rpc-client.js +201 -28
  24. package/dist/client/rpc/rpc-client.d.ts +1 -1
  25. package/dist/client/rpc/rpc-client.js +2 -2
  26. package/dist/constants/index.d.ts +1 -0
  27. package/dist/constants/index.js +1 -0
  28. package/dist/constants/registry.d.ts +2 -0
  29. package/dist/constants/registry.js +1 -0
  30. package/dist/examples/cache-management.js +2 -2
  31. package/dist/examples/config/plugins/plugins.config.d.ts +5 -0
  32. package/dist/examples/config/plugins/plugins.config.js +4 -0
  33. package/dist/examples/download-with-blind-relays.js +1 -1
  34. package/dist/examples/llamacpp-multimodal.js +3 -3
  35. package/dist/examples/llamacpp-native-tools.js +2 -2
  36. package/dist/examples/mcp-websearch.js +2 -2
  37. package/dist/examples/multi-model-demo.js +2 -2
  38. package/dist/examples/ocr-fasttext.js +4 -4
  39. package/dist/examples/parallel-download.js +2 -2
  40. package/dist/examples/plugins.d.ts +14 -0
  41. package/dist/examples/plugins.js +129 -0
  42. package/dist/examples/registry-query.d.ts +2 -0
  43. package/dist/examples/registry-query.js +87 -0
  44. package/dist/examples/translation/translation-bergamot-batch.js +2 -2
  45. package/dist/examples/translation/translation-bergamot.js +4 -4
  46. package/dist/examples/translation/translation-opus.js +2 -2
  47. package/dist/examples/translation/translation-stream.js +2 -2
  48. package/dist/examples/tts/chatterbox.d.ts +2 -0
  49. package/dist/examples/tts/chatterbox.js +59 -0
  50. package/dist/examples/tts/supertonic.d.ts +2 -0
  51. package/dist/examples/tts/supertonic.js +51 -0
  52. package/dist/examples/tts/utils.d.ts +17 -0
  53. package/dist/examples/tts/utils.js +93 -0
  54. package/dist/examples/whispercpp-filesystem.js +2 -3
  55. package/dist/examples/whispercpp-microphone-record.js +1 -2
  56. package/dist/examples/whispercpp-prompt.js +2 -3
  57. package/dist/expo/plugins/index.d.ts +3 -0
  58. package/dist/expo/plugins/index.js +3 -0
  59. package/dist/expo/plugins/resolve-sdk-package-dir.d.ts +15 -0
  60. package/dist/expo/plugins/resolve-sdk-package-dir.js +31 -0
  61. package/dist/expo/plugins/withAndroidArchitecture.d.ts +8 -0
  62. package/dist/expo/plugins/withAndroidArchitecture.js +52 -0
  63. package/dist/expo/plugins/withAndroidNdkVersion.d.ts +8 -0
  64. package/dist/expo/plugins/withAndroidNdkVersion.js +31 -0
  65. package/dist/expo/plugins/withDeviceInfo.d.ts +10 -0
  66. package/dist/expo/plugins/withDeviceInfo.js +48 -0
  67. package/dist/expo/plugins/withMobileBundle.d.ts +5 -2
  68. package/dist/expo/plugins/withMobileBundle.js +121 -65
  69. package/dist/expo/plugins/withQvacSDK.d.ts +4 -0
  70. package/dist/expo/plugins/withQvacSDK.js +26 -1
  71. package/dist/index.d.ts +4 -4
  72. package/dist/index.js +5 -5
  73. package/dist/models/{hyperdrive → registry}/index.js +1 -1
  74. package/dist/models/registry/models.d.ts +9056 -0
  75. package/dist/models/registry/models.js +9351 -0
  76. package/dist/models/update-models/codegen.d.ts +3 -0
  77. package/dist/models/update-models/codegen.js +135 -0
  78. package/dist/models/update-models/history.d.ts +13 -0
  79. package/dist/models/update-models/history.js +88 -0
  80. package/dist/models/update-models/index.d.ts +2 -0
  81. package/dist/models/update-models/index.js +124 -0
  82. package/dist/models/update-models/naming.d.ts +4 -0
  83. package/dist/models/update-models/naming.js +314 -0
  84. package/dist/models/update-models/processing.d.ts +8 -0
  85. package/dist/models/update-models/processing.js +67 -0
  86. package/dist/models/update-models/registry.d.ts +4 -0
  87. package/dist/models/update-models/registry.js +67 -0
  88. package/dist/models/update-models/shards.d.ts +4 -0
  89. package/dist/models/update-models/shards.js +57 -0
  90. package/dist/models/update-models/types.d.ts +60 -0
  91. package/dist/models/update-models/types.js +1 -0
  92. package/dist/models/update-models/utils.d.ts +3 -0
  93. package/dist/models/update-models/utils.js +21 -0
  94. package/dist/pear/pre.d.ts +18 -0
  95. package/dist/pear/pre.js +433 -0
  96. package/dist/schemas/common.d.ts +286 -32
  97. package/dist/schemas/common.js +12 -0
  98. package/dist/schemas/download-asset.d.ts +35 -11
  99. package/dist/schemas/download-asset.js +5 -1
  100. package/dist/schemas/engine-addon-map.d.ts +5 -0
  101. package/dist/schemas/engine-addon-map.js +49 -0
  102. package/dist/schemas/get-model-info.d.ts +32 -16
  103. package/dist/schemas/get-model-info.js +17 -8
  104. package/dist/schemas/index.d.ts +4 -1
  105. package/dist/schemas/index.js +4 -4
  106. package/dist/schemas/load-model.d.ts +2224 -900
  107. package/dist/schemas/load-model.js +130 -25
  108. package/dist/schemas/model-src-utils.d.ts +30 -12
  109. package/dist/schemas/model-src-utils.js +5 -2
  110. package/dist/schemas/model-types.d.ts +15 -4
  111. package/dist/schemas/model-types.js +21 -4
  112. package/dist/schemas/path-validation.d.ts +10 -0
  113. package/dist/schemas/path-validation.js +22 -0
  114. package/dist/schemas/plugin.d.ts +180 -0
  115. package/dist/schemas/plugin.js +132 -0
  116. package/dist/schemas/rag.d.ts +2 -2
  117. package/dist/schemas/rag.js +7 -3
  118. package/dist/schemas/registry.d.ts +338 -0
  119. package/dist/schemas/registry.js +91 -0
  120. package/dist/schemas/sdk-errors-client.d.ts +6 -6
  121. package/dist/schemas/sdk-errors-client.js +15 -15
  122. package/dist/schemas/sdk-errors-registry.d.ts +6 -0
  123. package/dist/schemas/sdk-errors-registry.js +8 -0
  124. package/dist/schemas/sdk-errors-server.d.ts +16 -2
  125. package/dist/schemas/sdk-errors-server.js +90 -10
  126. package/dist/schemas/text-to-speech.d.ts +670 -1
  127. package/dist/schemas/text-to-speech.js +51 -2
  128. package/dist/schemas/translate.d.ts +2 -2
  129. package/dist/scripts/run-security-tests-bare.d.ts +2 -0
  130. package/dist/scripts/run-security-tests-bare.js +78 -0
  131. package/dist/scripts/run-security-tests.d.ts +2 -0
  132. package/dist/scripts/run-security-tests.js +22 -0
  133. package/dist/server/bare/delegate-rpc-client.d.ts +6 -0
  134. package/dist/server/bare/delegate-rpc-client.js +136 -56
  135. package/dist/server/bare/{addons/llamacpp-embedding/handlers → ops}/embed.d.ts +1 -1
  136. package/dist/server/bare/{addons/llamacpp-embedding/handlers → ops}/embed.js +3 -3
  137. package/dist/server/bare/{addons/llamacpp-completion → ops}/kv-cache-utils.js +6 -6
  138. package/dist/server/bare/{addons → ops}/load-model.js +32 -42
  139. package/dist/server/bare/{addons/nmtcpp-translation/handlers → ops}/translate.d.ts +1 -1
  140. package/dist/server/bare/{addons/nmtcpp-translation/handlers → ops}/translate.js +5 -4
  141. package/dist/server/bare/plugins/index.d.ts +7 -0
  142. package/dist/server/bare/plugins/index.js +6 -0
  143. package/dist/server/bare/{addons/llamacpp-completion → plugins/llamacpp-completion/ops}/cache-logger.js +1 -1
  144. package/dist/server/bare/{addons/llamacpp-completion/handlers → plugins/llamacpp-completion/ops}/completion-stream.d.ts +1 -1
  145. package/dist/server/bare/{addons/llamacpp-completion/handlers → plugins/llamacpp-completion/ops}/completion-stream.js +2 -3
  146. package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +115 -0
  147. package/dist/server/bare/plugins/llamacpp-completion/plugin.js +142 -0
  148. package/dist/server/bare/plugins/llamacpp-embedding/plugin.d.ts +24 -0
  149. package/dist/server/bare/plugins/llamacpp-embedding/plugin.js +73 -0
  150. package/dist/server/bare/plugins/nmtcpp-translation/plugin.d.ts +45 -0
  151. package/dist/server/bare/plugins/nmtcpp-translation/plugin.js +97 -0
  152. package/dist/server/bare/{addons/onnx-ocr/handlers → plugins/onnx-ocr/ops}/ocr-stream.js +2 -1
  153. package/dist/server/bare/plugins/onnx-ocr/plugin.d.ts +38 -0
  154. package/dist/server/bare/{addons/onnx-ocr/create-model.js → plugins/onnx-ocr/plugin.js} +39 -2
  155. package/dist/server/bare/{addons/onnx-tts/handlers → plugins/onnx-tts/ops}/text-to-speech.js +23 -1
  156. package/dist/server/bare/plugins/onnx-tts/plugin.d.ts +26 -0
  157. package/dist/server/bare/plugins/onnx-tts/plugin.js +162 -0
  158. package/dist/server/bare/plugins/onnx-tts/wav-helper.d.ts +14 -0
  159. package/dist/server/bare/plugins/onnx-tts/wav-helper.js +107 -0
  160. package/dist/server/bare/plugins/whispercpp-transcription/ops/transcribe-stream.d.ts +3 -0
  161. package/dist/server/bare/{addons/whispercpp-transcription/handlers → plugins/whispercpp-transcription/ops}/transcribe-stream.js +1 -2
  162. package/dist/server/bare/plugins/whispercpp-transcription/plugin.d.ts +31 -0
  163. package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +74 -0
  164. package/dist/server/bare/rag-hyperdb/handlers/ingest.js +1 -1
  165. package/dist/server/bare/rag-hyperdb/handlers/search.js +1 -1
  166. package/dist/server/bare/rag-hyperdb/rag-workspace-manager.js +2 -1
  167. package/dist/server/bare/registry/config-registry.js +1 -1
  168. package/dist/server/bare/registry/model-config-utils.js +0 -11
  169. package/dist/server/bare/registry/registry-client.d.ts +5 -0
  170. package/dist/server/bare/registry/registry-client.js +37 -0
  171. package/dist/server/env.d.ts +22 -0
  172. package/dist/server/env.js +57 -0
  173. package/dist/server/plugins/index.d.ts +2 -0
  174. package/dist/server/plugins/index.js +1 -0
  175. package/dist/server/plugins/registry.d.ts +9 -0
  176. package/dist/server/plugins/registry.js +75 -0
  177. package/dist/server/rpc/delegate-transport.d.ts +11 -0
  178. package/dist/server/rpc/delegate-transport.js +60 -0
  179. package/dist/server/rpc/handle-request.d.ts +0 -9
  180. package/dist/server/rpc/handle-request.js +13 -321
  181. package/dist/server/rpc/handler-registry.d.ts +3 -0
  182. package/dist/server/rpc/handler-registry.js +84 -0
  183. package/dist/server/rpc/handler-utils.d.ts +22 -0
  184. package/dist/server/rpc/handler-utils.js +87 -0
  185. package/dist/server/rpc/handlers/cancelHandler.js +1 -1
  186. package/dist/server/rpc/handlers/completion-stream-delegated.js +1 -1
  187. package/dist/server/rpc/handlers/completion-stream.js +2 -43
  188. package/dist/server/rpc/handlers/delete-cache.js +1 -1
  189. package/dist/server/rpc/handlers/embed.js +2 -21
  190. package/dist/server/rpc/handlers/get-model-info.js +19 -15
  191. package/dist/server/rpc/handlers/index.d.ts +9 -0
  192. package/dist/server/rpc/handlers/index.js +9 -0
  193. package/dist/server/rpc/handlers/load-model/download-manager.d.ts +1 -0
  194. package/dist/server/rpc/handlers/load-model/download-manager.js +3 -0
  195. package/dist/server/rpc/handlers/load-model/handler.js +47 -24
  196. package/dist/server/rpc/handlers/load-model/http.js +3 -2
  197. package/dist/server/rpc/handlers/load-model/hyperdrive.js +14 -10
  198. package/dist/server/rpc/handlers/load-model/registry.d.ts +10 -0
  199. package/dist/server/rpc/handlers/load-model/registry.js +571 -0
  200. package/dist/server/rpc/handlers/load-model/resolve.js +18 -5
  201. package/dist/server/rpc/handlers/load-model-delegated.js +4 -2
  202. package/dist/server/rpc/handlers/ocr-stream.js +2 -37
  203. package/dist/server/rpc/handlers/ping.d.ts +3 -0
  204. package/dist/server/rpc/handlers/ping.js +3 -0
  205. package/dist/server/rpc/handlers/plugin-dispatch.d.ts +15 -0
  206. package/dist/server/rpc/handlers/plugin-dispatch.js +54 -0
  207. package/dist/server/rpc/handlers/plugin-invoke.d.ts +4 -0
  208. package/dist/server/rpc/handlers/plugin-invoke.js +87 -0
  209. package/dist/server/rpc/handlers/registry.d.ts +5 -0
  210. package/dist/server/rpc/handlers/registry.js +157 -0
  211. package/dist/server/rpc/handlers/text-to-speech.js +2 -5
  212. package/dist/server/rpc/handlers/transcribe-stream.js +2 -30
  213. package/dist/server/rpc/handlers/translate.js +2 -42
  214. package/dist/server/rpc/handlers/unload-model.js +1 -1
  215. package/dist/server/rpc/index.d.ts +1 -1
  216. package/dist/server/utils/archive.d.ts +1 -0
  217. package/dist/server/utils/archive.js +10 -2
  218. package/dist/server/utils/cache.d.ts +5 -0
  219. package/dist/server/utils/cache.js +26 -2
  220. package/dist/server/utils/gguf-tensor-extractor.js +3 -3
  221. package/dist/server/utils/index.d.ts +1 -1
  222. package/dist/server/utils/index.js +1 -1
  223. package/dist/server/utils/path-security.d.ts +12 -0
  224. package/dist/server/utils/path-security.js +25 -0
  225. package/dist/server/utils/shard-utils.js +3 -3
  226. package/dist/server/worker-core.d.ts +6 -0
  227. package/dist/server/worker-core.js +88 -0
  228. package/dist/server/worker.d.ts +4 -5
  229. package/dist/server/worker.js +18 -116
  230. package/dist/utils/errors-client.d.ts +9 -6
  231. package/dist/utils/errors-client.js +19 -11
  232. package/dist/utils/errors-server.d.ts +44 -5
  233. package/dist/utils/errors-server.js +82 -9
  234. package/dist/utils/path-sanitize.d.ts +17 -0
  235. package/dist/utils/path-sanitize.js +54 -0
  236. package/expo/plugins/patches/android-link.mjs +63 -0
  237. package/expo/plugins/patches/ios-link.mjs +63 -0
  238. package/package.json +74 -12
  239. package/dist/examples/text-to-speech.d.ts +0 -3
  240. package/dist/examples/text-to-speech.js +0 -137
  241. package/dist/models/hyperdrive/models.d.ts +0 -4003
  242. package/dist/models/hyperdrive/models.js +0 -4282
  243. package/dist/server/bare/addons/index.d.ts +0 -4
  244. package/dist/server/bare/addons/index.js +0 -3
  245. package/dist/server/bare/addons/llamacpp-completion/create-model.d.ts +0 -8
  246. package/dist/server/bare/addons/llamacpp-completion/create-model.js +0 -43
  247. package/dist/server/bare/addons/llamacpp-completion/index.d.ts +0 -4
  248. package/dist/server/bare/addons/llamacpp-completion/index.js +0 -3
  249. package/dist/server/bare/addons/llamacpp-embedding/create-model.d.ts +0 -8
  250. package/dist/server/bare/addons/llamacpp-embedding/create-model.js +0 -38
  251. package/dist/server/bare/addons/llamacpp-embedding/index.d.ts +0 -3
  252. package/dist/server/bare/addons/llamacpp-embedding/index.js +0 -2
  253. package/dist/server/bare/addons/nmtcpp-translation/create-model.d.ts +0 -8
  254. package/dist/server/bare/addons/nmtcpp-translation/create-model.js +0 -52
  255. package/dist/server/bare/addons/nmtcpp-translation/index.d.ts +0 -3
  256. package/dist/server/bare/addons/nmtcpp-translation/index.js +0 -2
  257. package/dist/server/bare/addons/onnx-ocr/create-model.d.ts +0 -10
  258. package/dist/server/bare/addons/onnx-ocr/index.d.ts +0 -3
  259. package/dist/server/bare/addons/onnx-ocr/index.js +0 -2
  260. package/dist/server/bare/addons/onnx-tts/create-model.d.ts +0 -10
  261. package/dist/server/bare/addons/onnx-tts/create-model.js +0 -25
  262. package/dist/server/bare/addons/onnx-tts/index.d.ts +0 -3
  263. package/dist/server/bare/addons/onnx-tts/index.js +0 -2
  264. package/dist/server/bare/addons/whispercpp-transcription/create-model.d.ts +0 -10
  265. package/dist/server/bare/addons/whispercpp-transcription/create-model.js +0 -37
  266. package/dist/server/bare/addons/whispercpp-transcription/handlers/transcribe-stream.d.ts +0 -3
  267. package/dist/server/bare/addons/whispercpp-transcription/index.d.ts +0 -3
  268. package/dist/server/bare/addons/whispercpp-transcription/index.js +0 -2
  269. /package/dist/models/{hyperdrive → registry}/index.d.ts +0 -0
  270. /package/dist/server/bare/{addons → ops}/cancel.d.ts +0 -0
  271. /package/dist/server/bare/{addons → ops}/cancel.js +0 -0
  272. /package/dist/server/bare/{addons/llamacpp-completion → ops}/kv-cache-utils.d.ts +0 -0
  273. /package/dist/server/bare/{addons → ops}/load-model.d.ts +0 -0
  274. /package/dist/server/bare/{addons → ops}/unload-model.d.ts +0 -0
  275. /package/dist/server/bare/{addons → ops}/unload-model.js +0 -0
  276. /package/dist/server/bare/{addons/llamacpp-completion → plugins/llamacpp-completion/ops}/cache-logger.d.ts +0 -0
  277. /package/dist/server/bare/{addons/onnx-ocr/handlers → plugins/onnx-ocr/ops}/ocr-stream.d.ts +0 -0
  278. /package/dist/server/bare/{addons/onnx-tts/handlers → plugins/onnx-tts/ops}/text-to-speech.d.ts +0 -0
@@ -1,6 +1,9 @@
1
1
  import RPC from "bare-rpc";
2
2
  import spawn, {} from "bare-runtime/spawn";
3
+ import { randomBytes } from "node:crypto";
4
+ import { existsSync, unlinkSync } from "node:fs";
3
5
  import { createServer } from "node:net";
6
+ import fs from "node:fs";
4
7
  import os from "node:os";
5
8
  import path from "node:path";
6
9
  import { fileURLToPath } from "node:url";
@@ -15,37 +18,175 @@ let rpcInstance = null;
15
18
  let rpcPromise = null;
16
19
  let bareWorkerProc = null;
17
20
  let ipcServer = null;
18
- // Smart path resolution for worker
19
- let WORKER_PATH;
20
- if (__dirname.includes("/dist/") || __dirname.includes("\\dist\\")) {
21
- const distRoot = __dirname.includes("/dist/")
22
- ? __dirname.split("/dist/")[0] + "/dist"
23
- : __dirname.split("\\dist\\")[0] + "\\dist";
24
- WORKER_PATH = path.join(distRoot, "server/worker.js");
21
+ let currentSocketPath = null;
22
+ let closePromise = null;
23
+ /**
24
+ * Find project root by looking for package.json (sync version)
25
+ * Safe to call at module load time
26
+ */
27
+ function findProjectRootSync() {
28
+ let dir = process.cwd();
29
+ const root = path.parse(dir).root;
30
+ while (dir !== root) {
31
+ if (fs.existsSync(path.join(dir, "package.json"))) {
32
+ return dir;
33
+ }
34
+ dir = path.dirname(dir);
35
+ }
36
+ return undefined;
37
+ }
38
+ function getResourcesPathSync() {
39
+ const { resourcesPath } = process;
40
+ return typeof resourcesPath === "string" ? resourcesPath : undefined;
41
+ }
42
+ function resolvePackagedWorkerPath() {
43
+ const resourcesPath = getResourcesPathSync();
44
+ if (!resourcesPath)
45
+ return undefined;
46
+ const candidates = [
47
+ path.join(resourcesPath, "app.asar.unpacked", "qvac", "worker.entry.mjs"),
48
+ path.join(resourcesPath, "app", "qvac", "worker.entry.mjs"),
49
+ path.join(resourcesPath, "qvac", "worker.entry.mjs"),
50
+ ];
51
+ for (const candidate of candidates) {
52
+ if (fs.existsSync(candidate))
53
+ return candidate;
54
+ }
55
+ return undefined;
56
+ }
57
+ /**
58
+ * Get default worker path from SDK dist
59
+ */
60
+ function getDefaultWorkerPath() {
61
+ const packagedWorker = path.resolve(__dirname, "../../server/worker.js");
62
+ if (fs.existsSync(packagedWorker))
63
+ return packagedWorker;
64
+ // Dev/source layout fallback
65
+ return path.resolve(__dirname, "../../dist/server/worker.js");
66
+ }
67
+ /**
68
+ * Resolve worker path with priority:
69
+ * 1. QVAC_WORKER_PATH environment variable
70
+ * 2. Packaged Electron app worker entry
71
+ * 3. qvac/worker.entry.mjs in project root (generated by npx qvac bundle sdk)
72
+ * 4. Default SDK worker
73
+ */
74
+ function resolveWorkerPath() {
75
+ const envWorkerPath = process.env["QVAC_WORKER_PATH"];
76
+ if (envWorkerPath) {
77
+ const normalized = path.resolve(envWorkerPath);
78
+ if (fs.existsSync(normalized)) {
79
+ logger.info(`🔧 Using worker entry from QVAC_WORKER_PATH: ${normalized}`);
80
+ return normalized;
81
+ }
82
+ logger.warn(`⚠️ QVAC_WORKER_PATH was set but file was not found: ${normalized}. Falling back.`);
83
+ }
84
+ // Prefer packaged worker entry when running as a packaged Electron app.
85
+ // This avoids accidental coupling to the project's cwd, and ensures the
86
+ // bare worker reads JS modules from the filesystem (not app.asar).
87
+ const packagedWorker = resolvePackagedWorkerPath();
88
+ if (packagedWorker) {
89
+ logger.info(`🔧 Using packaged worker entry: ${packagedWorker}`);
90
+ return packagedWorker;
91
+ }
92
+ // Check for custom worker entry at project root
93
+ // Note: We use worker.entry.mjs (unbundled ESM) for desktop because bare can
94
+ // load ES modules directly. The packed bundle is for mobile only.
95
+ const projectRoot = findProjectRootSync();
96
+ if (projectRoot) {
97
+ const customEntry = path.join(projectRoot, "qvac", "worker.entry.mjs");
98
+ if (fs.existsSync(customEntry)) {
99
+ logger.info(`🔧 Using custom worker entry: ${customEntry}`);
100
+ return customEntry;
101
+ }
102
+ }
103
+ // Fallback to default SDK worker
104
+ const defaultPath = getDefaultWorkerPath();
105
+ logger.debug(`🔧 Using default SDK worker: ${defaultPath}`);
106
+ return defaultPath;
25
107
  }
26
- else {
27
- WORKER_PATH = path.resolve(__dirname, "../../dist/server/worker.js");
108
+ const WORKER_PATH = resolveWorkerPath();
109
+ function createSocketPath() {
110
+ const timestamp = Date.now().toString(36);
111
+ const randomSuffix = randomBytes(2).toString("hex");
112
+ const socketName = `qvac-worker-${process.pid}-${timestamp}-${randomSuffix}`;
113
+ return process.platform === "win32"
114
+ ? `\\\\.\\pipe\\${socketName}`
115
+ : path.join(os.tmpdir(), `${socketName}.sock`);
116
+ }
117
+ function bestEffortUnlinkSocket(socketPath) {
118
+ // Windows named pipes are not filesystem paths, so unlink is Unix-only.
119
+ if (!socketPath || process.platform === "win32")
120
+ return;
121
+ try {
122
+ if (existsSync(socketPath)) {
123
+ unlinkSync(socketPath);
124
+ }
125
+ }
126
+ catch (error) {
127
+ logger.debug("Failed to unlink IPC socket path", { socketPath, error });
128
+ }
129
+ }
130
+ function snapshotAndResetState() {
131
+ const workerToClose = bareWorkerProc;
132
+ const serverToClose = ipcServer;
133
+ const socketPathToClose = currentSocketPath;
134
+ rpcInstance = null;
135
+ rpcPromise = null;
136
+ bareWorkerProc = null;
137
+ ipcServer = null;
138
+ currentSocketPath = null;
139
+ return { workerToClose, serverToClose, socketPathToClose };
140
+ }
141
+ function closeSyncForExit() {
142
+ const { workerToClose, serverToClose, socketPathToClose } = snapshotAndResetState();
143
+ if (workerToClose) {
144
+ try {
145
+ workerToClose.kill("SIGTERM");
146
+ }
147
+ catch (error) {
148
+ logger.debug("Failed to kill bare worker during process exit", { error });
149
+ }
150
+ }
151
+ if (serverToClose) {
152
+ try {
153
+ serverToClose.close();
154
+ }
155
+ catch (error) {
156
+ logger.debug("Failed to close IPC server during process exit", { error });
157
+ }
158
+ }
159
+ bestEffortUnlinkSocket(socketPathToClose);
28
160
  }
29
- const SOCKET_PATH = process.platform === "win32"
30
- ? `\\\\.\\pipe\\qvac-worker-${process.pid}`
31
- : path.join(os.tmpdir(), `qvac-worker-${process.pid}.sock`);
32
161
  async function ensureRPC() {
33
162
  if (rpcInstance)
34
163
  return rpcInstance;
35
164
  if (rpcPromise)
36
165
  return rpcPromise;
166
+ if (closePromise) {
167
+ await closePromise;
168
+ }
169
+ const socketPath = createSocketPath();
170
+ currentSocketPath = socketPath;
37
171
  rpcPromise = new Promise((resolve, reject) => {
38
172
  ipcServer = createServer((socket) => {
39
173
  rpcInstance = new RPC(socket, () => { });
40
174
  resolve(rpcInstance);
41
175
  });
42
- ipcServer.on("error", reject);
43
- ipcServer.listen(SOCKET_PATH, () => {
176
+ ipcServer.on("error", (error) => {
177
+ rpcPromise = null;
178
+ rpcInstance = null;
179
+ bareWorkerProc = null;
180
+ ipcServer = null;
181
+ currentSocketPath = null;
182
+ reject(error);
183
+ });
184
+ ipcServer.listen(socketPath, () => {
44
185
  bareWorkerProc = spawn("bare", {
45
186
  args: [
46
187
  WORKER_PATH,
47
188
  JSON.stringify({
48
- QVAC_IPC_SOCKET_PATH: SOCKET_PATH,
189
+ QVAC_IPC_SOCKET_PATH: socketPath,
49
190
  HOME_DIR: os.homedir(),
50
191
  }),
51
192
  ],
@@ -100,20 +241,52 @@ const mockRPC = {
100
241
  export function getRPC() {
101
242
  return mockRPC;
102
243
  }
103
- export function close() {
244
+ export async function close() {
245
+ if (closePromise) {
246
+ await closePromise;
247
+ return;
248
+ }
249
+ if (!rpcInstance && !rpcPromise && !bareWorkerProc && !ipcServer)
250
+ return;
104
251
  logger.info("🧹 Closing RPC client");
105
- if (bareWorkerProc) {
106
- logger.info("🐻🔫 Killing bare worker process");
107
- bareWorkerProc.kill("SIGTERM");
108
- bareWorkerProc = null;
252
+ const { workerToClose, serverToClose, socketPathToClose } = snapshotAndResetState();
253
+ closePromise = (async () => {
254
+ if (workerToClose) {
255
+ logger.info("🐻🔫 Killing bare worker process");
256
+ try {
257
+ workerToClose.kill("SIGTERM");
258
+ }
259
+ catch (error) {
260
+ logger.debug("Failed to kill bare worker process", { error });
261
+ }
262
+ }
263
+ if (serverToClose) {
264
+ logger.info("🔌 Closing IPC server");
265
+ await new Promise((resolve) => {
266
+ try {
267
+ serverToClose.close(() => resolve());
268
+ }
269
+ catch (error) {
270
+ logger.debug("Failed to close IPC server", { error });
271
+ resolve();
272
+ }
273
+ });
274
+ }
275
+ bestEffortUnlinkSocket(socketPathToClose);
276
+ })();
277
+ try {
278
+ await closePromise;
109
279
  }
110
- if (ipcServer) {
111
- logger.info("🔌 Closing IPC server");
112
- ipcServer.close();
113
- ipcServer = null;
280
+ finally {
281
+ closePromise = null;
114
282
  }
115
- rpcInstance = null;
116
- rpcPromise = null;
117
283
  }
118
- // Register cleanup handlers for the parent process
119
- process.once("exit", close);
284
+ function handleTerminationSignal(signal) {
285
+ logger.info(`Received ${signal}, closing RPC resources...`);
286
+ closeSyncForExit();
287
+ process.kill(process.pid, signal);
288
+ }
289
+ process.once("SIGINT", () => handleTerminationSignal("SIGINT"));
290
+ process.once("SIGTERM", () => handleTerminationSignal("SIGTERM"));
291
+ process.once("SIGHUP", () => handleTerminationSignal("SIGHUP"));
292
+ process.once("exit", closeSyncForExit);
@@ -2,5 +2,5 @@ import type RPC from "bare-rpc";
2
2
  import { type Request, type Response, type RPCOptions } from "../../schemas/index";
3
3
  export declare function send<T extends Request>(request: T, rpc?: RPC, options?: RPCOptions): Promise<Response>;
4
4
  export declare function stream<T extends Request>(request: T, rpc?: RPC, options?: RPCOptions): AsyncGenerator<Response>;
5
- export declare function close(): void;
5
+ export declare function close(): Promise<void>;
6
6
  //# sourceMappingURL=rpc-client.d.ts.map
@@ -62,9 +62,9 @@ export async function* stream(request, rpc, options = {}) {
62
62
  }
63
63
  }
64
64
  }
65
- export function close() {
65
+ export async function close() {
66
66
  if (!rpcInstance)
67
67
  return;
68
- closeRPC();
69
68
  rpcInstance = null;
69
+ await closeRPC();
70
70
  }
@@ -1,2 +1,3 @@
1
1
  export * from "./audio";
2
+ export * from "./registry";
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1,2 @@
1
1
  export * from "./audio.js";
2
+ export * from "./registry.js";
@@ -0,0 +1,2 @@
1
+ export declare const DEFAULT_REGISTRY_CORE_KEY = "uf1fm44uzockp6azhcdiqt1esjgm65fwtimsh946e8kwysdes9ko";
2
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ export const DEFAULT_REGISTRY_CORE_KEY = "uf1fm44uzockp6azhcdiqt1esjgm65fwtimsh946e8kwysdes9ko";
@@ -1,10 +1,10 @@
1
- import { WHISPER_TINY } from "../models/hyperdrive/index.js";
1
+ import { WHISPER_TINY } from "../models/registry/index.js";
2
2
  import { downloadAsset, getModelInfo, loadModel, unloadModel } from "..";
3
3
  const printModelStatus = (info, label) => {
4
4
  console.log(`\n${label}`);
5
5
  console.log(` Model Name: ${info.name}`);
6
6
  console.log(` Model ID: ${info.modelId}`);
7
- console.log(` Hyperdrive Key: ${info.hyperdriveKey.substring(0, 16)}...`);
7
+ console.log(` Blob Core Key: ${info.blobCoreKey?.substring(0, 16) || "N/A"}...`);
8
8
  console.log(` Expected Size: ${(info.expectedSize / 1024 / 1024).toFixed(2)} MB`);
9
9
  console.log(` Addon: ${info.addon}`);
10
10
  console.log(` Cache Files: ${info.cacheFiles.length}`);
@@ -0,0 +1,5 @@
1
+ declare const _default: {
2
+ plugins: ("@qvac/sdk/llamacpp-completion/plugin" | "@qvac/sdk/nmtcpp-translation/plugin")[];
3
+ };
4
+ export default _default;
5
+ //# sourceMappingURL=plugins.config.d.ts.map
@@ -0,0 +1,4 @@
1
+ import { PLUGIN_LLM, PLUGIN_NMT } from "@qvac/sdk";
2
+ export default {
3
+ plugins: [PLUGIN_LLM, PLUGIN_NMT],
4
+ };
@@ -38,7 +38,7 @@ try {
38
38
  });
39
39
  console.log(`\n✅ Model downloaded successfully using blind relays!`);
40
40
  console.log(`Blind relays helped establish peer connections through NAT/firewalls\n`);
41
- close();
41
+ await close();
42
42
  }
43
43
  catch (error) {
44
44
  console.error("❌ Error:", error);
@@ -1,4 +1,4 @@
1
- import { completion, loadModel, SMOLVLM2_2_500M_MULTIMODAL_Q8_0, MMPROJ_SMOLVLM2_2_500M_MULTIMODAL_Q8_0, unloadModel, } from "@qvac/sdk";
1
+ import { completion, loadModel, SMOLVLM2_500M_MULTIMODAL_Q8_0, MMPROJ_SMOLVLM2_500M_MULTIMODAL_Q8_0, unloadModel, } from "@qvac/sdk";
2
2
  if (process.argv.length < 3) {
3
3
  console.error(`Specify an image file path as the first argument and a second image file path as the second (optional) argument`);
4
4
  process.exit(1);
@@ -8,9 +8,9 @@ try {
8
8
  const imageFilePath = process.argv[2];
9
9
  // Load the main model with projection in a single step
10
10
  const modelId = await loadModel({
11
- modelSrc: SMOLVLM2_2_500M_MULTIMODAL_Q8_0,
11
+ modelSrc: SMOLVLM2_500M_MULTIMODAL_Q8_0,
12
12
  modelType: "llm",
13
- projectionModelSrc: MMPROJ_SMOLVLM2_2_500M_MULTIMODAL_Q8_0,
13
+ projectionModelSrc: MMPROJ_SMOLVLM2_500M_MULTIMODAL_Q8_0,
14
14
  modelConfig: {
15
15
  ctx_size: 1024,
16
16
  },
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { completion, loadModel, unloadModel, QWEN_3_1_7B_INST_Q4, } from "../index.js";
2
+ import { completion, loadModel, unloadModel, QWEN3_1_7B_INST_Q4, } from "../index.js";
3
3
  // Define Zod schemas for tool parameters
4
4
  const weatherSchema = z.object({
5
5
  city: z.string().describe("City name"),
@@ -29,7 +29,7 @@ const tools = [
29
29
  try {
30
30
  // Load model from provided file path with tools support enabled
31
31
  const modelId = await loadModel({
32
- modelSrc: QWEN_3_1_7B_INST_Q4,
32
+ modelSrc: QWEN3_1_7B_INST_Q4,
33
33
  modelType: "llm",
34
34
  modelConfig: {
35
35
  ctx_size: 4096,
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * Run with: bun run examples/mcp-websearch.ts
11
11
  */
12
- import { completion, loadModel, unloadModel, QWEN_3_1_7B_INST_Q4, } from "../index.js";
12
+ import { completion, loadModel, unloadModel, QWEN3_1_7B_INST_Q4, } from "../index.js";
13
13
  // MCP SDK is a user-installed optional dependency
14
14
  // Install with: bun add @modelcontextprotocol/sdk
15
15
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
@@ -63,7 +63,7 @@ try {
63
63
  // ============================================================
64
64
  console.log("2️⃣ Loading model...");
65
65
  const modelId = await loadModel({
66
- modelSrc: QWEN_3_1_7B_INST_Q4,
66
+ modelSrc: QWEN3_1_7B_INST_Q4,
67
67
  modelType: "llm",
68
68
  modelConfig: {
69
69
  ctx_size: 4096,
@@ -1,7 +1,7 @@
1
- import { completion, LLAMA_3_2_1B_INST_Q4_0, loadModel, QWEN_3_1_7B_INST_Q4, unloadModel, } from "@qvac/sdk";
1
+ import { completion, LLAMA_3_2_1B_INST_Q4_0, loadModel, QWEN3_1_7B_INST_Q4, unloadModel, } from "@qvac/sdk";
2
2
  try {
3
3
  const alice = await loadModel({
4
- modelSrc: QWEN_3_1_7B_INST_Q4,
4
+ modelSrc: QWEN3_1_7B_INST_Q4,
5
5
  modelType: "llm",
6
6
  modelConfig: {
7
7
  ctx_size: 4096,
@@ -1,13 +1,12 @@
1
- import { close, loadModel, ocr, OCR_CRAFT_LATIN_RECOGNIZER_1, unloadModel, } from "@qvac/sdk";
1
+ import { close, loadModel, ocr, OCR_LATIN_RECOGNIZER_1, unloadModel, } from "@qvac/sdk";
2
2
  import path from "path";
3
3
  import { fileURLToPath } from "url";
4
4
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
5
5
  const imagePath = process.argv[2] || path.join(__dirname, "image/basic_test.bmp");
6
6
  try {
7
7
  console.log("🚀 Loading OCR model...");
8
- // Only need to pass the recognizer - detector is auto-derived from same hyperdrive key
9
8
  const modelId = await loadModel({
10
- modelSrc: OCR_CRAFT_LATIN_RECOGNIZER_1,
9
+ modelSrc: OCR_LATIN_RECOGNIZER_1,
11
10
  modelType: "ocr",
12
11
  modelConfig: {
13
12
  langList: ["en"],
@@ -45,8 +44,9 @@ try {
45
44
  console.log("\n🔄 Unloading model...");
46
45
  await unloadModel({ modelId, clearStorage: false });
47
46
  console.log("✅ Model unloaded successfully.");
47
+ process.exit(0);
48
48
  }
49
49
  catch (error) {
50
50
  console.error("❌ Error during OCR processing:", error);
51
- close();
51
+ await close();
52
52
  }
@@ -1,4 +1,4 @@
1
- import { LLAMA_3_2_1B_INST_Q4_0, downloadAsset, WHISPER_LARGE_3, close, } from "@qvac/sdk";
1
+ import { LLAMA_3_2_1B_INST_Q4_0, downloadAsset, WHISPER_TINY, close, } from "@qvac/sdk";
2
2
  try {
3
3
  const llamaDownloadPromise = downloadAsset({
4
4
  assetSrc: LLAMA_3_2_1B_INST_Q4_0,
@@ -7,7 +7,7 @@ try {
7
7
  },
8
8
  });
9
9
  const whisperDownloadPromise = downloadAsset({
10
- assetSrc: WHISPER_LARGE_3,
10
+ assetSrc: WHISPER_TINY,
11
11
  onProgress: (progress) => {
12
12
  console.log("🔊 Whisper progress:", progress);
13
13
  },
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Plugin Selection Example
3
+ *
4
+ * Config: examples/config/plugins/plugins.config.json
5
+ * Selected: llamacpp-completion (LLM), nmtcpp-translation (NMT)
6
+ *
7
+ * Demonstrates:
8
+ * 1. LLM completion -> works (plugin selected)
9
+ * 2. NMT translation -> works (plugin selected)
10
+ * 3. Embeddings -> fails (plugin not selected)
11
+ *
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=plugins.d.ts.map
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Plugin Selection Example
3
+ *
4
+ * Config: examples/config/plugins/plugins.config.json
5
+ * Selected: llamacpp-completion (LLM), nmtcpp-translation (NMT)
6
+ *
7
+ * Demonstrates:
8
+ * 1. LLM completion -> works (plugin selected)
9
+ * 2. NMT translation -> works (plugin selected)
10
+ * 3. Embeddings -> fails (plugin not selected)
11
+ *
12
+ */
13
+ import { execSync } from "child_process";
14
+ import { existsSync, rmSync } from "fs";
15
+ import path from "path";
16
+ const configDir = import.meta.dirname ?? process.cwd();
17
+ const configPath = `${configDir}/config/plugins/plugins.config.json`;
18
+ const projectRoot = path.resolve(configDir, "..");
19
+ const qvacOutputDir = path.join(projectRoot, "qvac");
20
+ // ─── Generate the worker bundle from the plugins config ─────────────────────
21
+ console.log(`🔍 Config: ${configPath}`);
22
+ console.log(`⚠️ This example will generate a worker bundle in ${qvacOutputDir} and delete it on exit.`);
23
+ console.log(" If you have an existing qvac/ folder with bundled files, they will be overwritten and removed.\n");
24
+ console.log("🔨 Generating worker bundle from plugins config...\n");
25
+ try {
26
+ execSync(`npx @qvac/cli bundle sdk --config "${configPath}" --quiet`, {
27
+ cwd: projectRoot,
28
+ stdio: "inherit",
29
+ });
30
+ }
31
+ catch (error) {
32
+ console.error("❌ Failed to generate worker bundle. Ensure @qvac/cli is installed:");
33
+ console.error(" npm install -D @qvac/cli");
34
+ console.error("❌ Error:", error);
35
+ process.exit(1);
36
+ }
37
+ console.log("");
38
+ // Cleanup generated qvac/ folder on exit
39
+ function cleanup() {
40
+ if (existsSync(qvacOutputDir)) {
41
+ rmSync(qvacOutputDir, { recursive: true, force: true });
42
+ console.log(`\n🧹 Cleaned up ${qvacOutputDir}`);
43
+ }
44
+ }
45
+ process.on("exit", cleanup);
46
+ // Point config before importing the SDK.
47
+ // In a real app, place qvac.config.json (or .js/.ts) in your project root (auto-discovered).
48
+ process.env["QVAC_CONFIG_PATH"] = configPath;
49
+ const { completion, translate, embed, loadModel, unloadModel, LLAMA_3_2_1B_INST_Q4_0, MARIAN_OPUS_EN_IT_Q4_0, GTE_LARGE_FP16, } = await import("@qvac/sdk");
50
+ console.log("1. LLM Completion (llamacpp-completion plugin)");
51
+ try {
52
+ const llmModelId = await loadModel({
53
+ modelSrc: LLAMA_3_2_1B_INST_Q4_0,
54
+ modelType: "llm",
55
+ modelConfig: { ctx_size: 2048 },
56
+ onProgress: (p) => console.log(` Loading LLM: ${p.percentage.toFixed(1)}%`),
57
+ });
58
+ console.log(` Model loaded: ${llmModelId}`);
59
+ const question = "What is 2 + 2? Answer in one word.";
60
+ console.log(` Question: ${question}`);
61
+ const result = completion({
62
+ modelId: llmModelId,
63
+ history: [{ role: "user", content: question }],
64
+ stream: true,
65
+ });
66
+ process.stdout.write(" Response: ");
67
+ for await (const token of result.tokenStream) {
68
+ process.stdout.write(token);
69
+ }
70
+ console.log("\n");
71
+ await unloadModel({ modelId: llmModelId });
72
+ console.log(" ✅ LLM unloaded\n");
73
+ }
74
+ catch (error) {
75
+ console.error(" ❌ LLM failed:", error);
76
+ process.exit(1);
77
+ }
78
+ console.log("2. Translation (nmtcpp-translation plugin)");
79
+ try {
80
+ const nmtModelId = await loadModel({
81
+ modelSrc: MARIAN_OPUS_EN_IT_Q4_0,
82
+ modelType: "nmt",
83
+ modelConfig: {
84
+ engine: "Opus",
85
+ from: "en",
86
+ to: "it",
87
+ },
88
+ onProgress: (p) => console.log(` Loading NMT: ${p.percentage.toFixed(1)}%`),
89
+ });
90
+ console.log(` Model loaded: ${nmtModelId}`);
91
+ const text = "Hello, how are you?";
92
+ const result = translate({
93
+ modelId: nmtModelId,
94
+ text,
95
+ modelType: "nmt",
96
+ stream: false,
97
+ });
98
+ const translated = await result.text;
99
+ console.log(` "${text}" -> "${translated}"\n`);
100
+ await unloadModel({ modelId: nmtModelId });
101
+ console.log(" ✅ NMT unloaded\n");
102
+ }
103
+ catch (error) {
104
+ console.error(" ❌ Translation failed:", error);
105
+ process.exit(1);
106
+ }
107
+ console.log("3. Embeddings (llamacpp-embedding plugin NOT in config)");
108
+ console.log(" Attempting to load an embeddings model...\n");
109
+ try {
110
+ const embedModelId = await loadModel({
111
+ modelSrc: GTE_LARGE_FP16,
112
+ modelType: "embeddings",
113
+ });
114
+ await embed({ modelId: embedModelId, text: "test" });
115
+ console.error(" ❌ Unexpected: embed succeeded without the plugin!");
116
+ process.exit(1);
117
+ }
118
+ catch (error) {
119
+ const message = error instanceof Error ? error.message : String(error);
120
+ if (message.includes("Plugin not found")) {
121
+ console.log(" ✅ Expected PLUGIN_NOT_FOUND error:");
122
+ console.log(` ${message}\n`);
123
+ }
124
+ else {
125
+ console.error(" ❌ Unexpected error:", error);
126
+ process.exit(1);
127
+ }
128
+ }
129
+ console.log("Done! Only the selected plugins were available.");
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=registry-query.d.ts.map