@qvac/sdk 0.2.7-dev.1761566029.f834aa3 → 0.4.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 (215) hide show
  1. package/README.md +26 -3
  2. package/dist/client/api/cancel.d.ts +1 -1
  3. package/dist/client/api/cancel.js +4 -3
  4. package/dist/client/api/completion-stream.d.ts +24 -32
  5. package/dist/client/api/completion-stream.js +142 -50
  6. package/dist/client/api/delete-cache.js +3 -2
  7. package/dist/client/api/download-asset.d.ts +3 -3
  8. package/dist/client/api/download-asset.js +12 -17
  9. package/dist/client/api/embed.d.ts +1 -1
  10. package/dist/client/api/embed.js +4 -3
  11. package/dist/client/api/get-model-info.d.ts +29 -0
  12. package/dist/client/api/get-model-info.js +14 -0
  13. package/dist/client/api/index.d.ts +4 -0
  14. package/dist/client/api/index.js +4 -0
  15. package/dist/client/api/load-model.d.ts +3 -3
  16. package/dist/client/api/load-model.js +13 -22
  17. package/dist/client/api/logging-stream.d.ts +1 -1
  18. package/dist/client/api/logging-stream.js +3 -2
  19. package/dist/client/api/ping.d.ts +1 -1
  20. package/dist/client/api/ping.js +3 -2
  21. package/dist/client/api/provide.d.ts +1 -1
  22. package/dist/client/api/provide.js +4 -3
  23. package/dist/client/api/rag.d.ts +3 -3
  24. package/dist/client/api/rag.js +13 -12
  25. package/dist/client/api/set-config.d.ts +7 -0
  26. package/dist/client/api/set-config.js +20 -0
  27. package/dist/client/api/stop-provider.d.ts +15 -0
  28. package/dist/client/api/stop-provider.js +25 -0
  29. package/dist/client/api/text-to-speech.d.ts +7 -0
  30. package/dist/client/api/text-to-speech.js +58 -0
  31. package/dist/client/api/transcribe.d.ts +4 -2
  32. package/dist/client/api/transcribe.js +9 -5
  33. package/dist/client/api/translate.d.ts +1 -1
  34. package/dist/client/api/translate.js +3 -2
  35. package/dist/client/api/unload-model.d.ts +5 -1
  36. package/dist/client/api/unload-model.js +14 -4
  37. package/dist/client/config-manager.d.ts +4 -0
  38. package/dist/client/config-manager.js +8 -0
  39. package/dist/client/index.d.ts +1 -1
  40. package/dist/client/index.js +1 -1
  41. package/dist/client/init-hooks.d.ts +6 -0
  42. package/dist/client/init-hooks.js +37 -0
  43. package/dist/client/rpc/bare-client.d.ts +73 -0
  44. package/dist/client/rpc/bare-client.js +5 -4
  45. package/dist/client/rpc/bare-rpc-client.js +7 -3
  46. package/dist/client/rpc/expo-rpc-client.d.ts +1 -0
  47. package/dist/client/rpc/expo-rpc-client.js +9 -1
  48. package/dist/client/rpc/node-rpc-client.d.ts +1 -1
  49. package/dist/client/rpc/node-rpc-client.js +22 -9
  50. package/dist/client/rpc/rpc-client.d.ts +1 -0
  51. package/dist/client/rpc/rpc-client.js +27 -3
  52. package/dist/examples/cache-management.d.ts +2 -0
  53. package/dist/examples/cache-management.js +97 -0
  54. package/dist/examples/delegated-inference/consumer.js +2 -2
  55. package/dist/examples/download-with-blind-relays.d.ts +2 -0
  56. package/dist/examples/download-with-blind-relays.js +48 -0
  57. package/dist/examples/download-with-cancel.js +3 -4
  58. package/dist/examples/embed-hyperdrive.js +0 -1
  59. package/dist/examples/kv-cache-cleanup.js +0 -1
  60. package/dist/examples/kv-cache-custom-key.js +0 -1
  61. package/dist/examples/kv-cache-example.js +0 -1
  62. package/dist/examples/llamacpp-file-logging.js +0 -1
  63. package/dist/examples/llamacpp-filesystem.js +2 -2
  64. package/dist/examples/llamacpp-http.js +0 -1
  65. package/dist/examples/llamacpp-hyperdrive.js +0 -1
  66. package/dist/examples/llamacpp-multimodal.js +0 -1
  67. package/dist/examples/llamacpp-native-tools.js +118 -36
  68. package/dist/examples/llamacpp-sharded.d.ts +2 -0
  69. package/dist/examples/llamacpp-sharded.js +44 -0
  70. package/dist/examples/multi-model-demo.js +0 -1
  71. package/dist/examples/parallel-download.js +2 -2
  72. package/dist/examples/rag/rag-chromadb.js +0 -1
  73. package/dist/examples/rag/rag-hyperdb-workspaces.js +0 -1
  74. package/dist/examples/rag/rag-hyperdb.js +0 -1
  75. package/dist/examples/rag/rag-lancedb.js +0 -1
  76. package/dist/examples/rag/rag-sqlite.js +0 -1
  77. package/dist/examples/text-to-speech.d.ts +3 -0
  78. package/dist/examples/text-to-speech.js +137 -0
  79. package/dist/examples/translation/translation-indic.js +3 -1
  80. package/dist/examples/translation/translation-llm-context.js +0 -1
  81. package/dist/examples/translation/translation-llm.js +2 -2
  82. package/dist/examples/translation/translation-opus.js +3 -1
  83. package/dist/examples/translation/translation-stream.js +0 -1
  84. package/dist/examples/whispercpp-filesystem.js +32 -5
  85. package/dist/examples/whispercpp-microphone-record.js +9 -9
  86. package/dist/examples/whispercpp-prompt.d.ts +2 -0
  87. package/dist/examples/whispercpp-prompt.js +68 -0
  88. package/dist/expo/plugins/withMobileBundle.js +9 -3
  89. package/dist/index.d.ts +4 -2
  90. package/dist/index.js +4 -2
  91. package/dist/models/hyperdrive/models.d.ts +1924 -100
  92. package/dist/models/hyperdrive/models.js +2051 -105
  93. package/dist/schemas/common.d.ts +420 -58
  94. package/dist/schemas/common.js +12 -0
  95. package/dist/schemas/completion-stream.d.ts +26 -22
  96. package/dist/schemas/completion-stream.js +9 -23
  97. package/dist/schemas/download-asset.d.ts +77 -2
  98. package/dist/schemas/download-asset.js +15 -4
  99. package/dist/schemas/get-model-info.d.ts +100 -0
  100. package/dist/schemas/get-model-info.js +40 -0
  101. package/dist/schemas/index.d.ts +8 -0
  102. package/dist/schemas/index.js +8 -0
  103. package/dist/schemas/llamacpp-config.d.ts +2 -1
  104. package/dist/schemas/llamacpp-config.js +3 -4
  105. package/dist/schemas/load-model.d.ts +2316 -266
  106. package/dist/schemas/load-model.js +157 -10
  107. package/dist/schemas/model-src-utils.d.ts +98 -0
  108. package/dist/schemas/model-src-utils.js +31 -0
  109. package/dist/schemas/sdk-errors-client.d.ts +25 -0
  110. package/dist/schemas/sdk-errors-client.js +111 -0
  111. package/dist/schemas/sdk-errors-server.d.ts +55 -0
  112. package/dist/schemas/sdk-errors-server.js +271 -0
  113. package/dist/schemas/set-config.d.ts +21 -0
  114. package/dist/schemas/set-config.js +14 -0
  115. package/dist/schemas/stop-provide.d.ts +17 -0
  116. package/dist/schemas/stop-provide.js +15 -0
  117. package/dist/schemas/text-to-speech.d.ts +34 -0
  118. package/dist/schemas/text-to-speech.js +25 -0
  119. package/dist/schemas/tools.d.ts +62 -0
  120. package/dist/schemas/tools.js +43 -0
  121. package/dist/schemas/transcription.d.ts +25 -2
  122. package/dist/schemas/transcription.js +12 -1
  123. package/dist/schemas/translation-config.d.ts +33 -5
  124. package/dist/schemas/translation-config.js +18 -1
  125. package/dist/schemas/unload-model.d.ts +2 -0
  126. package/dist/schemas/unload-model.js +2 -0
  127. package/dist/schemas/whispercpp-config.d.ts +55 -18
  128. package/dist/schemas/whispercpp-config.js +63 -15
  129. package/dist/server/bare/addons/cancel.js +2 -1
  130. package/dist/server/bare/addons/llamacpp/create-model.d.ts +9 -2
  131. package/dist/server/bare/addons/llamacpp/create-model.js +23 -23
  132. package/dist/server/bare/addons/llamacpp/handlers/completion-stream.d.ts +10 -2
  133. package/dist/server/bare/addons/llamacpp/handlers/completion-stream.js +62 -43
  134. package/dist/server/bare/addons/llamacpp/handlers/embed.js +3 -2
  135. package/dist/server/bare/addons/llamacpp/kv-cache-utils.d.ts +1 -1
  136. package/dist/server/bare/addons/llamacpp/kv-cache-utils.js +6 -2
  137. package/dist/server/bare/addons/load-model.js +59 -28
  138. package/dist/server/bare/addons/translation/create-model.d.ts +5 -1
  139. package/dist/server/bare/addons/translation/create-model.js +17 -25
  140. package/dist/server/bare/addons/translation/handlers/translate.js +10 -1
  141. package/dist/server/bare/addons/tts/create-model.d.ts +10 -0
  142. package/dist/server/bare/addons/tts/create-model.js +25 -0
  143. package/dist/server/bare/addons/tts/handlers/text-to-speech.d.ts +3 -0
  144. package/dist/server/bare/addons/tts/handlers/text-to-speech.js +87 -0
  145. package/dist/server/bare/addons/tts/index.d.ts +3 -0
  146. package/dist/server/bare/addons/tts/index.js +2 -0
  147. package/dist/server/bare/addons/unload-model.js +21 -3
  148. package/dist/server/bare/addons/whispercpp/create-model.d.ts +5 -1
  149. package/dist/server/bare/addons/whispercpp/create-model.js +13 -32
  150. package/dist/server/bare/addons/whispercpp/handlers/transcribe-stream.js +41 -20
  151. package/dist/server/bare/delegate-rpc-client.js +3 -2
  152. package/dist/server/bare/hyperswarm.d.ts +3 -0
  153. package/dist/server/bare/hyperswarm.js +22 -1
  154. package/dist/server/bare/rag-hyperdb/rag-manager.js +16 -13
  155. package/dist/server/bare/registry/config-registry.d.ts +5 -0
  156. package/dist/server/bare/registry/config-registry.js +39 -0
  157. package/dist/server/bare/registry/logging-stream-registry.d.ts +1 -0
  158. package/dist/server/bare/registry/logging-stream-registry.js +7 -0
  159. package/dist/server/bare/registry/model-registry.d.ts +13 -0
  160. package/dist/server/bare/registry/model-registry.js +24 -7
  161. package/dist/server/rpc/handle-request.js +48 -3
  162. package/dist/server/rpc/handlers/completion-stream-delegated.js +2 -1
  163. package/dist/server/rpc/handlers/completion-stream.js +11 -4
  164. package/dist/server/rpc/handlers/download-asset.js +2 -3
  165. package/dist/server/rpc/handlers/get-model-info.d.ts +3 -0
  166. package/dist/server/rpc/handlers/get-model-info.js +148 -0
  167. package/dist/server/rpc/handlers/index.d.ts +6 -0
  168. package/dist/server/rpc/handlers/index.js +8 -0
  169. package/dist/server/rpc/handlers/load-model/download-manager.d.ts +1 -0
  170. package/dist/server/rpc/handlers/load-model/download-manager.js +12 -31
  171. package/dist/server/rpc/handlers/load-model/http.js +51 -10
  172. package/dist/server/rpc/handlers/load-model/hyperdrive.js +336 -156
  173. package/dist/server/rpc/handlers/load-model/index.js +1 -1
  174. package/dist/server/rpc/handlers/load-model/resolve.d.ts +1 -1
  175. package/dist/server/rpc/handlers/load-model/resolve.js +17 -60
  176. package/dist/server/rpc/handlers/load-model-delegated.js +7 -4
  177. package/dist/server/rpc/handlers/load-model.js +19 -1
  178. package/dist/server/rpc/handlers/provideHandler/handler.js +2 -1
  179. package/dist/server/rpc/handlers/rag.js +0 -3
  180. package/dist/server/rpc/handlers/set-config.d.ts +3 -0
  181. package/dist/server/rpc/handlers/set-config.js +18 -0
  182. package/dist/server/rpc/handlers/stopProvideHandler.d.ts +3 -0
  183. package/dist/server/rpc/handlers/stopProvideHandler.js +22 -0
  184. package/dist/server/rpc/handlers/text-to-speech.d.ts +3 -0
  185. package/dist/server/rpc/handlers/text-to-speech.js +7 -0
  186. package/dist/server/rpc/handlers/transcribe-stream.js +6 -2
  187. package/dist/server/rpc/handlers/unload-model.js +7 -0
  188. package/dist/server/utils/cache.d.ts +13 -8
  189. package/dist/server/utils/cache.js +69 -14
  190. package/dist/server/utils/checksum.d.ts +2 -0
  191. package/dist/server/utils/checksum.js +24 -0
  192. package/dist/server/utils/index.d.ts +2 -0
  193. package/dist/server/utils/index.js +2 -0
  194. package/dist/server/utils/shard-utils.d.ts +22 -0
  195. package/dist/server/utils/shard-utils.js +37 -0
  196. package/dist/server/utils/tool-integration.d.ts +13 -0
  197. package/dist/server/utils/tool-integration.js +43 -0
  198. package/dist/server/utils/tool-parser.d.ts +7 -0
  199. package/dist/server/utils/tool-parser.js +244 -0
  200. package/dist/server/worker.js +28 -10
  201. package/dist/utils/errors-base.d.ts +3 -0
  202. package/dist/utils/errors-base.js +13 -0
  203. package/dist/utils/errors-client.d.ts +107 -0
  204. package/dist/utils/errors-client.js +186 -0
  205. package/dist/utils/errors-server.d.ts +146 -0
  206. package/dist/utils/errors-server.js +253 -0
  207. package/dist/utils/tool-helpers.d.ts +17 -0
  208. package/dist/utils/tool-helpers.js +99 -0
  209. package/package.json +15 -11
  210. package/dist/examples/llamacpp-tools-routing.d.ts +0 -2
  211. package/dist/examples/llamacpp-tools-routing.js +0 -364
  212. package/dist/examples/llamacpp-tools.d.ts +0 -2
  213. package/dist/examples/llamacpp-tools.js +0 -81
  214. package/dist/server/http-server.d.ts +0 -2
  215. package/dist/server/http-server.js +0 -189
@@ -1,46 +1,11 @@
1
- import { getModelBySrc, models } from "../../../../models/hyperdrive/models.js";
1
+ import { models } from "../../../../models/hyperdrive/models.js";
2
2
  import { hyperdriveUrlSchema } from "../../../../schemas/index.js";
3
3
  import { getModelsCacheDir } from "../../../utils/index.js";
4
4
  import { promises as fsPromises } from "bare-fs";
5
5
  import path from "bare-path";
6
6
  import { downloadModelFromHttp } from "./http.js";
7
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
- }
8
+ import { ModelLoadFailedError, ModelNotFoundError, SeedingNotSupportedError, } from "../../../../utils/errors-server.js";
44
9
  /**
45
10
  * Resolves a local file path or cached file
46
11
  */
@@ -48,7 +13,7 @@ async function resolveLocalOrCachedFile(modelIdOrPath) {
48
13
  // Check if it's a hex string (arbitrary hyperdrive key)
49
14
  const isHexString = /^[0-9a-fA-F]{64}$/.test(modelIdOrPath);
50
15
  if (isHexString) {
51
- throw new Error(`Direct hyperdrive keys not supported. Use hyperdriveKey parameter instead. Example: loadModel("model.gguf", "${modelIdOrPath}")`);
16
+ throw new ModelLoadFailedError(`Direct hyperdrive keys not supported. Use hyperdriveKey parameter instead. Example: loadModel("model.gguf", "${modelIdOrPath}")`);
52
17
  }
53
18
  // Check if it's a cached file or local file
54
19
  const cacheDir = getModelsCacheDir();
@@ -68,26 +33,26 @@ async function resolveLocalOrCachedFile(modelIdOrPath) {
68
33
  catch {
69
34
  // Invalid model ID - provide helpful error
70
35
  const availableModels = models.map((m) => m.modelId);
71
- throw new Error(`Invalid model ID: "${modelIdOrPath}". Available models: ${availableModels.join(", ")}`);
36
+ throw new ModelNotFoundError(`${modelIdOrPath}". Available models: ${availableModels.join(", ")}`);
72
37
  }
73
38
  }
74
39
  }
40
+ import { modelInputToSrcSchema } from "../../../../schemas/index.js";
75
41
  export async function resolveModelPath(modelSrc, progressCallback, seed) {
42
+ // Extract src and validate using Zod schema transform
43
+ const srcString = modelInputToSrcSchema.parse(modelSrc);
76
44
  // Parse hyperdrive URLs if present
77
45
  let hyperdriveKey;
78
- let actualModelSrc = modelSrc;
79
- if (modelSrc.startsWith("pear://")) {
80
- const { key, path } = hyperdriveUrlSchema.parse(modelSrc);
46
+ let actualModelSrc = srcString;
47
+ if (srcString.startsWith("pear://")) {
48
+ const { key, path } = hyperdriveUrlSchema.parse(srcString);
81
49
  hyperdriveKey = key;
82
50
  actualModelSrc = path;
83
51
  }
84
52
  let actualPath;
85
53
  // Validate seeding is only used with hyperdrive models
86
54
  if (seed && !hyperdriveKey) {
87
- const model = getModelBySrc(actualModelSrc);
88
- if (!model) {
89
- throw new Error("Seeding is only supported for hyperdrive models");
90
- }
55
+ throw new SeedingNotSupportedError();
91
56
  }
92
57
  // Check if it's an HTTP/HTTPS URL
93
58
  if (actualModelSrc.startsWith("http://") ||
@@ -101,21 +66,13 @@ export async function resolveModelPath(modelSrc, progressCallback, seed) {
101
66
  console.log(`Loading from hyperdrive: ${hyperdriveKey}`);
102
67
  actualPath = await downloadModelFromHyperdrive(hyperdriveKey, actualModelSrc, seed, progressCallback);
103
68
  }
69
+ else if (actualModelSrc.includes("/") || actualModelSrc.includes("\\")) {
70
+ // Handle file paths (absolute or relative with slashes)
71
+ actualPath = actualModelSrc;
72
+ }
104
73
  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
- }
74
+ // Handle local files and cached files
75
+ actualPath = await resolveLocalOrCachedFile(actualModelSrc);
119
76
  }
120
77
  return actualPath;
121
78
  }
@@ -1,10 +1,12 @@
1
+ import { modelInputToSrcSchema } from "../../../schemas/index.js";
1
2
  import { registerModel } from "../../bare/registry/model-registry.js";
2
3
  import { getRPC } from "../../bare/delegate-rpc-client.js";
3
4
  import { send, stream } from "../../../client/rpc/rpc-client.js";
4
5
  import { handleLoadModel } from "./load-model/index.js";
6
+ import { ModelLoadFailedError, DelegateNoFinalResponseError, } from "../../../utils/errors-server.js";
5
7
  export async function handleLoadModelDelegated(request, progressCallback) {
6
8
  if (!request.delegate) {
7
- throw new Error("Delegate information is required for delegated load model");
9
+ throw new ModelLoadFailedError("Delegate information is required for delegated load model");
8
10
  }
9
11
  const { delegate } = request;
10
12
  const { topic, providerPublicKey, timeout, fallbackToLocal } = delegate;
@@ -33,7 +35,7 @@ export async function handleLoadModelDelegated(request, progressCallback) {
33
35
  }
34
36
  }
35
37
  if (!finalResponse) {
36
- throw new Error("No final response received from provider");
38
+ throw new DelegateNoFinalResponseError();
37
39
  }
38
40
  }
39
41
  else {
@@ -49,8 +51,9 @@ export async function handleLoadModelDelegated(request, progressCallback) {
49
51
  error: `Provider failed to load model: ${finalResponse?.error || "Unknown error"}`,
50
52
  };
51
53
  }
52
- // Register the delegated model with provider info
53
- const modelId = finalResponse.modelId || request.modelSrc || `delegated-${Date.now()}`;
54
+ const modelId = finalResponse.modelId ||
55
+ modelInputToSrcSchema.parse(request.modelSrc) ||
56
+ `delegated-${Date.now()}`;
54
57
  const delegateOptions = {
55
58
  topic,
56
59
  providerPublicKey,
@@ -1,8 +1,12 @@
1
1
  import { loadModel } from "../../bare/addons/index.js";
2
2
  import { resolveModelPath } from "./load-model/resolve.js";
3
3
  import { generateShortHash } from "../../utils/index.js";
4
+ import { TTSConfigModelRequiredError, ESpeakDataPathRequiredError, } from "../../../utils/errors-server.js";
4
5
  export async function handleLoadModel(request, progressCallback) {
5
- const { modelSrc, seed, projectionModelSrc, vadModelSrc } = request;
6
+ const { modelSrc, modelName, seed, projectionModelSrc, vadModelSrc, configSrc, } = request;
7
+ const eSpeakDataPath = request.modelType === "tts"
8
+ ? request.eSpeakDataPath
9
+ : undefined;
6
10
  try {
7
11
  const modelPath = await resolveModelPath(modelSrc, progressCallback, seed);
8
12
  let projectionModelPath;
@@ -13,6 +17,17 @@ export async function handleLoadModel(request, progressCallback) {
13
17
  if (vadModelSrc) {
14
18
  vadModelPath = await resolveModelPath(vadModelSrc, progressCallback, seed);
15
19
  }
20
+ let ttsConfigModelPath;
21
+ if (configSrc) {
22
+ ttsConfigModelPath = await resolveModelPath(configSrc, progressCallback, seed);
23
+ }
24
+ // For TTS models, ttsConfigModelPath and eSpeakDataPath are required
25
+ if (request.modelType === "tts" && !ttsConfigModelPath) {
26
+ throw new TTSConfigModelRequiredError();
27
+ }
28
+ if (request.modelType === "tts" && !eSpeakDataPath) {
29
+ throw new ESpeakDataPathRequiredError();
30
+ }
16
31
  // Generate hash-based modelId
17
32
  const configStr = JSON.stringify(request.modelConfig, Object.keys(request.modelConfig).sort());
18
33
  const modelHashInput = `${request.modelType}:${modelSrc}:${configStr}`;
@@ -23,6 +38,9 @@ export async function handleLoadModel(request, progressCallback) {
23
38
  options: request,
24
39
  projectionModelPath,
25
40
  vadModelPath,
41
+ ttsConfigModelPath,
42
+ eSpeakDataPath,
43
+ modelName,
26
44
  });
27
45
  return {
28
46
  type: "loadModel",
@@ -1,4 +1,4 @@
1
- import { getSwarm } from "../../../bare/hyperswarm.js";
1
+ import { getSwarm, registerProviderTopic } from "../../../bare/hyperswarm.js";
2
2
  import { setupConnectionHandlers } from "./connection.js";
3
3
  export async function provideHandler(request) {
4
4
  const swarm = getSwarm({
@@ -27,6 +27,7 @@ export async function provideHandler(request) {
27
27
  console.log(`🎯 Ready to accept connections on topic: ${topic.toString("hex").substring(0, 16)}...`);
28
28
  // Handle incoming connections
29
29
  setupConnectionHandlers(swarm);
30
+ registerProviderTopic(topic.toString("hex"));
30
31
  console.log("🏁 About to return success response...");
31
32
  const response = {
32
33
  type: "provide",
@@ -29,9 +29,6 @@ export async function handleRag(request) {
29
29
  success,
30
30
  };
31
31
  }
32
- default: {
33
- throw new Error(`Unknown RAG operation`);
34
- }
35
32
  }
36
33
  }
37
34
  catch (error) {
@@ -0,0 +1,3 @@
1
+ import type { SetConfigRequest, SetConfigResponse } from "../../../schemas/index";
2
+ export declare const handleSetConfig: (request: SetConfigRequest) => SetConfigResponse;
3
+ //# sourceMappingURL=set-config.d.ts.map
@@ -0,0 +1,18 @@
1
+ import { setSDKConfig } from "../../bare/registry/config-registry.js";
2
+ export const handleSetConfig = (request) => {
3
+ try {
4
+ setSDKConfig(request.config);
5
+ return {
6
+ type: "setConfig",
7
+ success: true,
8
+ };
9
+ }
10
+ catch (error) {
11
+ console.error("Error setting config:", error);
12
+ return {
13
+ type: "setConfig",
14
+ success: false,
15
+ error: error instanceof Error ? error.message : "Unknown error",
16
+ };
17
+ }
18
+ };
@@ -0,0 +1,3 @@
1
+ import type { StopProvideRequest, StopProvideResponse } from "../../../schemas/stop-provide";
2
+ export declare function stopProvideHandler(request: StopProvideRequest): StopProvideResponse;
3
+ //# sourceMappingURL=stopProvideHandler.d.ts.map
@@ -0,0 +1,22 @@
1
+ import { getSwarm, unregisterProviderTopic } from "../../bare/hyperswarm.js";
2
+ export function stopProvideHandler(request) {
3
+ const swarm = getSwarm();
4
+ try {
5
+ const topic = Buffer.from(request.topic, "hex");
6
+ const topicHex = request.topic;
7
+ swarm.leave(topic);
8
+ unregisterProviderTopic(topicHex);
9
+ return {
10
+ type: "stopProvide",
11
+ success: true,
12
+ };
13
+ }
14
+ catch (error) {
15
+ console.error("❌ Error in stop provide handler:", error);
16
+ return {
17
+ type: "stopProvide",
18
+ success: false,
19
+ error: error instanceof Error ? error.message : "Unknown error",
20
+ };
21
+ }
22
+ }
@@ -0,0 +1,3 @@
1
+ import type { TtsRequest, TtsResponse } from "../../../schemas/index";
2
+ export declare function handleTextToSpeech(request: TtsRequest): AsyncGenerator<TtsResponse>;
3
+ //# sourceMappingURL=text-to-speech.d.ts.map
@@ -0,0 +1,7 @@
1
+ import { textToSpeech } from "../../bare/addons/tts/index.js";
2
+ export async function* handleTextToSpeech(request) {
3
+ const stream = textToSpeech(request);
4
+ for await (const response of stream) {
5
+ yield response;
6
+ }
7
+ }
@@ -1,9 +1,13 @@
1
1
  import { transcribeStream } from "../../bare/addons/whispercpp/index.js";
2
2
  export async function* handleTranscribeStream(request) {
3
- const { modelId, audioChunk } = request;
3
+ const { modelId, audioChunk, prompt } = request;
4
4
  try {
5
5
  // Stream transcription results in real-time
6
- for await (const textChunk of transcribeStream({ audioChunk, modelId })) {
6
+ for await (const textChunk of transcribeStream({
7
+ audioChunk,
8
+ modelId,
9
+ prompt,
10
+ })) {
7
11
  yield {
8
12
  type: "transcribeStream",
9
13
  text: textChunk,
@@ -1,12 +1,19 @@
1
1
  import { unloadModel } from "../../bare/addons/index.js";
2
+ import { getRegistryStats } from "../../bare/registry/model-registry.js";
3
+ import { hasActiveProviders } from "../../bare/hyperswarm.js";
2
4
  export async function handleUnloadModel(request) {
3
5
  const { modelId, clearStorage } = request;
4
6
  try {
5
7
  console.log("Unloading model", modelId);
6
8
  await unloadModel({ modelId, clearStorage });
9
+ const stats = getRegistryStats();
10
+ const modelsActive = stats.totalModels > 0;
11
+ const providersActive = hasActiveProviders();
7
12
  return {
8
13
  type: "unloadModel",
9
14
  success: true,
15
+ hasActiveModels: modelsActive,
16
+ hasActiveProviders: providersActive,
10
17
  };
11
18
  }
12
19
  catch (error) {
@@ -1,15 +1,20 @@
1
+ import type { ShardMetadata } from "./shard-utils";
2
+ export declare const getCacheDir: (subDir: string) => string;
3
+ export declare const getModelsCacheDir: () => string;
4
+ export declare const getKVCacheDir: () => string;
1
5
  /**
2
- * Creates and returns cache directory path for the specified subdirectory
3
- * @param subDir - Subdirectory name (e.g., "models", "kv-cache")
4
- * @returns Full path to the cache directory
6
+ * Get cache directory for sharded model
7
+ * Returns: cache/sharded/<hyperdriveKey>/
5
8
  */
6
- export declare function getCacheDir(subDir: string): string;
9
+ export declare function getShardedModelCacheDir(hyperdriveKey: string): string;
7
10
  /**
8
- * Legacy function for backward compatibility - gets models cache directory
11
+ * Get full path to specific shard file
12
+ * Returns: cache/sharded/<hyperdriveKey>/<shardFilename>
9
13
  */
10
- export declare function getModelsCacheDir(): string;
14
+ export declare function getShardPath(hyperdriveKey: string, shardFilename: string): string;
11
15
  /**
12
- * Gets KV cache directory
16
+ * Check if all shards exist and are valid (size + checksum check)
17
+ * Returns array of missing/invalid shard indices (0-based)
13
18
  */
14
- export declare function getKVCacheDir(): string;
19
+ export declare function checkShardCompleteness(hyperdriveKey: string, shardFilenames: readonly string[], shardMetadata: readonly ShardMetadata[]): Promise<number[]>;
15
20
  //# sourceMappingURL=cache.d.ts.map
@@ -1,15 +1,11 @@
1
- import fs from "bare-fs";
1
+ import fs, { promises as fsPromises } from "bare-fs";
2
2
  import path from "bare-path";
3
3
  import { getEnv } from "../worker.js";
4
- /**
5
- * Creates and returns cache directory path for the specified subdirectory
6
- * @param subDir - Subdirectory name (e.g., "models", "kv-cache")
7
- * @returns Full path to the cache directory
8
- */
9
- export function getCacheDir(subDir) {
4
+ import { getConfiguredCacheDir } from "../bare/registry/config-registry.js";
5
+ import { calculateFileChecksum } from "./checksum.js";
6
+ export const getCacheDir = (subDir) => {
10
7
  const homeDir = getEnv().HOME_DIR;
11
8
  const cacheDir = path.join(homeDir, ".qvac", subDir);
12
- // Ensure cache directory exists
13
9
  try {
14
10
  fs.mkdirSync(cacheDir, { recursive: true });
15
11
  }
@@ -17,16 +13,75 @@ export function getCacheDir(subDir) {
17
13
  console.error(`Error creating cache directory (${subDir}):`, error instanceof Error ? error.message : String(error));
18
14
  }
19
15
  return cacheDir;
16
+ };
17
+ export const getModelsCacheDir = () => {
18
+ const configuredDir = getConfiguredCacheDir();
19
+ try {
20
+ fs.mkdirSync(configuredDir, { recursive: true });
21
+ }
22
+ catch (error) {
23
+ console.error(`Error creating models cache directory:`, error instanceof Error ? error.message : String(error));
24
+ }
25
+ return configuredDir;
26
+ };
27
+ export const getKVCacheDir = () => {
28
+ return getCacheDir("kv-cache");
29
+ };
30
+ /**
31
+ * Get cache directory for sharded model
32
+ * Returns: cache/sharded/<hyperdriveKey>/
33
+ */
34
+ export function getShardedModelCacheDir(hyperdriveKey) {
35
+ const baseCache = getModelsCacheDir();
36
+ const shardDir = path.join(baseCache, "sharded", hyperdriveKey);
37
+ try {
38
+ fs.mkdirSync(shardDir, { recursive: true });
39
+ }
40
+ catch (error) {
41
+ console.error(`Error creating sharded model cache directory:`, error instanceof Error ? error.message : String(error));
42
+ }
43
+ return shardDir;
20
44
  }
21
45
  /**
22
- * Legacy function for backward compatibility - gets models cache directory
46
+ * Get full path to specific shard file
47
+ * Returns: cache/sharded/<hyperdriveKey>/<shardFilename>
23
48
  */
24
- export function getModelsCacheDir() {
25
- return getCacheDir("models");
49
+ export function getShardPath(hyperdriveKey, shardFilename) {
50
+ const shardDir = getShardedModelCacheDir(hyperdriveKey);
51
+ return path.join(shardDir, shardFilename);
26
52
  }
27
53
  /**
28
- * Gets KV cache directory
54
+ * Check if all shards exist and are valid (size + checksum check)
55
+ * Returns array of missing/invalid shard indices (0-based)
29
56
  */
30
- export function getKVCacheDir() {
31
- return getCacheDir("kv-cache");
57
+ export async function checkShardCompleteness(hyperdriveKey, shardFilenames, shardMetadata) {
58
+ const invalidIndices = [];
59
+ for (let i = 0; i < shardFilenames.length; i++) {
60
+ const shardPath = getShardPath(hyperdriveKey, shardFilenames[i]);
61
+ const fileMeta = shardMetadata[i];
62
+ if (!fileMeta) {
63
+ invalidIndices.push(i);
64
+ continue;
65
+ }
66
+ try {
67
+ const stats = await fsPromises.stat(shardPath);
68
+ if (stats.size !== fileMeta.expectedSize) {
69
+ console.warn(`File ${i + 1} size mismatch: expected ${fileMeta.expectedSize}, got ${stats.size}`);
70
+ invalidIndices.push(i);
71
+ continue;
72
+ }
73
+ if (fileMeta.sha256Checksum) {
74
+ const actualChecksum = await calculateFileChecksum(shardPath);
75
+ if (actualChecksum !== fileMeta.sha256Checksum) {
76
+ console.warn(`File ${i + 1} checksum mismatch for ${fileMeta.filename}. Expected: ${fileMeta.sha256Checksum}. Actual: ${actualChecksum}. Will re-download.`);
77
+ invalidIndices.push(i);
78
+ }
79
+ }
80
+ }
81
+ catch {
82
+ // File doesn't exist
83
+ invalidIndices.push(i);
84
+ }
85
+ }
86
+ return invalidIndices;
32
87
  }
@@ -0,0 +1,2 @@
1
+ export declare function calculateFileChecksum(filePath: string): Promise<string>;
2
+ //# sourceMappingURL=checksum.d.ts.map
@@ -0,0 +1,24 @@
1
+ import fs from "bare-fs";
2
+ import crypto from "bare-crypto";
3
+ export async function calculateFileChecksum(filePath) {
4
+ return new Promise((resolve, reject) => {
5
+ try {
6
+ const hash = crypto.createHash("sha256");
7
+ const stream = fs.createReadStream(filePath);
8
+ stream.on("data", (chunk) => {
9
+ hash.update(chunk);
10
+ });
11
+ stream.on("end", () => {
12
+ resolve(hash.digest("hex"));
13
+ });
14
+ stream.on("error", (error) => {
15
+ reject(new Error(`Checksum calculation error: ${error.message}`));
16
+ });
17
+ }
18
+ catch (error) {
19
+ reject(error instanceof Error
20
+ ? error
21
+ : new Error(`Checksum calculation error: ${String(error)}`));
22
+ }
23
+ });
24
+ }
@@ -1,5 +1,7 @@
1
1
  export * from "./audio/decoder";
2
2
  export * from "./cache";
3
+ export * from "./checksum";
3
4
  export * from "./hash";
4
5
  export * from "./model-path";
6
+ export * from "./shard-utils";
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -1,4 +1,6 @@
1
1
  export * from "./audio/decoder.js";
2
2
  export * from "./cache.js";
3
+ export * from "./checksum.js";
3
4
  export * from "./hash.js";
4
5
  export * from "./model-path.js";
6
+ export * from "./shard-utils.js";
@@ -0,0 +1,22 @@
1
+ export interface ShardInfo {
2
+ isSharded: boolean;
3
+ currentShard?: number;
4
+ totalShards?: number;
5
+ baseFilename?: string;
6
+ extension?: string;
7
+ }
8
+ export interface ShardMetadata {
9
+ filename: string;
10
+ expectedSize: number;
11
+ sha256Checksum: string;
12
+ }
13
+ /**
14
+ * Detect if model filename follows shard pattern (00001-of-0000x)
15
+ */
16
+ export declare function detectShardedModel(filename: string): ShardInfo;
17
+ /**
18
+ * Generate list of all required files for a sharded model
19
+ * Includes numbered shards AND the .tensors.txt companion file
20
+ */
21
+ export declare function generateShardFilenames(firstShardName: string): string[];
22
+ //# sourceMappingURL=shard-utils.d.ts.map
@@ -0,0 +1,37 @@
1
+ import { ModelLoadFailedError } from "../../utils/errors-server.js";
2
+ /**
3
+ * Detect if model filename follows shard pattern (00001-of-0000x)
4
+ */
5
+ export function detectShardedModel(filename) {
6
+ const shardPattern = /^(.+)-(\d{5})-of-(\d{5})(\.\w+)$/;
7
+ const match = filename.match(shardPattern);
8
+ if (match && match[1] && match[2] && match[3] && match[4]) {
9
+ return {
10
+ isSharded: true,
11
+ baseFilename: match[1],
12
+ currentShard: parseInt(match[2], 10),
13
+ totalShards: parseInt(match[3], 10),
14
+ extension: match[4],
15
+ };
16
+ }
17
+ return { isSharded: false };
18
+ }
19
+ /**
20
+ * Generate list of all required files for a sharded model
21
+ * Includes numbered shards AND the .tensors.txt companion file
22
+ */
23
+ export function generateShardFilenames(firstShardName) {
24
+ const shardInfo = detectShardedModel(firstShardName);
25
+ if (!shardInfo.isSharded || !shardInfo.totalShards) {
26
+ throw new ModelLoadFailedError(`Not a sharded model filename: ${firstShardName}`);
27
+ }
28
+ const filenames = [];
29
+ const { baseFilename, totalShards, extension } = shardInfo;
30
+ for (let i = 1; i <= totalShards; i++) {
31
+ const shardNumber = i.toString().padStart(5, "0");
32
+ const totalShardsStr = totalShards.toString().padStart(5, "0");
33
+ filenames.push(`${baseFilename}-${shardNumber}-of-${totalShardsStr}${extension}`);
34
+ }
35
+ filenames.push(`${baseFilename}.tensors.txt`);
36
+ return filenames;
37
+ }
@@ -0,0 +1,13 @@
1
+ import type { Tool, ToolCallEvent } from "../../schemas/index";
2
+ interface HistoryMessage {
3
+ role: string;
4
+ content: string;
5
+ attachments?: {
6
+ path: string;
7
+ }[] | undefined;
8
+ }
9
+ export declare function insertToolsIntoHistory(history: HistoryMessage[], tools: Tool[]): Array<HistoryMessage | Tool>;
10
+ export declare function setupToolGrammar(modelConfig: Record<string, unknown>, tools: Tool[]): void;
11
+ export declare function checkForToolEvents(accumulatedText: string, currentToken: string, tools: Tool[], emittedToolCallPositions: Set<number>): ToolCallEvent[];
12
+ export {};
13
+ //# sourceMappingURL=tool-integration.d.ts.map
@@ -0,0 +1,43 @@
1
+ import { parseToolCalls, convertToolsToGrammar, } from "./tool-parser.js";
2
+ export function insertToolsIntoHistory(history, tools) {
3
+ const systemMsgIndex = history.findIndex((msg) => msg.role === "system");
4
+ if (systemMsgIndex >= 0) {
5
+ return [
6
+ ...history.slice(0, systemMsgIndex + 1),
7
+ ...tools,
8
+ ...history.slice(systemMsgIndex + 1),
9
+ ];
10
+ }
11
+ return [...tools, ...history];
12
+ }
13
+ export function setupToolGrammar(modelConfig, tools) {
14
+ const grammar = convertToolsToGrammar(tools);
15
+ modelConfig["grammar"] = grammar;
16
+ }
17
+ export function checkForToolEvents(accumulatedText, currentToken, tools, emittedToolCallPositions) {
18
+ const events = [];
19
+ if (currentToken.includes("</tool_call>") || currentToken.includes("}")) {
20
+ const { toolCalls, errors } = parseToolCalls(accumulatedText, tools);
21
+ for (const call of toolCalls) {
22
+ const callPosition = accumulatedText.indexOf(call.raw || "");
23
+ if (callPosition >= 0 && !emittedToolCallPositions.has(callPosition)) {
24
+ emittedToolCallPositions.add(callPosition);
25
+ events.push({
26
+ type: "toolCall",
27
+ call,
28
+ });
29
+ }
30
+ }
31
+ for (const error of errors) {
32
+ const errorPosition = accumulatedText.indexOf(error.raw || "");
33
+ if (errorPosition >= 0 && !emittedToolCallPositions.has(errorPosition)) {
34
+ emittedToolCallPositions.add(errorPosition);
35
+ events.push({
36
+ type: "toolCallError",
37
+ error,
38
+ });
39
+ }
40
+ }
41
+ }
42
+ return events;
43
+ }
@@ -0,0 +1,7 @@
1
+ import type { Tool, ToolCall, ToolCallError } from "../../schemas/index";
2
+ export declare function parseToolCalls(text: string, tools: Tool[]): {
3
+ toolCalls: ToolCall[];
4
+ errors: ToolCallError[];
5
+ };
6
+ export declare function convertToolsToGrammar(tools: Tool[]): string;
7
+ //# sourceMappingURL=tool-parser.d.ts.map