@qvac/sdk 0.1.0-dev.1760648187.328e967

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 (287) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +301 -0
  3. package/dist/client/api/cancel.d.ts +25 -0
  4. package/dist/client/api/cancel.js +37 -0
  5. package/dist/client/api/completion-stream.d.ts +50 -0
  6. package/dist/client/api/completion-stream.js +103 -0
  7. package/dist/client/api/download-asset.d.ts +39 -0
  8. package/dist/client/api/download-asset.js +72 -0
  9. package/dist/client/api/embed.d.ts +11 -0
  10. package/dist/client/api/embed.js +24 -0
  11. package/dist/client/api/index.d.ts +13 -0
  12. package/dist/client/api/index.js +12 -0
  13. package/dist/client/api/load-model.d.ts +98 -0
  14. package/dist/client/api/load-model.js +154 -0
  15. package/dist/client/api/logging-stream.d.ts +21 -0
  16. package/dist/client/api/logging-stream.js +32 -0
  17. package/dist/client/api/ping.d.ts +11 -0
  18. package/dist/client/api/ping.js +18 -0
  19. package/dist/client/api/provide.d.ts +18 -0
  20. package/dist/client/api/provide.js +27 -0
  21. package/dist/client/api/rag.d.ts +42 -0
  22. package/dist/client/api/rag.js +97 -0
  23. package/dist/client/api/transcribe.d.ts +24 -0
  24. package/dist/client/api/transcribe.js +52 -0
  25. package/dist/client/api/translate.d.ts +47 -0
  26. package/dist/client/api/translate.js +114 -0
  27. package/dist/client/api/unload-model.d.ts +11 -0
  28. package/dist/client/api/unload-model.js +26 -0
  29. package/dist/client/index.d.ts +2 -0
  30. package/dist/client/index.js +1 -0
  31. package/dist/client/logging-stream-registry.d.ts +5 -0
  32. package/dist/client/logging-stream-registry.js +60 -0
  33. package/dist/client/rpc/bare-client.d.ts +112 -0
  34. package/dist/client/rpc/bare-client.js +82 -0
  35. package/dist/client/rpc/bare-rpc-client.d.ts +4 -0
  36. package/dist/client/rpc/bare-rpc-client.js +87 -0
  37. package/dist/client/rpc/expo-rpc-client.d.ts +3 -0
  38. package/dist/client/rpc/expo-rpc-client.js +57 -0
  39. package/dist/client/rpc/node-rpc-client.d.ts +9 -0
  40. package/dist/client/rpc/node-rpc-client.js +99 -0
  41. package/dist/client/rpc/rpc-client.d.ts +5 -0
  42. package/dist/client/rpc/rpc-client.js +91 -0
  43. package/dist/client/rpc/rpc-error.d.ts +19 -0
  44. package/dist/client/rpc/rpc-error.js +39 -0
  45. package/dist/constants/audio.d.ts +3 -0
  46. package/dist/constants/audio.js +17 -0
  47. package/dist/constants/index.d.ts +2 -0
  48. package/dist/constants/index.js +1 -0
  49. package/dist/examples/delegated-inference/consumer.d.ts +2 -0
  50. package/dist/examples/delegated-inference/consumer.js +56 -0
  51. package/dist/examples/delegated-inference/provider.d.ts +2 -0
  52. package/dist/examples/delegated-inference/provider.js +57 -0
  53. package/dist/examples/download-with-cancel.d.ts +2 -0
  54. package/dist/examples/download-with-cancel.js +46 -0
  55. package/dist/examples/embed-hyperdrive.d.ts +2 -0
  56. package/dist/examples/embed-hyperdrive.js +19 -0
  57. package/dist/examples/kv-cache-example.d.ts +2 -0
  58. package/dist/examples/kv-cache-example.js +74 -0
  59. package/dist/examples/llamacpp-file-logging.d.ts +2 -0
  60. package/dist/examples/llamacpp-file-logging.js +62 -0
  61. package/dist/examples/llamacpp-filesystem.d.ts +2 -0
  62. package/dist/examples/llamacpp-filesystem.js +40 -0
  63. package/dist/examples/llamacpp-http.d.ts +2 -0
  64. package/dist/examples/llamacpp-http.js +41 -0
  65. package/dist/examples/llamacpp-hyperdrive.d.ts +2 -0
  66. package/dist/examples/llamacpp-hyperdrive.js +39 -0
  67. package/dist/examples/llamacpp-multimodal.d.ts +2 -0
  68. package/dist/examples/llamacpp-multimodal.js +62 -0
  69. package/dist/examples/llamacpp-native-tools.d.ts +2 -0
  70. package/dist/examples/llamacpp-native-tools.js +64 -0
  71. package/dist/examples/llamacpp-tools-routing.d.ts +2 -0
  72. package/dist/examples/llamacpp-tools-routing.js +364 -0
  73. package/dist/examples/llamacpp-tools.d.ts +2 -0
  74. package/dist/examples/llamacpp-tools.js +81 -0
  75. package/dist/examples/multi-model-demo.d.ts +2 -0
  76. package/dist/examples/multi-model-demo.js +75 -0
  77. package/dist/examples/parallel-download.d.ts +2 -0
  78. package/dist/examples/parallel-download.js +21 -0
  79. package/dist/examples/rag/rag-chromadb.d.ts +2 -0
  80. package/dist/examples/rag/rag-chromadb.js +130 -0
  81. package/dist/examples/rag/rag-hyperdb-workspaces.d.ts +2 -0
  82. package/dist/examples/rag/rag-hyperdb-workspaces.js +106 -0
  83. package/dist/examples/rag/rag-hyperdb.d.ts +2 -0
  84. package/dist/examples/rag/rag-hyperdb.js +50 -0
  85. package/dist/examples/rag/rag-lancedb.d.ts +2 -0
  86. package/dist/examples/rag/rag-lancedb.js +95 -0
  87. package/dist/examples/rag/rag-sqlite.d.ts +2 -0
  88. package/dist/examples/rag/rag-sqlite.js +107 -0
  89. package/dist/examples/seed-hyperdrive.d.ts +2 -0
  90. package/dist/examples/seed-hyperdrive.js +21 -0
  91. package/dist/examples/translation/translation-indic.d.ts +2 -0
  92. package/dist/examples/translation/translation-indic.js +30 -0
  93. package/dist/examples/translation/translation-llm-context.d.ts +2 -0
  94. package/dist/examples/translation/translation-llm-context.js +30 -0
  95. package/dist/examples/translation/translation-llm.d.ts +2 -0
  96. package/dist/examples/translation/translation-llm.js +38 -0
  97. package/dist/examples/translation/translation-opus.d.ts +2 -0
  98. package/dist/examples/translation/translation-opus.js +30 -0
  99. package/dist/examples/translation/translation-stream.d.ts +2 -0
  100. package/dist/examples/translation/translation-stream.js +35 -0
  101. package/dist/examples/whispercpp-filesystem.d.ts +2 -0
  102. package/dist/examples/whispercpp-filesystem.js +43 -0
  103. package/dist/examples/whispercpp-microphone-record.d.ts +2 -0
  104. package/dist/examples/whispercpp-microphone-record.js +311 -0
  105. package/dist/expo/plugins/index.d.ts +5 -0
  106. package/dist/expo/plugins/index.js +5 -0
  107. package/dist/expo/plugins/withMobileBundle.d.ts +8 -0
  108. package/dist/expo/plugins/withMobileBundle.js +60 -0
  109. package/dist/expo/plugins/withOpenCL.d.ts +9 -0
  110. package/dist/expo/plugins/withOpenCL.js +118 -0
  111. package/dist/expo/plugins/withQvacSDK.d.ts +9 -0
  112. package/dist/expo/plugins/withQvacSDK.js +13 -0
  113. package/dist/index.d.ts +7 -0
  114. package/dist/index.js +8 -0
  115. package/dist/logging/base-logger.d.ts +7 -0
  116. package/dist/logging/base-logger.js +55 -0
  117. package/dist/logging/index.d.ts +4 -0
  118. package/dist/logging/index.js +2 -0
  119. package/dist/logging/logger.d.ts +5 -0
  120. package/dist/logging/logger.js +28 -0
  121. package/dist/logging/stream-logger.d.ts +3 -0
  122. package/dist/logging/stream-logger.js +9 -0
  123. package/dist/logging/transport.d.ts +3 -0
  124. package/dist/logging/transport.js +15 -0
  125. package/dist/logging/types.d.ts +18 -0
  126. package/dist/logging/types.js +1 -0
  127. package/dist/logging/utils.d.ts +4 -0
  128. package/dist/logging/utils.js +47 -0
  129. package/dist/models/hyperdrive/index.d.ts +2 -0
  130. package/dist/models/hyperdrive/index.js +2 -0
  131. package/dist/models/hyperdrive/models.d.ts +475 -0
  132. package/dist/models/hyperdrive/models.js +534 -0
  133. package/dist/schemas/cancel.d.ts +33 -0
  134. package/dist/schemas/cancel.js +25 -0
  135. package/dist/schemas/common.d.ts +626 -0
  136. package/dist/schemas/common.js +47 -0
  137. package/dist/schemas/completion-stream.d.ts +125 -0
  138. package/dist/schemas/completion-stream.js +53 -0
  139. package/dist/schemas/delegate.d.ts +9 -0
  140. package/dist/schemas/delegate.js +9 -0
  141. package/dist/schemas/download-asset.d.ts +75 -0
  142. package/dist/schemas/download-asset.js +43 -0
  143. package/dist/schemas/embed.d.ts +20 -0
  144. package/dist/schemas/embed.js +14 -0
  145. package/dist/schemas/error.d.ts +13 -0
  146. package/dist/schemas/error.js +35 -0
  147. package/dist/schemas/index.d.ts +19 -0
  148. package/dist/schemas/index.js +19 -0
  149. package/dist/schemas/llamacpp-config.d.ts +30 -0
  150. package/dist/schemas/llamacpp-config.js +39 -0
  151. package/dist/schemas/load-model.d.ts +1259 -0
  152. package/dist/schemas/load-model.js +108 -0
  153. package/dist/schemas/logging-stream.d.ts +27 -0
  154. package/dist/schemas/logging-stream.js +16 -0
  155. package/dist/schemas/ping.d.ts +11 -0
  156. package/dist/schemas/ping.js +8 -0
  157. package/dist/schemas/provide.d.ts +43 -0
  158. package/dist/schemas/provide.js +25 -0
  159. package/dist/schemas/rag.d.ts +159 -0
  160. package/dist/schemas/rag.js +78 -0
  161. package/dist/schemas/transcription.d.ts +24 -0
  162. package/dist/schemas/transcription.js +15 -0
  163. package/dist/schemas/translate.d.ts +82 -0
  164. package/dist/schemas/translate.js +42 -0
  165. package/dist/schemas/translation-config.d.ts +83 -0
  166. package/dist/schemas/translation-config.js +46 -0
  167. package/dist/schemas/unload-model.d.ts +19 -0
  168. package/dist/schemas/unload-model.js +13 -0
  169. package/dist/schemas/whispercpp-config.d.ts +25 -0
  170. package/dist/schemas/whispercpp-config.js +18 -0
  171. package/dist/server/bare/addons/cancel.d.ts +3 -0
  172. package/dist/server/bare/addons/cancel.js +12 -0
  173. package/dist/server/bare/addons/index.d.ts +4 -0
  174. package/dist/server/bare/addons/index.js +3 -0
  175. package/dist/server/bare/addons/llamacpp/create-model.d.ts +5 -0
  176. package/dist/server/bare/addons/llamacpp/create-model.js +57 -0
  177. package/dist/server/bare/addons/llamacpp/handlers/completion-stream.d.ts +3 -0
  178. package/dist/server/bare/addons/llamacpp/handlers/completion-stream.js +65 -0
  179. package/dist/server/bare/addons/llamacpp/handlers/embed.d.ts +4 -0
  180. package/dist/server/bare/addons/llamacpp/handlers/embed.js +40 -0
  181. package/dist/server/bare/addons/llamacpp/index.d.ts +4 -0
  182. package/dist/server/bare/addons/llamacpp/index.js +3 -0
  183. package/dist/server/bare/addons/llamacpp/kv-cache-utils.d.ts +19 -0
  184. package/dist/server/bare/addons/llamacpp/kv-cache-utils.js +46 -0
  185. package/dist/server/bare/addons/load-model.d.ts +3 -0
  186. package/dist/server/bare/addons/load-model.js +55 -0
  187. package/dist/server/bare/addons/translation/create-model.d.ts +4 -0
  188. package/dist/server/bare/addons/translation/create-model.js +45 -0
  189. package/dist/server/bare/addons/translation/handlers/translate.d.ts +3 -0
  190. package/dist/server/bare/addons/translation/handlers/translate.js +86 -0
  191. package/dist/server/bare/addons/translation/index.d.ts +3 -0
  192. package/dist/server/bare/addons/translation/index.js +2 -0
  193. package/dist/server/bare/addons/unload-model.d.ts +3 -0
  194. package/dist/server/bare/addons/unload-model.js +20 -0
  195. package/dist/server/bare/addons/whispercpp/create-model.d.ts +6 -0
  196. package/dist/server/bare/addons/whispercpp/create-model.js +55 -0
  197. package/dist/server/bare/addons/whispercpp/handlers/transcribe-stream.d.ts +3 -0
  198. package/dist/server/bare/addons/whispercpp/handlers/transcribe-stream.js +42 -0
  199. package/dist/server/bare/addons/whispercpp/index.d.ts +3 -0
  200. package/dist/server/bare/addons/whispercpp/index.js +2 -0
  201. package/dist/server/bare/delegate-rpc-client.d.ts +4 -0
  202. package/dist/server/bare/delegate-rpc-client.js +70 -0
  203. package/dist/server/bare/hyperswarm.d.ts +7 -0
  204. package/dist/server/bare/hyperswarm.js +62 -0
  205. package/dist/server/bare/rag-hyperdb/handlers/delete-embeddings.d.ts +3 -0
  206. package/dist/server/bare/rag-hyperdb/handlers/delete-embeddings.js +12 -0
  207. package/dist/server/bare/rag-hyperdb/handlers/save-embeddings.d.ts +6 -0
  208. package/dist/server/bare/rag-hyperdb/handlers/save-embeddings.js +16 -0
  209. package/dist/server/bare/rag-hyperdb/handlers/search.d.ts +3 -0
  210. package/dist/server/bare/rag-hyperdb/handlers/search.js +15 -0
  211. package/dist/server/bare/rag-hyperdb/index.d.ts +5 -0
  212. package/dist/server/bare/rag-hyperdb/index.js +4 -0
  213. package/dist/server/bare/rag-hyperdb/rag-manager.d.ts +5 -0
  214. package/dist/server/bare/rag-hyperdb/rag-manager.js +61 -0
  215. package/dist/server/bare/registry/logging-stream-registry.d.ts +12 -0
  216. package/dist/server/bare/registry/logging-stream-registry.js +46 -0
  217. package/dist/server/bare/registry/model-registry.d.ts +64 -0
  218. package/dist/server/bare/registry/model-registry.js +95 -0
  219. package/dist/server/error-handlers.d.ts +4 -0
  220. package/dist/server/error-handlers.js +27 -0
  221. package/dist/server/http-server.d.ts +2 -0
  222. package/dist/server/http-server.js +189 -0
  223. package/dist/server/rpc/create-server.d.ts +4 -0
  224. package/dist/server/rpc/create-server.js +19 -0
  225. package/dist/server/rpc/handle-request.d.ts +12 -0
  226. package/dist/server/rpc/handle-request.js +220 -0
  227. package/dist/server/rpc/handlers/cancelHandler.d.ts +3 -0
  228. package/dist/server/rpc/handlers/cancelHandler.js +27 -0
  229. package/dist/server/rpc/handlers/completion-stream-delegated.d.ts +3 -0
  230. package/dist/server/rpc/handlers/completion-stream-delegated.js +30 -0
  231. package/dist/server/rpc/handlers/completion-stream.d.ts +3 -0
  232. package/dist/server/rpc/handlers/completion-stream.js +52 -0
  233. package/dist/server/rpc/handlers/download-asset.d.ts +3 -0
  234. package/dist/server/rpc/handlers/download-asset.js +21 -0
  235. package/dist/server/rpc/handlers/embed.d.ts +3 -0
  236. package/dist/server/rpc/handlers/embed.js +21 -0
  237. package/dist/server/rpc/handlers/index.d.ts +23 -0
  238. package/dist/server/rpc/handlers/index.js +22 -0
  239. package/dist/server/rpc/handlers/load-model/download-manager.d.ts +31 -0
  240. package/dist/server/rpc/handlers/load-model/download-manager.js +88 -0
  241. package/dist/server/rpc/handlers/load-model/http.d.ts +3 -0
  242. package/dist/server/rpc/handlers/load-model/http.js +337 -0
  243. package/dist/server/rpc/handlers/load-model/hyperdrive.d.ts +4 -0
  244. package/dist/server/rpc/handlers/load-model/hyperdrive.js +332 -0
  245. package/dist/server/rpc/handlers/load-model/index.d.ts +4 -0
  246. package/dist/server/rpc/handlers/load-model/index.js +3 -0
  247. package/dist/server/rpc/handlers/load-model/resolve.d.ts +3 -0
  248. package/dist/server/rpc/handlers/load-model/resolve.js +121 -0
  249. package/dist/server/rpc/handlers/load-model-delegated.d.ts +3 -0
  250. package/dist/server/rpc/handlers/load-model-delegated.js +93 -0
  251. package/dist/server/rpc/handlers/load-model.d.ts +3 -0
  252. package/dist/server/rpc/handlers/load-model.js +41 -0
  253. package/dist/server/rpc/handlers/logging-stream.d.ts +3 -0
  254. package/dist/server/rpc/handlers/logging-stream.js +37 -0
  255. package/dist/server/rpc/handlers/provideHandler/connection.d.ts +3 -0
  256. package/dist/server/rpc/handlers/provideHandler/connection.js +25 -0
  257. package/dist/server/rpc/handlers/provideHandler/handler.d.ts +3 -0
  258. package/dist/server/rpc/handlers/provideHandler/handler.js +50 -0
  259. package/dist/server/rpc/handlers/provideHandler/proxy.d.ts +3 -0
  260. package/dist/server/rpc/handlers/provideHandler/proxy.js +22 -0
  261. package/dist/server/rpc/handlers/provideHandler.d.ts +2 -0
  262. package/dist/server/rpc/handlers/provideHandler.js +2 -0
  263. package/dist/server/rpc/handlers/rag.d.ts +3 -0
  264. package/dist/server/rpc/handlers/rag.js +67 -0
  265. package/dist/server/rpc/handlers/transcribe-stream.d.ts +3 -0
  266. package/dist/server/rpc/handlers/transcribe-stream.js +26 -0
  267. package/dist/server/rpc/handlers/translate.d.ts +3 -0
  268. package/dist/server/rpc/handlers/translate.js +51 -0
  269. package/dist/server/rpc/handlers/unload-model.d.ts +3 -0
  270. package/dist/server/rpc/handlers/unload-model.js +20 -0
  271. package/dist/server/rpc/index.d.ts +3 -0
  272. package/dist/server/rpc/index.js +2 -0
  273. package/dist/server/utils/audio/decoder.d.ts +4 -0
  274. package/dist/server/utils/audio/decoder.js +41 -0
  275. package/dist/server/utils/cache.d.ts +15 -0
  276. package/dist/server/utils/cache.js +32 -0
  277. package/dist/server/utils/hash.d.ts +5 -0
  278. package/dist/server/utils/hash.js +11 -0
  279. package/dist/server/utils/index.d.ts +5 -0
  280. package/dist/server/utils/index.js +4 -0
  281. package/dist/server/utils/model-path.d.ts +5 -0
  282. package/dist/server/utils/model-path.js +7 -0
  283. package/dist/server/worker.d.ts +6 -0
  284. package/dist/server/worker.js +77 -0
  285. package/dist/utils/withTimeout.d.ts +11 -0
  286. package/dist/utils/withTimeout.js +37 -0
  287. package/package.json +129 -0
@@ -0,0 +1,332 @@
1
+ import fs, { promises as fsPromises } from "bare-fs";
2
+ import path from "bare-path";
3
+ import crypto from "bare-crypto";
4
+ import Corestore from "corestore";
5
+ import Hyperswarm, {} from "hyperswarm";
6
+ import Hyperdrive from "hyperdrive";
7
+ import {} from "bare-stream";
8
+ import { AbortController } from "bare-abort-controller";
9
+ import { getEnv } from "../../../worker.js";
10
+ import { getModelsCacheDir, generateShortHash } from "../../../utils/index.js";
11
+ import { getModelBySrc } from "../../../../models/hyperdrive/index.js";
12
+ import { getActiveDownload, registerDownload, unregisterDownload, createHyperdriveDownloadKey, shouldClearCache, clearClearCacheFlag, } from "./download-manager.js";
13
+ async function setupHyperdrive(hyperdriveKey, corestoreDir) {
14
+ const corestore = new Corestore(corestoreDir);
15
+ await corestore.ready();
16
+ const drive = new Hyperdrive(corestore, Buffer.from(hyperdriveKey, "hex"));
17
+ await drive.ready();
18
+ const swarm = new Hyperswarm();
19
+ swarm.join(drive.discoveryKey, { server: false, client: true });
20
+ swarm.on("connection", (connection) => {
21
+ console.log(`🤝 Connected to peer for hyperdrive download`);
22
+ drive.replicate(connection);
23
+ });
24
+ const doneFindingPeers = drive.findingPeers();
25
+ await swarm.flush();
26
+ doneFindingPeers();
27
+ return { corestore, drive, swarm, corestoreDir };
28
+ }
29
+ async function cleanupHyperdrive(setup) {
30
+ console.log("🧹 Cleaning up hyperdrive setup");
31
+ await setup.swarm.destroy();
32
+ await setup.drive.close();
33
+ await setup.corestore.close();
34
+ }
35
+ export async function deleteCorestoreDirectory(corestoreDir) {
36
+ console.log(`🗑️ DELETING corestore directory... ${corestoreDir}`);
37
+ try {
38
+ await fsPromises.rm(corestoreDir, { recursive: true, force: true });
39
+ }
40
+ catch (e) {
41
+ console.error(`Error deleting corestore directory: ${e instanceof Error ? e.message : String(e)}`);
42
+ }
43
+ }
44
+ async function findFileInHyperdrive(drive, modelFileName) {
45
+ const paths = [modelFileName, `/${modelFileName}`, `./${modelFileName}`];
46
+ let entry = null;
47
+ let targetPath = modelFileName;
48
+ for (const pathVariation of paths) {
49
+ try {
50
+ entry = await drive.entry(pathVariation);
51
+ if (entry) {
52
+ targetPath = pathVariation;
53
+ break;
54
+ }
55
+ }
56
+ catch {
57
+ // Continue trying other paths
58
+ }
59
+ }
60
+ if (!entry) {
61
+ // Try listing available files to help debug
62
+ try {
63
+ const rootFiles = drive.list("/", false);
64
+ const availableFiles = [];
65
+ for await (const file of rootFiles) {
66
+ availableFiles.push(file.key);
67
+ }
68
+ if (availableFiles.length === 0) {
69
+ // Try without leading slash
70
+ const noSlashFiles = drive.list("", false);
71
+ for await (const file of noSlashFiles) {
72
+ availableFiles.push(file.key);
73
+ }
74
+ }
75
+ throw new Error(`File ${modelFileName} not found in hyperdrive. Available files: ${availableFiles.join(", ")}`);
76
+ }
77
+ catch (listError) {
78
+ throw new Error(`File ${modelFileName} not found in hyperdrive. Could not list available files: ${listError instanceof Error ? listError.message : String(listError)}`);
79
+ }
80
+ }
81
+ return { entry, targetPath };
82
+ }
83
+ async function validateFileChecksum(filePath, expectedChecksum) {
84
+ console.log(`🔍 Validating SHA256 checksum...`);
85
+ return new Promise((resolve) => {
86
+ try {
87
+ const hash = crypto.createHash("sha256");
88
+ const stream = fs.createReadStream(filePath);
89
+ stream.on("data", (chunk) => {
90
+ hash.update(chunk);
91
+ });
92
+ stream.on("end", () => {
93
+ const actualChecksum = hash.digest("hex");
94
+ console.log(`Expected: ${String(expectedChecksum)}`);
95
+ console.log(`Actual: ${String(actualChecksum)}`);
96
+ const isValid = actualChecksum === expectedChecksum;
97
+ if (isValid) {
98
+ console.log(`✅ Checksum validation passed!`);
99
+ }
100
+ else {
101
+ console.log(`❌ Checksum validation FAILED! File may be corrupted.`);
102
+ }
103
+ resolve(isValid);
104
+ });
105
+ stream.on("error", (error) => {
106
+ console.error(`❌ Error validating checksum: ${error.message}`);
107
+ resolve(false);
108
+ });
109
+ }
110
+ catch (error) {
111
+ console.error(`❌ Error validating checksum: ${error instanceof Error ? error.message : String(error)}`);
112
+ resolve(false);
113
+ }
114
+ });
115
+ }
116
+ async function validateCachedFile(modelPath, modelFileName, expectedSize, expectedChecksum) {
117
+ try {
118
+ await fsPromises.access(modelPath);
119
+ const localStats = await fsPromises.stat(modelPath);
120
+ const localSize = localStats.size;
121
+ // For hyperdrive: only validate if file is complete
122
+ // Partial files are ignored - corestore state is the source of truth for resume
123
+ if (localSize === expectedSize) {
124
+ console.log(`✅ Model cached with correct size: ${modelPath}`);
125
+ // Always validate checksum if provided, even when size matches
126
+ if (expectedChecksum && expectedChecksum.length === 64) {
127
+ const isValid = await validateFileChecksum(modelPath, expectedChecksum);
128
+ if (isValid) {
129
+ return modelPath;
130
+ }
131
+ else {
132
+ throw new Error(`File ${modelFileName} is fully downloaded but checksum validation failed. Expected: ${expectedChecksum}. File may be corrupted.`);
133
+ }
134
+ }
135
+ else {
136
+ console.log(`✅ Model already cached and size validated: ${modelPath}`);
137
+ return modelPath;
138
+ }
139
+ }
140
+ // File exists but incomplete - will be overwritten during download
141
+ // Resume state will be determined by corestore blocks, not file size
142
+ return null;
143
+ }
144
+ catch {
145
+ // Model doesn't exist, need to download
146
+ return null;
147
+ }
148
+ }
149
+ async function performHyperdriveDownload(modelPath, modelFileName, hyperdriveKey, corestoreDir, downloadKey, progressCallback, seed, signal) {
150
+ // Check if already aborted
151
+ if (signal?.aborted) {
152
+ throw new Error("Download cancelled");
153
+ }
154
+ console.log(`Downloading model from hyperdrive ${hyperdriveKey} to ${modelPath}`);
155
+ const setup = await setupHyperdrive(hyperdriveKey, corestoreDir);
156
+ let downloadedBytes = 0;
157
+ let totalBytes = 0;
158
+ // Set up abort handler
159
+ let readStream;
160
+ let writeStream;
161
+ const cleanup = () => {
162
+ console.log("🛑 Aborting hyperdrive download...");
163
+ // Destroy streams if they exist
164
+ if (readStream) {
165
+ readStream.destroy();
166
+ }
167
+ if (writeStream) {
168
+ writeStream.destroy();
169
+ }
170
+ };
171
+ signal?.addEventListener("abort", cleanup);
172
+ try {
173
+ const result = await findFileInHyperdrive(setup.drive, modelFileName);
174
+ const { entry, targetPath } = result;
175
+ totalBytes = entry?.value?.blob?.byteLength || 0;
176
+ console.log(`📏 Model size: ${totalBytes} bytes (${(totalBytes / 1024 / 1024).toFixed(2)} MB)`);
177
+ // Get blobs and file blob range
178
+ const blobs = await setup.drive.getBlobs();
179
+ const blob = entry?.value?.blob;
180
+ if (!blob) {
181
+ throw new Error(`No blob found for ${modelFileName}`);
182
+ }
183
+ // Check what blocks are already downloaded in corestore for this specific file
184
+ let alreadyDownloaded = 0;
185
+ for (let i = blob.blockOffset; i < blob.blockOffset + blob.blockLength; i++) {
186
+ const hasBlock = await blobs.core.has(i);
187
+ if (hasBlock) {
188
+ alreadyDownloaded++;
189
+ }
190
+ }
191
+ downloadedBytes = 0;
192
+ if (alreadyDownloaded > 0) {
193
+ console.log(`📥 Resuming download (${alreadyDownloaded}/${blob.blockLength} blocks already in corestore)`);
194
+ }
195
+ else {
196
+ console.log(`📥 Starting fresh download`);
197
+ }
198
+ // Track only downloads for blocks within our file's blob range
199
+ blobs.core.on("download", (index, bytes) => {
200
+ if (index >= blob.blockOffset &&
201
+ index < blob.blockOffset + blob.blockLength) {
202
+ downloadedBytes += bytes;
203
+ if (progressCallback) {
204
+ progressCallback({
205
+ type: "modelProgress",
206
+ downloaded: downloadedBytes,
207
+ total: totalBytes,
208
+ percentage: totalBytes > 0 ? (downloadedBytes / totalBytes) * 100 : 0,
209
+ downloadKey,
210
+ });
211
+ }
212
+ }
213
+ });
214
+ // Check if aborted before starting streams
215
+ if (signal?.aborted) {
216
+ throw new Error("Download cancelled");
217
+ }
218
+ // Trigger download for this file (hyperdrive will only download missing blocks)
219
+ setup.drive.download(targetPath);
220
+ readStream = setup.drive.createReadStream(targetPath);
221
+ writeStream = fs.createWriteStream(modelPath);
222
+ // Pipe the streams
223
+ readStream.pipe(writeStream);
224
+ // Wait for download to complete
225
+ await new Promise((resolve, reject) => {
226
+ writeStream.on("finish", () => resolve(undefined));
227
+ writeStream.on("error", reject);
228
+ readStream.on("error", reject);
229
+ // Also reject on abort
230
+ if (signal) {
231
+ signal.addEventListener("abort", () => {
232
+ reject(new Error("Download cancelled"));
233
+ }, { once: true });
234
+ }
235
+ });
236
+ console.log(`✅ Model downloaded successfully to ${modelPath}`);
237
+ // Delete corestore directory after successful download (only when not seeding, to save space)
238
+ if (!seed) {
239
+ await deleteCorestoreDirectory(setup.corestoreDir);
240
+ }
241
+ }
242
+ catch (error) {
243
+ console.error("❌ Error during hyperdrive download:", error instanceof Error ? error.message : String(error));
244
+ // Preserve cancellation errors
245
+ if (error instanceof Error && error.message === "Download cancelled") {
246
+ throw error;
247
+ }
248
+ throw new Error(`Download failed for ${modelFileName} from hyperdrive: ${hyperdriveKey}`);
249
+ }
250
+ finally {
251
+ signal?.removeEventListener("abort", cleanup);
252
+ if (!seed) {
253
+ await cleanupHyperdrive(setup);
254
+ }
255
+ // Only delete corestore and partial file if user explicitly requested clearCache
256
+ if (signal?.aborted) {
257
+ if (shouldClearCache(downloadKey)) {
258
+ try {
259
+ await fsPromises.unlink(modelPath);
260
+ }
261
+ catch {
262
+ // no-op
263
+ }
264
+ await deleteCorestoreDirectory(corestoreDir);
265
+ }
266
+ clearClearCacheFlag(downloadKey);
267
+ }
268
+ }
269
+ }
270
+ export async function downloadModelFromHyperdrive(hyperdriveKey, modelFileName, seed, progressCallback, expectedChecksum) {
271
+ const downloadKey = createHyperdriveDownloadKey(hyperdriveKey, modelFileName);
272
+ // Check if already downloading
273
+ const existing = getActiveDownload(downloadKey);
274
+ if (existing) {
275
+ return existing.promise;
276
+ }
277
+ const corestoreDir = path.join(getEnv().HOME_DIR, ".qvac", "corestore", hyperdriveKey);
278
+ const cacheDir = getModelsCacheDir();
279
+ const sourceHash = generateShortHash(`${hyperdriveKey}/${modelFileName}`);
280
+ const modelPath = path.join(cacheDir, `${sourceHash}_${modelFileName}`);
281
+ // Get model definition to get expected size (if it's a known model)
282
+ const model = getModelBySrc(modelFileName, hyperdriveKey);
283
+ // First, check if we already have a valid cached file (only if we have model metadata)
284
+ if (model) {
285
+ const cachedPath = await validateCachedFile(modelPath, modelFileName, model.expectedSize, expectedChecksum || model.sha256Checksum);
286
+ if (cachedPath) {
287
+ // Delete any leftover corestore directory from previous runs (only when not seeding)
288
+ if (!seed) {
289
+ await deleteCorestoreDirectory(corestoreDir);
290
+ }
291
+ return cachedPath;
292
+ }
293
+ }
294
+ // Create managed download with AbortController
295
+ const abortController = new AbortController();
296
+ const downloadPromise = (async () => {
297
+ try {
298
+ // Download the file from hyperdrive
299
+ await performHyperdriveDownload(modelPath, modelFileName, hyperdriveKey, corestoreDir, downloadKey, progressCallback, seed, abortController.signal);
300
+ // Validate checksum using provided checksum or model's checksum (if available)
301
+ const checksumToValidate = expectedChecksum || model?.sha256Checksum;
302
+ if (checksumToValidate && checksumToValidate.length === 64) {
303
+ const isValid = await validateFileChecksum(modelPath, checksumToValidate);
304
+ if (!isValid) {
305
+ await fsPromises.unlink(modelPath);
306
+ throw new Error(`Checksum validation failed for ${modelFileName}`);
307
+ }
308
+ }
309
+ else {
310
+ console.log(`⚠️ No valid checksum available for validation`);
311
+ }
312
+ return modelPath;
313
+ }
314
+ finally {
315
+ // Cleanup from download manager
316
+ unregisterDownload(downloadKey);
317
+ }
318
+ })();
319
+ // Register download
320
+ const downloadEntry = {
321
+ key: downloadKey,
322
+ promise: downloadPromise,
323
+ abortController,
324
+ startTime: Date.now(),
325
+ type: "hyperdrive",
326
+ hyperdriveKey,
327
+ modelFileName,
328
+ ...(progressCallback && { onProgress: progressCallback }),
329
+ };
330
+ registerDownload(downloadKey, downloadEntry);
331
+ return downloadPromise;
332
+ }
@@ -0,0 +1,4 @@
1
+ export { handleLoadModel } from "../load-model";
2
+ export { downloadModelFromHyperdrive } from "./hyperdrive";
3
+ export { resolveModelPath } from "./resolve";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,3 @@
1
+ export { handleLoadModel } from "../load-model";
2
+ export { downloadModelFromHyperdrive } from "./hyperdrive.js";
3
+ export { resolveModelPath } from "./resolve.js";
@@ -0,0 +1,3 @@
1
+ import { type ModelProgressUpdate } from "../../../../schemas/index";
2
+ export declare function resolveModelPath(modelSrc: string, progressCallback?: (progress: ModelProgressUpdate) => void, seed?: boolean): Promise<string>;
3
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1,121 @@
1
+ import { getModelBySrc, models } from "../../../../models/hyperdrive/models.js";
2
+ import { hyperdriveUrlSchema } from "../../../../schemas/index.js";
3
+ import { getModelsCacheDir } from "../../../utils/index.js";
4
+ import { promises as fsPromises } from "bare-fs";
5
+ import path from "bare-path";
6
+ import { downloadModelFromHttp } from "./http.js";
7
+ import { downloadModelFromHyperdrive } from "./hyperdrive.js";
8
+ /**
9
+ * Attempts to resolve a model from cache (without validation)
10
+ * Validation will be handled by the hyperdrive download logic
11
+ */
12
+ async function tryResolveCachedModel(modelId) {
13
+ const cacheDir = getModelsCacheDir();
14
+ const cachedPath = path.join(cacheDir, modelId);
15
+ try {
16
+ await fsPromises.access(cachedPath);
17
+ // File exists - return null to let hyperdrive validation handle size/checksum
18
+ // This ensures partial downloads are properly resumed instead of being
19
+ // incorrectly validated and deleted
20
+ return null;
21
+ }
22
+ catch {
23
+ // File doesn't exist
24
+ return null;
25
+ }
26
+ }
27
+ /**
28
+ * Resolves a known model by ID from hyperdrive, checking cache first
29
+ */
30
+ async function resolveKnownModel(model, modelIdOrPath, progressCallback, seed) {
31
+ if (!model) {
32
+ throw new Error("Model is null");
33
+ }
34
+ console.log(`Loading model ID '${modelIdOrPath}' from hyperdrive`);
35
+ // Try to resolve from cache first
36
+ const cachedPath = await tryResolveCachedModel(model.modelId);
37
+ if (cachedPath) {
38
+ return cachedPath;
39
+ }
40
+ // Not cached or invalid, download from hyperdrive
41
+ const downloadedPath = await downloadModelFromHyperdrive(model.hyperdriveKey, model.modelId, seed, progressCallback, model.sha256Checksum);
42
+ return downloadedPath;
43
+ }
44
+ /**
45
+ * Resolves a local file path or cached file
46
+ */
47
+ async function resolveLocalOrCachedFile(modelIdOrPath) {
48
+ // Check if it's a hex string (arbitrary hyperdrive key)
49
+ const isHexString = /^[0-9a-fA-F]{64}$/.test(modelIdOrPath);
50
+ if (isHexString) {
51
+ throw new Error(`Direct hyperdrive keys not supported. Use hyperdriveKey parameter instead. Example: loadModel("model.gguf", "${modelIdOrPath}")`);
52
+ }
53
+ // Check if it's a cached file or local file
54
+ const cacheDir = getModelsCacheDir();
55
+ const cachedPath = path.join(cacheDir, modelIdOrPath);
56
+ try {
57
+ await fsPromises.access(cachedPath);
58
+ console.log(`Loading cached model: ${cachedPath}`);
59
+ return cachedPath;
60
+ }
61
+ catch {
62
+ // Try as local file in current directory
63
+ try {
64
+ await fsPromises.access(modelIdOrPath);
65
+ console.log(`Loading local file: ${modelIdOrPath}`);
66
+ return modelIdOrPath;
67
+ }
68
+ catch {
69
+ // Invalid model ID - provide helpful error
70
+ const availableModels = models.map((m) => m.modelId);
71
+ throw new Error(`Invalid model ID: "${modelIdOrPath}". Available models: ${availableModels.join(", ")}`);
72
+ }
73
+ }
74
+ }
75
+ export async function resolveModelPath(modelSrc, progressCallback, seed) {
76
+ // Parse hyperdrive URLs if present
77
+ let hyperdriveKey;
78
+ let actualModelSrc = modelSrc;
79
+ if (modelSrc.startsWith("pear://")) {
80
+ const { key, path } = hyperdriveUrlSchema.parse(modelSrc);
81
+ hyperdriveKey = key;
82
+ actualModelSrc = path;
83
+ }
84
+ let actualPath;
85
+ // Validate seeding is only used with hyperdrive models
86
+ if (seed && !hyperdriveKey) {
87
+ const model = getModelBySrc(actualModelSrc);
88
+ if (!model) {
89
+ throw new Error("Seeding is only supported for hyperdrive models");
90
+ }
91
+ }
92
+ // Check if it's an HTTP/HTTPS URL
93
+ if (actualModelSrc.startsWith("http://") ||
94
+ actualModelSrc.startsWith("https://")) {
95
+ console.log(`Loading from HTTP URL: ${actualModelSrc}`);
96
+ actualPath = await downloadModelFromHttp(actualModelSrc, progressCallback);
97
+ console.log(`Loaded Model to ${actualPath}`);
98
+ }
99
+ else if (hyperdriveKey) {
100
+ // Direct hyperdrive loading
101
+ console.log(`Loading from hyperdrive: ${hyperdriveKey}`);
102
+ actualPath = await downloadModelFromHyperdrive(hyperdriveKey, actualModelSrc, seed, progressCallback);
103
+ }
104
+ else {
105
+ // Try to resolve as a known model ID
106
+ const model = getModelBySrc(actualModelSrc);
107
+ if (model) {
108
+ actualPath = await resolveKnownModel(model, actualModelSrc, progressCallback, seed);
109
+ }
110
+ else if (actualModelSrc.includes("/") || actualModelSrc.includes("\\")) {
111
+ // Handle file paths (absolute or relative with slashes)
112
+ console.log(`Loading from file: ${actualModelSrc}`);
113
+ actualPath = actualModelSrc;
114
+ }
115
+ else {
116
+ // Handle local files and cached files
117
+ actualPath = await resolveLocalOrCachedFile(actualModelSrc);
118
+ }
119
+ }
120
+ return actualPath;
121
+ }
@@ -0,0 +1,3 @@
1
+ import type { LoadModelRequest, LoadModelResponse, ModelProgressUpdate } from "../../../schemas/index";
2
+ export declare function handleLoadModelDelegated(request: LoadModelRequest, progressCallback?: (update: ModelProgressUpdate) => void): Promise<LoadModelResponse>;
3
+ //# sourceMappingURL=load-model-delegated.d.ts.map
@@ -0,0 +1,93 @@
1
+ import { registerModel } from "../../bare/registry/model-registry.js";
2
+ import { getRPC } from "../../bare/delegate-rpc-client.js";
3
+ import { send, stream } from "../../../client/rpc/rpc-client.js";
4
+ import { handleLoadModel } from "./load-model/index.js";
5
+ export async function handleLoadModelDelegated(request, progressCallback) {
6
+ if (!request.delegate) {
7
+ throw new Error("Delegate information is required for delegated load model");
8
+ }
9
+ const { delegate } = request;
10
+ const { topic, providerPublicKey, timeout, fallbackToLocal } = delegate;
11
+ try {
12
+ console.log(`📤 Sending delegated loadModel request to provider: ${providerPublicKey}${timeout ? `, timeout: ${timeout}ms` : ""}`);
13
+ // Create RPC instance for this HyperSwarm peer
14
+ const rpc = await getRPC(topic, providerPublicKey, { timeout });
15
+ // Strip out the delegate field to avoid infinite delegation
16
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
17
+ const { delegate: _, ...providerRequest } = request;
18
+ let finalResponse;
19
+ if (request.withProgress) {
20
+ // Use streaming for progress updates
21
+ console.log("📊 Using streaming mode for loadModel with progress");
22
+ const responseStream = stream(providerRequest, rpc, timeout ? { timeout } : {});
23
+ for await (const response of responseStream) {
24
+ if (response.type === "modelProgress") {
25
+ // Forward progress updates to the client
26
+ if (progressCallback) {
27
+ progressCallback(response);
28
+ }
29
+ }
30
+ else if (response.type === "loadModel") {
31
+ finalResponse = response;
32
+ break;
33
+ }
34
+ }
35
+ if (!finalResponse) {
36
+ throw new Error("No final response received from provider");
37
+ }
38
+ }
39
+ else {
40
+ // Use simple send for non-progress requests
41
+ console.log("📤 Using simple send mode for loadModel");
42
+ finalResponse = (await send(providerRequest, rpc, timeout ? { timeout } : {}));
43
+ }
44
+ if (!finalResponse || !finalResponse.success) {
45
+ console.error("Provider failed to load model:", finalResponse?.error);
46
+ return {
47
+ type: "loadModel",
48
+ success: false,
49
+ error: `Provider failed to load model: ${finalResponse?.error || "Unknown error"}`,
50
+ };
51
+ }
52
+ // Register the delegated model with provider info
53
+ const modelId = finalResponse.modelId || request.modelSrc || `delegated-${Date.now()}`;
54
+ const delegateOptions = {
55
+ topic,
56
+ providerPublicKey,
57
+ };
58
+ if (timeout !== undefined) {
59
+ delegateOptions.timeout = timeout;
60
+ }
61
+ registerModel(modelId, delegateOptions);
62
+ console.log(`✅ Delegated model registered: ${modelId} -> provider: ${providerPublicKey}`);
63
+ return {
64
+ type: "loadModel",
65
+ success: true,
66
+ modelId,
67
+ };
68
+ }
69
+ catch (error) {
70
+ console.error("Error in delegated load model:", error);
71
+ if (fallbackToLocal) {
72
+ console.log("🔄 Fallback to local model loading enabled, attempting local load...");
73
+ try {
74
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
75
+ const { delegate: _, ...localRequest } = request;
76
+ return await handleLoadModel(localRequest, progressCallback);
77
+ }
78
+ catch (localError) {
79
+ console.error("❌ Local fallback also failed:", localError);
80
+ return {
81
+ type: "loadModel",
82
+ success: false,
83
+ error: `Both delegated and local loading failed. Delegated error: ${error instanceof Error ? error.message : String(error)}. Local error: ${localError instanceof Error ? localError.message : String(localError)}`,
84
+ };
85
+ }
86
+ }
87
+ return {
88
+ type: "loadModel",
89
+ success: false,
90
+ error: error instanceof Error ? error.message : "Unknown error",
91
+ };
92
+ }
93
+ }
@@ -0,0 +1,3 @@
1
+ import type { LoadModelRequest, LoadModelResponse, ModelProgressUpdate } from "../../../schemas/index";
2
+ export declare function handleLoadModel(request: LoadModelRequest, progressCallback?: (update: ModelProgressUpdate) => void): Promise<LoadModelResponse>;
3
+ //# sourceMappingURL=load-model.d.ts.map
@@ -0,0 +1,41 @@
1
+ import { loadModel } from "../../bare/addons/index.js";
2
+ import { resolveModelPath } from "./load-model/resolve.js";
3
+ import { generateShortHash } from "../../utils/index.js";
4
+ export async function handleLoadModel(request, progressCallback) {
5
+ const { modelSrc, seed, projectionModelSrc, vadModelSrc } = request;
6
+ try {
7
+ const modelPath = await resolveModelPath(modelSrc, progressCallback, seed);
8
+ let projectionModelPath;
9
+ if (projectionModelSrc) {
10
+ projectionModelPath = await resolveModelPath(projectionModelSrc, progressCallback, seed);
11
+ }
12
+ let vadModelPath;
13
+ if (vadModelSrc) {
14
+ vadModelPath = await resolveModelPath(vadModelSrc, progressCallback, seed);
15
+ }
16
+ // Generate hash-based modelId
17
+ const configStr = JSON.stringify(request.modelConfig, Object.keys(request.modelConfig).sort());
18
+ const modelHashInput = `${request.modelType}:${modelSrc}:${configStr}`;
19
+ const modelId = generateShortHash(modelHashInput);
20
+ await loadModel({
21
+ modelId,
22
+ modelPath,
23
+ options: request,
24
+ projectionModelPath,
25
+ vadModelPath,
26
+ });
27
+ return {
28
+ type: "loadModel",
29
+ success: true,
30
+ modelId,
31
+ };
32
+ }
33
+ catch (error) {
34
+ console.error("Error loading model:", error);
35
+ return {
36
+ type: "loadModel",
37
+ success: false,
38
+ error: error instanceof Error ? error.message : "Unknown error",
39
+ };
40
+ }
41
+ }
@@ -0,0 +1,3 @@
1
+ import type { LoggingStreamRequest, LoggingStreamResponse } from "../../../schemas/index";
2
+ export declare function handleLoggingStream(request: LoggingStreamRequest): AsyncGenerator<LoggingStreamResponse>;
3
+ //# sourceMappingURL=logging-stream.d.ts.map
@@ -0,0 +1,37 @@
1
+ import { registerLoggingStream, unregisterLoggingStream, } from "../../bare/registry/logging-stream-registry.js";
2
+ export async function* handleLoggingStream(request) {
3
+ const { modelId } = request;
4
+ const logQueue = [];
5
+ let pendingResolve = null;
6
+ const streamHandler = (level, namespace, message) => {
7
+ const logResponse = {
8
+ type: "loggingStream",
9
+ modelId,
10
+ level: level,
11
+ namespace,
12
+ message,
13
+ timestamp: Date.now(),
14
+ };
15
+ logQueue.push(logResponse);
16
+ if (pendingResolve) {
17
+ const resolve = pendingResolve;
18
+ pendingResolve = null;
19
+ resolve();
20
+ }
21
+ };
22
+ registerLoggingStream(modelId, streamHandler);
23
+ try {
24
+ while (true) {
25
+ while (logQueue.length > 0) {
26
+ yield logQueue.shift();
27
+ }
28
+ // Wait for new logs - stream will terminate when client disconnects
29
+ await new Promise((resolve) => {
30
+ pendingResolve = resolve;
31
+ });
32
+ }
33
+ }
34
+ finally {
35
+ unregisterLoggingStream(modelId, streamHandler);
36
+ }
37
+ }
@@ -0,0 +1,3 @@
1
+ import type Hyperswarm from "hyperswarm";
2
+ export declare function setupConnectionHandlers(swarm: Hyperswarm): void;
3
+ //# sourceMappingURL=connection.d.ts.map