@qvac/sdk 0.3.0 → 0.4.1

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 (210) hide show
  1. package/README.md +22 -0
  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 +3 -0
  14. package/dist/client/api/index.js +3 -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 +1 -1
  28. package/dist/client/api/stop-provider.js +4 -3
  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 +69 -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 +20 -1
  52. package/dist/constants/audio.d.ts +1 -2
  53. package/dist/constants/audio.js +1 -17
  54. package/dist/examples/cache-management.d.ts +2 -0
  55. package/dist/examples/cache-management.js +97 -0
  56. package/dist/examples/delegated-inference/consumer.js +2 -2
  57. package/dist/examples/download-with-blind-relays.d.ts +2 -0
  58. package/dist/examples/download-with-blind-relays.js +48 -0
  59. package/dist/examples/download-with-cancel.js +3 -4
  60. package/dist/examples/embed-hyperdrive.js +0 -1
  61. package/dist/examples/kv-cache-cleanup.js +0 -1
  62. package/dist/examples/kv-cache-custom-key.js +0 -1
  63. package/dist/examples/kv-cache-example.js +0 -1
  64. package/dist/examples/llamacpp-file-logging.js +0 -1
  65. package/dist/examples/llamacpp-filesystem.js +2 -2
  66. package/dist/examples/llamacpp-http.js +0 -1
  67. package/dist/examples/llamacpp-hyperdrive.js +0 -1
  68. package/dist/examples/llamacpp-multimodal.js +0 -1
  69. package/dist/examples/llamacpp-native-tools.js +118 -36
  70. package/dist/examples/llamacpp-sharded.d.ts +2 -0
  71. package/dist/examples/llamacpp-sharded.js +44 -0
  72. package/dist/examples/multi-model-demo.js +0 -1
  73. package/dist/examples/parallel-download.js +2 -2
  74. package/dist/examples/rag/rag-chromadb.js +0 -1
  75. package/dist/examples/rag/rag-hyperdb-workspaces.js +0 -1
  76. package/dist/examples/rag/rag-hyperdb.js +0 -1
  77. package/dist/examples/rag/rag-lancedb.js +0 -1
  78. package/dist/examples/rag/rag-sqlite.js +0 -1
  79. package/dist/examples/text-to-speech.d.ts +3 -0
  80. package/dist/examples/text-to-speech.js +137 -0
  81. package/dist/examples/translation/translation-indic.js +3 -1
  82. package/dist/examples/translation/translation-llm-context.js +0 -1
  83. package/dist/examples/translation/translation-llm.js +2 -2
  84. package/dist/examples/translation/translation-opus.js +3 -1
  85. package/dist/examples/translation/translation-stream.js +0 -1
  86. package/dist/examples/whispercpp-filesystem.js +32 -5
  87. package/dist/examples/whispercpp-microphone-record.js +9 -9
  88. package/dist/examples/whispercpp-prompt.d.ts +2 -0
  89. package/dist/examples/whispercpp-prompt.js +68 -0
  90. package/dist/expo/plugins/withMobileBundle.js +9 -3
  91. package/dist/index.d.ts +4 -2
  92. package/dist/index.js +4 -2
  93. package/dist/models/hyperdrive/models.d.ts +1916 -100
  94. package/dist/models/hyperdrive/models.js +2042 -102
  95. package/dist/schemas/common.d.ts +413 -58
  96. package/dist/schemas/common.js +9 -0
  97. package/dist/schemas/completion-stream.d.ts +26 -22
  98. package/dist/schemas/completion-stream.js +9 -23
  99. package/dist/schemas/download-asset.d.ts +77 -2
  100. package/dist/schemas/download-asset.js +15 -4
  101. package/dist/schemas/get-model-info.d.ts +100 -0
  102. package/dist/schemas/get-model-info.js +40 -0
  103. package/dist/schemas/index.d.ts +7 -0
  104. package/dist/schemas/index.js +7 -0
  105. package/dist/schemas/llamacpp-config.d.ts +2 -1
  106. package/dist/schemas/llamacpp-config.js +3 -4
  107. package/dist/schemas/load-model.d.ts +2316 -266
  108. package/dist/schemas/load-model.js +157 -10
  109. package/dist/schemas/model-src-utils.d.ts +98 -0
  110. package/dist/schemas/model-src-utils.js +31 -0
  111. package/dist/schemas/sdk-errors-client.d.ts +25 -0
  112. package/dist/schemas/sdk-errors-client.js +111 -0
  113. package/dist/schemas/sdk-errors-server.d.ts +55 -0
  114. package/dist/schemas/sdk-errors-server.js +271 -0
  115. package/dist/schemas/set-config.d.ts +21 -0
  116. package/dist/schemas/set-config.js +14 -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 +2 -3
  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/model-registry.d.ts +13 -0
  158. package/dist/server/bare/registry/model-registry.js +24 -7
  159. package/dist/server/rpc/handle-request.js +42 -3
  160. package/dist/server/rpc/handlers/completion-stream-delegated.js +2 -1
  161. package/dist/server/rpc/handlers/completion-stream.js +11 -4
  162. package/dist/server/rpc/handlers/download-asset.js +2 -3
  163. package/dist/server/rpc/handlers/get-model-info.d.ts +3 -0
  164. package/dist/server/rpc/handlers/get-model-info.js +148 -0
  165. package/dist/server/rpc/handlers/index.d.ts +4 -0
  166. package/dist/server/rpc/handlers/index.js +6 -0
  167. package/dist/server/rpc/handlers/load-model/http.js +51 -10
  168. package/dist/server/rpc/handlers/load-model/hyperdrive.js +336 -156
  169. package/dist/server/rpc/handlers/load-model/index.js +1 -1
  170. package/dist/server/rpc/handlers/load-model/resolve.d.ts +1 -1
  171. package/dist/server/rpc/handlers/load-model/resolve.js +10 -6
  172. package/dist/server/rpc/handlers/load-model-delegated.js +7 -4
  173. package/dist/server/rpc/handlers/load-model.js +19 -1
  174. package/dist/server/rpc/handlers/provideHandler/handler.js +2 -1
  175. package/dist/server/rpc/handlers/rag.js +0 -3
  176. package/dist/server/rpc/handlers/set-config.d.ts +3 -0
  177. package/dist/server/rpc/handlers/set-config.js +18 -0
  178. package/dist/server/rpc/handlers/stopProvideHandler.js +3 -1
  179. package/dist/server/rpc/handlers/text-to-speech.d.ts +3 -0
  180. package/dist/server/rpc/handlers/text-to-speech.js +7 -0
  181. package/dist/server/rpc/handlers/transcribe-stream.js +6 -2
  182. package/dist/server/rpc/handlers/unload-model.js +7 -0
  183. package/dist/server/utils/audio/decoder.js +1 -1
  184. package/dist/server/utils/cache.d.ts +13 -8
  185. package/dist/server/utils/cache.js +69 -14
  186. package/dist/server/utils/checksum.d.ts +2 -0
  187. package/dist/server/utils/checksum.js +24 -0
  188. package/dist/server/utils/index.d.ts +2 -0
  189. package/dist/server/utils/index.js +2 -0
  190. package/dist/server/utils/shard-utils.d.ts +22 -0
  191. package/dist/server/utils/shard-utils.js +37 -0
  192. package/dist/server/utils/tool-integration.d.ts +13 -0
  193. package/dist/server/utils/tool-integration.js +43 -0
  194. package/dist/server/utils/tool-parser.d.ts +7 -0
  195. package/dist/server/utils/tool-parser.js +244 -0
  196. package/dist/utils/errors-base.d.ts +3 -0
  197. package/dist/utils/errors-base.js +13 -0
  198. package/dist/utils/errors-client.d.ts +107 -0
  199. package/dist/utils/errors-client.js +186 -0
  200. package/dist/utils/errors-server.d.ts +146 -0
  201. package/dist/utils/errors-server.js +253 -0
  202. package/dist/utils/tool-helpers.d.ts +17 -0
  203. package/dist/utils/tool-helpers.js +99 -0
  204. package/package.json +14 -10
  205. package/dist/examples/llamacpp-tools-routing.d.ts +0 -2
  206. package/dist/examples/llamacpp-tools-routing.js +0 -364
  207. package/dist/examples/llamacpp-tools.d.ts +0 -2
  208. package/dist/examples/llamacpp-tools.js +0 -81
  209. package/dist/server/http-server.d.ts +0 -2
  210. package/dist/server/http-server.js +0 -189
@@ -1,4 +1,8 @@
1
1
  import { type AnyModel } from "../../registry/model-registry";
2
2
  import { type NmtConfig } from "../../../../schemas/index";
3
- export declare function createNmtModel(modelId: string, modelPath: string, nmtConfig: NmtConfig): AnyModel;
3
+ import FilesystemDL from "@qvac/dl-filesystem";
4
+ export declare function createNmtModel(modelId: string, modelPath: string, nmtConfig: NmtConfig): {
5
+ model: AnyModel;
6
+ loader: FilesystemDL;
7
+ };
4
8
  //# sourceMappingURL=create-model.d.ts.map
@@ -1,45 +1,37 @@
1
1
  import TranslationNmtcpp from "@qvac/translation-nmtcpp";
2
- import { Readable } from "bare-stream";
3
2
  import {} from "../../registry/model-registry.js";
4
3
  import { INDICTRANS_LANGUAGES } from "../../../../schemas/index.js";
5
4
  import { createStreamLogger } from "../../../../logging/index.js";
6
5
  import { parseModelPath } from "../../../utils/index.js";
7
- // Mimic qvac-lib-dl-filesystem functionality
8
- function createFilesystemDLMimic(options) {
9
- return {
10
- dirPath: options.dirPath,
11
- getStream: () => {
12
- return Promise.resolve(Readable.from([]));
13
- },
14
- ready: () => Promise.resolve(),
15
- close: () => Promise.resolve(),
16
- destroy: () => Promise.resolve(),
17
- start: () => Promise.resolve(),
18
- stop: () => Promise.resolve(),
19
- };
20
- }
6
+ import FilesystemDL from "@qvac/dl-filesystem";
7
+ import { TranslationFailedError } from "../../../../utils/errors-server.js";
21
8
  export function createNmtModel(modelId, modelPath, nmtConfig) {
22
9
  const { dirPath, basePath } = parseModelPath(modelPath);
23
- const dl = createFilesystemDLMimic({
24
- dirPath: "./",
25
- });
10
+ const loader = new FilesystemDL({ dirPath });
26
11
  const logger = createStreamLogger(modelId, "nmtcpp");
12
+ const { mode, from, to, ...generationParams } = nmtConfig;
27
13
  const args = {
28
- loader: dl,
14
+ loader,
29
15
  logger,
30
16
  modelName: basePath,
31
17
  diskPath: dirPath,
32
18
  params: {
33
- mode: nmtConfig.mode,
34
- srcLang: nmtConfig.from,
35
- dstLang: nmtConfig.to,
19
+ mode,
20
+ srcLang: from,
21
+ dstLang: to,
36
22
  },
37
23
  };
38
24
  const config = {
39
- modelType: INDICTRANS_LANGUAGES.includes(nmtConfig.from) &&
40
- INDICTRANS_LANGUAGES.includes(nmtConfig.to)
25
+ modelType: INDICTRANS_LANGUAGES.includes(from) &&
26
+ INDICTRANS_LANGUAGES.includes(to)
41
27
  ? TranslationNmtcpp.ModelTypes.IndicTrans
42
28
  : TranslationNmtcpp.ModelTypes.Opus,
29
+ ...generationParams,
43
30
  };
44
- return new TranslationNmtcpp(args, config);
31
+ // Fail fast if model type is IndicTrans
32
+ if (config.modelType === TranslationNmtcpp.ModelTypes.IndicTrans) {
33
+ throw new TranslationFailedError("IndicTrans models are not supported with current NMT addon version.");
34
+ }
35
+ const model = new TranslationNmtcpp(args, config);
36
+ return { model, loader };
45
37
  }
@@ -1,5 +1,12 @@
1
1
  import { getModel } from "../../../registry/model-registry.js";
2
2
  import { translateServerParamsSchema, } from "../../../../../schemas/index.js";
3
+ import { getLangName } from "@qvac/langdetect-text";
4
+ function getLanguage(code) {
5
+ if (!code)
6
+ return "";
7
+ const fullName = getLangName(code);
8
+ return fullName ?? code.toUpperCase();
9
+ }
3
10
  export async function* translate(params) {
4
11
  const { modelId, text, modelType } = params;
5
12
  const from = params.modelType === "llm" ? params.from : undefined;
@@ -7,13 +14,15 @@ export async function* translate(params) {
7
14
  const context = params.modelType === "llm" ? params.context : undefined;
8
15
  translateServerParamsSchema.parse(params);
9
16
  const model = getModel(modelId);
17
+ const fromLanguage = getLanguage(from);
18
+ const toLanguage = getLanguage(to);
10
19
  // Prepare input based on model type
11
20
  const input = modelType === "nmt"
12
21
  ? text
13
22
  : [
14
23
  {
15
24
  role: "system",
16
- content: `${context ? `${context}. ` : ""}Translate the following text from ${from?.toUpperCase()} into ${to?.toUpperCase()}.Only output the translation, nothing else.\n\n${from?.toUpperCase()}: ${text}\n${to?.toUpperCase()}:`,
25
+ content: `${context ? `${context}. ` : ""}Translate the following text from ${fromLanguage} into ${toLanguage}. Only output the translation, nothing else.\n\n${fromLanguage}: ${text}\n${toLanguage}:`,
17
26
  },
18
27
  ];
19
28
  const startTime = Date.now();
@@ -0,0 +1,10 @@
1
+ import ONNXTTS from "@qvac/tts-onnx";
2
+ import { type AnyModel } from "../../registry/model-registry";
3
+ import { type TtsConfig } from "../../../../schemas/index";
4
+ import FilesystemDL from "@qvac/dl-filesystem";
5
+ export type TtsModel = ONNXTTS;
6
+ export declare function createTtsModel(modelId: string, modelPath: string, ttsConfig: TtsConfig, ttsConfigModelPath: string, eSpeakDataPath: string): {
7
+ model: AnyModel;
8
+ loader: FilesystemDL;
9
+ };
10
+ //# sourceMappingURL=create-model.d.ts.map
@@ -0,0 +1,25 @@
1
+ import ONNXTTS from "@qvac/tts-onnx";
2
+ import {} from "../../registry/model-registry.js";
3
+ import {} from "../../../../schemas/index.js";
4
+ import { createStreamLogger } from "../../../../logging/index.js";
5
+ import { parseModelPath } from "../../../utils/index.js";
6
+ import FilesystemDL from "@qvac/dl-filesystem";
7
+ export function createTtsModel(modelId, modelPath, ttsConfig, ttsConfigModelPath, eSpeakDataPath) {
8
+ const { dirPath, basePath: fileName } = parseModelPath(modelPath);
9
+ const loader = new FilesystemDL({ dirPath });
10
+ const logger = createStreamLogger(modelId, "tts");
11
+ const args = {
12
+ loader,
13
+ logger,
14
+ mainModelUrl: fileName,
15
+ configJsonPath: parseModelPath(ttsConfigModelPath).basePath,
16
+ cache: dirPath,
17
+ eSpeakDataPath: eSpeakDataPath,
18
+ opts: { stats: true },
19
+ };
20
+ const config = {
21
+ language: ttsConfig.language,
22
+ };
23
+ const model = new ONNXTTS(args, config);
24
+ return { model, loader };
25
+ }
@@ -0,0 +1,3 @@
1
+ import { type TtsRequest, type TtsResponse } from "../../../../../schemas/index";
2
+ export declare function textToSpeech(params: TtsRequest): AsyncGenerator<TtsResponse>;
3
+ //# sourceMappingURL=text-to-speech.d.ts.map
@@ -0,0 +1,87 @@
1
+ import { getModel } from "../../../registry/model-registry.js";
2
+ import { ttsRequestSchema } from "../../../../../schemas/index.js";
3
+ export async function* textToSpeech(params) {
4
+ const { modelId, inputType, text, stream } = ttsRequestSchema.parse(params);
5
+ const model = getModel(modelId);
6
+ const response = await model.run({ input: text, inputType });
7
+ if (!stream) {
8
+ // Non-streaming mode: wait for complete response and yield once
9
+ let completeBuffer = [];
10
+ await response
11
+ .onUpdate((data) => {
12
+ completeBuffer = completeBuffer.concat(Array.from(data.outputArray));
13
+ })
14
+ .await();
15
+ yield {
16
+ type: "textToSpeech",
17
+ buffer: completeBuffer,
18
+ done: true,
19
+ };
20
+ }
21
+ else {
22
+ // Streaming mode: use async iterator pattern
23
+ const outputQueue = [];
24
+ let isComplete = false;
25
+ let resolveNext = null;
26
+ // Start the response processing
27
+ const responsePromise = response
28
+ .onUpdate((data) => {
29
+ if (resolveNext) {
30
+ // If there's a pending read, resolve it immediately
31
+ resolveNext({
32
+ value: {
33
+ type: "textToSpeech",
34
+ buffer: Array.from(data.outputArray),
35
+ done: false,
36
+ },
37
+ done: false,
38
+ });
39
+ resolveNext = null;
40
+ }
41
+ else {
42
+ // Otherwise, queue the output
43
+ outputQueue.push(data);
44
+ }
45
+ })
46
+ .await()
47
+ .then(() => {
48
+ isComplete = true;
49
+ if (resolveNext) {
50
+ resolveNext({ value: undefined, done: true });
51
+ resolveNext = null;
52
+ }
53
+ });
54
+ // Create an async iterator
55
+ const asyncIterator = {
56
+ async next() {
57
+ if (outputQueue.length > 0) {
58
+ const data = outputQueue.shift();
59
+ return {
60
+ value: {
61
+ type: "textToSpeech",
62
+ buffer: Array.from(data.outputArray),
63
+ done: false,
64
+ },
65
+ done: false,
66
+ };
67
+ }
68
+ if (isComplete) {
69
+ return { value: undefined, done: true };
70
+ }
71
+ // Wait for the next output
72
+ return new Promise((resolve) => {
73
+ resolveNext = resolve;
74
+ });
75
+ },
76
+ [Symbol.asyncIterator]() {
77
+ return this;
78
+ },
79
+ };
80
+ // Yield outputs as they come
81
+ for await (const output of asyncIterator) {
82
+ yield output;
83
+ }
84
+ // Ensure the response is fully processed
85
+ await responsePromise;
86
+ }
87
+ }
@@ -0,0 +1,3 @@
1
+ export { createTtsModel } from "./create-model";
2
+ export { textToSpeech } from "./handlers/text-to-speech";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ export { createTtsModel } from "./create-model.js";
2
+ export { textToSpeech } from "./handlers/text-to-speech.js";
@@ -1,19 +1,37 @@
1
1
  import { promises as fsPromises } from "bare-fs";
2
+ import path from "bare-path";
2
3
  import { unregisterModel } from "../registry/model-registry.js";
3
4
  import { unregisterAllLoggingStreams } from "../registry/logging-stream-registry.js";
4
5
  import { unloadModelParamsSchema } from "../../../schemas/index.js";
6
+ import { ModelNotLoadedError } from "../../../utils/errors-server.js";
7
+ import { detectShardedModel } from "../../utils/index.js";
5
8
  export async function unloadModel(params) {
6
9
  const { modelId, clearStorage } = unloadModelParamsSchema.parse(params);
7
10
  const entry = unregisterModel(modelId);
8
11
  if (!entry) {
9
- throw new Error(`Model with ID "${modelId}" is not loaded`);
12
+ throw new ModelNotLoadedError(modelId);
13
+ }
14
+ if (entry.local?.loader) {
15
+ await entry.local.loader.close();
10
16
  }
11
17
  if (entry.local?.model && entry.local.model.unload) {
12
18
  await entry.local.model.unload();
13
19
  }
14
20
  if (clearStorage && entry.local?.path) {
15
- await fsPromises.rm(entry.local.path, { recursive: true, force: true });
16
- console.log(`Model storage cleared: ${entry.local.path}`);
21
+ const modelPath = entry.local.path;
22
+ const modelFileName = path.basename(modelPath);
23
+ const shardInfo = detectShardedModel(modelFileName);
24
+ if (shardInfo.isSharded) {
25
+ // Delete entire shard directory
26
+ const shardDir = path.dirname(modelPath);
27
+ await fsPromises.rm(shardDir, { recursive: true, force: true });
28
+ console.log(`Sharded model storage cleared: ${shardDir}`);
29
+ }
30
+ else {
31
+ // Delete single file
32
+ await fsPromises.rm(modelPath, { recursive: true, force: true });
33
+ console.log(`Model storage cleared: ${modelPath}`);
34
+ }
17
35
  }
18
36
  unregisterAllLoggingStreams(modelId);
19
37
  console.log(`Model ${modelId} unloaded`);
@@ -1,6 +1,10 @@
1
1
  import TranscriptionWhispercpp from "@qvac/transcription-whispercpp";
2
2
  import { type AnyModel } from "../../registry/model-registry";
3
3
  import { type WhisperConfig } from "../../../../schemas/index";
4
+ import FilesystemDL from "@qvac/dl-filesystem";
4
5
  export type WhispercppModel = TranscriptionWhispercpp;
5
- export declare function createWhisperModel(modelId: string, modelPath: string, whisperConfig: WhisperConfig, vadModelPath?: string): AnyModel;
6
+ export declare function createWhisperModel(modelId: string, modelPath: string, whisperConfig: WhisperConfig, vadModelPath?: string): {
7
+ model: AnyModel;
8
+ loader: FilesystemDL;
9
+ };
6
10
  //# sourceMappingURL=create-model.d.ts.map
@@ -1,42 +1,22 @@
1
1
  import TranscriptionWhispercpp from "@qvac/transcription-whispercpp";
2
- import { Readable } from "bare-stream";
3
2
  import {} from "../../registry/model-registry.js";
4
3
  import {} from "../../../../schemas/index.js";
5
4
  import { createStreamLogger } from "../../../../logging/index.js";
6
5
  import { parseModelPath } from "../../../utils/index.js";
7
- // Mimic qvac-lib-dl-filesystem functionality
8
- function createFilesystemDLMimic(options) {
9
- return {
10
- dirPath: options.dirPath,
11
- getStream: () => {
12
- return Readable.from([]);
13
- },
14
- ready: () => Promise.resolve(),
15
- close: () => Promise.resolve(),
16
- destroy: () => Promise.resolve(),
17
- getFileSize: () => Promise.resolve(0),
18
- download: () => Promise.resolve({
19
- await: () => Promise.resolve(),
20
- }),
21
- downloadFiles: () => Promise.resolve([]),
22
- };
23
- }
6
+ import FilesystemDL from "@qvac/dl-filesystem";
24
7
  export function createWhisperModel(modelId, modelPath, whisperConfig, vadModelPath) {
25
8
  const { dirPath, basePath } = parseModelPath(modelPath);
26
- // Handle VAD model path - now uses vadModelPath parameter for consistency
9
+ // Handle VAD model path
27
10
  let vadModelName = "";
28
- let vadDirPath = "./";
29
- if (vadModelPath) {
30
- const vadParsed = parseModelPath(vadModelPath);
31
- vadDirPath = vadParsed.dirPath;
11
+ const effectiveVadPath = vadModelPath || whisperConfig.vad_model_path;
12
+ if (effectiveVadPath) {
13
+ const vadParsed = parseModelPath(effectiveVadPath);
32
14
  vadModelName = vadParsed.basePath;
33
15
  }
34
- const dl = createFilesystemDLMimic({
35
- dirPath: vadDirPath,
36
- });
16
+ const loader = new FilesystemDL({ dirPath });
37
17
  const logger = createStreamLogger(modelId, "whispercpp");
38
18
  const args = {
39
- loader: dl,
19
+ loader,
40
20
  logger,
41
21
  modelName: basePath,
42
22
  diskPath: dirPath,
@@ -45,11 +25,12 @@ export function createWhisperModel(modelId, modelPath, whisperConfig, vadModelPa
45
25
  stats: false,
46
26
  },
47
27
  };
28
+ const { contextParams, miscConfig, ...whisperParams } = whisperConfig;
48
29
  const config = {
49
- whisperConfig: {
50
- ...whisperConfig,
51
- vad_model: vadModelPath || "",
52
- },
30
+ whisperConfig: whisperParams,
31
+ ...(contextParams && { contextParams }),
32
+ ...(miscConfig && { miscConfig }),
53
33
  };
54
- return new TranscriptionWhispercpp(args, config);
34
+ const model = new TranscriptionWhispercpp(args, config);
35
+ return { model, loader };
55
36
  }
@@ -1,30 +1,51 @@
1
- import { getModel } from "../../../registry/model-registry.js";
1
+ import { getModel, getModelConfig, updateModelConfig, } from "../../../registry/model-registry.js";
2
2
  import { Readable } from "bare-stream";
3
3
  import fs from "bare-fs";
4
4
  import { needsDecoding, decodeAudioToStream } from "../../../../utils/index.js";
5
- import path from "bare-path";
6
- import { transcribeParamsSchema } from "../../../../../schemas/index.js";
5
+ import {} from "../../../../../schemas/index.js";
6
+ import { AudioFileNotFoundError, InvalidAudioChunkError, } from "../../../../../utils/errors-server.js";
7
7
  export async function* transcribe(params) {
8
- const { audioChunk: audioInput, modelId } = transcribeParamsSchema.parse(params);
9
- const model = getModel(modelId);
8
+ const model = getModel(params.modelId);
9
+ if (params.prompt && typeof model.reload === "function") {
10
+ const existingConfig = getModelConfig(params.modelId);
11
+ const updatedConfig = {
12
+ ...existingConfig,
13
+ initial_prompt: params.prompt,
14
+ };
15
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
16
+ const { contextParams: _, miscConfig, ...whisperParams } = updatedConfig;
17
+ await model.reload({
18
+ whisperConfig: whisperParams,
19
+ ...(miscConfig && { miscConfig }),
20
+ });
21
+ updateModelConfig(params.modelId, updatedConfig);
22
+ }
10
23
  let audioStream;
11
- // Check if it's a file path or base64 buffer
12
- if (typeof audioInput === "string" &&
13
- (audioInput.startsWith("/") || audioInput.includes("."))) {
14
- // It's a file path - check if it needs decoding
15
- if (needsDecoding(audioInput)) {
16
- console.log(`Detected encoded format: ${path.extname(audioInput).toLowerCase()}, decoding before transcription...`);
17
- audioStream = await decodeAudioToStream(audioInput);
24
+ const audioChunk = params.audioChunk;
25
+ switch (audioChunk.type) {
26
+ case "base64": {
27
+ const audioBuffer = Buffer.from(audioChunk.value, "base64");
28
+ audioStream = Readable.from([audioBuffer]);
29
+ break;
18
30
  }
19
- else {
20
- // File doesn't need decoding (e.g., RAW), create stream directly
21
- audioStream = fs.createReadStream(audioInput);
31
+ case "filePath": {
32
+ const filePath = audioChunk.value;
33
+ try {
34
+ fs.accessSync(filePath);
35
+ }
36
+ catch (error) {
37
+ throw new AudioFileNotFoundError(filePath, error);
38
+ }
39
+ if (needsDecoding(filePath)) {
40
+ audioStream = await decodeAudioToStream(filePath);
41
+ }
42
+ else {
43
+ audioStream = fs.createReadStream(filePath);
44
+ }
45
+ break;
22
46
  }
23
- }
24
- else {
25
- // It's base64 encoded buffer - decode and create stream
26
- const audioBuffer = Buffer.from(audioInput, "base64");
27
- audioStream = Readable.from([audioBuffer]);
47
+ default:
48
+ throw new InvalidAudioChunkError();
28
49
  }
29
50
  // Run transcription with streaming enabled
30
51
  const response = await model.run(audioStream);
@@ -1,6 +1,7 @@
1
1
  import { getSwarm } from "./hyperswarm.js";
2
2
  import RPC from "bare-rpc";
3
3
  import { withTimeout } from "../../utils/withTimeout.js";
4
+ import { DelegateConnectionFailedError } from "../../utils/errors-server.js";
4
5
  // Map of active RPC instances by public key
5
6
  const activeRPCs = new Map();
6
7
  // Establish RPC connection to a peer if not already connected
@@ -27,7 +28,7 @@ async function ensureRPCConnection(topic, publicKey, timeout) {
27
28
  if (!rpc) {
28
29
  console.error(`❌ No RPC instance found for peer ${publicKey}`);
29
30
  console.log(`📊 Available RPC connections:`, Array.from(activeRPCs.keys()));
30
- throw new Error(`Could not establish RPC connection to peer ${publicKey} on topic ${topic}`);
31
+ throw new DelegateConnectionFailedError(`Could not establish RPC connection to peer ${publicKey} on topic ${topic}`);
31
32
  }
32
33
  else {
33
34
  console.log(`✅ RPC instance found for peer ${publicKey}`);
@@ -37,7 +38,7 @@ async function ensureRPCConnection(topic, publicKey, timeout) {
37
38
  }
38
39
  catch (error) {
39
40
  console.error("Failed to establish RPC connection:", error);
40
- throw new Error(`RPC connection failed: ${error instanceof Error ? error.message : String(error)}`);
41
+ throw new DelegateConnectionFailedError(`RPC connection failed: ${error instanceof Error ? error.message : String(error)}`, error);
41
42
  }
42
43
  }
43
44
  return rpc;
@@ -3,5 +3,8 @@ import { type FirewallConfig } from "../../schemas/provide";
3
3
  export declare function getSwarm({ firewallConfig, }?: {
4
4
  firewallConfig?: FirewallConfig | undefined;
5
5
  }): Hyperswarm;
6
+ export declare function registerProviderTopic(topic: string): void;
7
+ export declare function unregisterProviderTopic(topic: string): void;
8
+ export declare function hasActiveProviders(): boolean;
6
9
  export declare function destroySwarm(): Promise<void>;
7
10
  //# sourceMappingURL=hyperswarm.d.ts.map
@@ -2,6 +2,7 @@ import process from "bare-process";
2
2
  import Hyperswarm from "hyperswarm";
3
3
  import crypto from "bare-crypto";
4
4
  import { envSchema } from "../../schemas/provide.js";
5
+ import { getSDKConfig } from "./registry/config-registry.js";
5
6
  function getHyperswarmSeedBuffer() {
6
7
  const parsedEnv = envSchema.safeParse(process.env);
7
8
  if (parsedEnv.success) {
@@ -45,9 +46,19 @@ function createFirewallFunction(config) {
45
46
  function createSwarm(firewallConfig) {
46
47
  const seed = getHyperswarmSeedBuffer();
47
48
  const firewall = createFirewallFunction(firewallConfig);
48
- return new Hyperswarm({ seed, firewall });
49
+ const getRelays = () => {
50
+ const config = getSDKConfig();
51
+ const relayPublicKeys = config.swarmRelays;
52
+ if (!relayPublicKeys || relayPublicKeys.length === 0) {
53
+ return null;
54
+ }
55
+ return relayPublicKeys.map((key) => Buffer.from(key, "hex"));
56
+ };
57
+ const swarmOptions = { seed, firewall, relayThrough: getRelays };
58
+ return new Hyperswarm(swarmOptions);
49
59
  }
50
60
  let swarm;
61
+ const activeProviderTopics = new Set();
51
62
  export function getSwarm({ firewallConfig, } = {}) {
52
63
  if (swarm) {
53
64
  return swarm;
@@ -55,8 +66,18 @@ export function getSwarm({ firewallConfig, } = {}) {
55
66
  swarm = createSwarm(firewallConfig);
56
67
  return swarm;
57
68
  }
69
+ export function registerProviderTopic(topic) {
70
+ activeProviderTopics.add(topic);
71
+ }
72
+ export function unregisterProviderTopic(topic) {
73
+ activeProviderTopics.delete(topic);
74
+ }
75
+ export function hasActiveProviders() {
76
+ return activeProviderTopics.size > 0;
77
+ }
58
78
  export async function destroySwarm() {
59
79
  if (swarm) {
80
+ activeProviderTopics.clear();
60
81
  return swarm.destroy();
61
82
  }
62
83
  }
@@ -2,6 +2,7 @@ import { RAG, HyperDBAdapter } from "@qvac/rag";
2
2
  import Corestore from "corestore";
3
3
  import path from "bare-path";
4
4
  import { getEnv } from "../../worker.js";
5
+ import { RAGWorkspaceModelMismatchError } from "../../../utils/errors-server.js";
5
6
  const ragInstances = new Map();
6
7
  const defaultWorkspace = "default";
7
8
  const getStorePath = (workspace) => {
@@ -14,9 +15,7 @@ export const getRagInstance = async (modelId, embeddingFunction, workspace) => {
14
15
  if (existingEntry) {
15
16
  // Validate model consistency
16
17
  if (existingEntry.modelId !== modelId) {
17
- throw new Error(`Workspace "${key}" is configured for model "${existingEntry.modelId}", ` +
18
- `but you're trying to use model "${modelId}". ` +
19
- `Use a different workspace or the same model.`);
18
+ throw new RAGWorkspaceModelMismatchError(key, existingEntry.modelId, modelId);
20
19
  }
21
20
  return existingEntry.rag;
22
21
  }
@@ -0,0 +1,5 @@
1
+ import type { SDKConfig } from "../../../schemas/index";
2
+ export declare const setSDKConfig: (config: SDKConfig) => void;
3
+ export declare const getSDKConfig: () => SDKConfig;
4
+ export declare const getConfiguredCacheDir: () => string;
5
+ //# sourceMappingURL=config-registry.d.ts.map
@@ -0,0 +1,39 @@
1
+ import fs from "bare-fs";
2
+ import path from "bare-path";
3
+ import { getEnv } from "../../worker.js";
4
+ import { CacheDirNotAbsoluteError, CacheDirNotWritableError, } from "../../../utils/errors-server.js";
5
+ const configRegistry = {
6
+ cacheDirectory: undefined,
7
+ swarmRelays: undefined,
8
+ };
9
+ export const setSDKConfig = (config) => {
10
+ if (config.cacheDirectory !== undefined && config.cacheDirectory !== null) {
11
+ if (!path.isAbsolute(config.cacheDirectory)) {
12
+ throw new CacheDirNotAbsoluteError();
13
+ }
14
+ try {
15
+ fs.mkdirSync(config.cacheDirectory, { recursive: true });
16
+ const testFile = path.join(config.cacheDirectory, ".qvac-test");
17
+ fs.writeFileSync(testFile, "test");
18
+ fs.unlinkSync(testFile);
19
+ }
20
+ catch (error) {
21
+ throw new CacheDirNotWritableError(config.cacheDirectory, error instanceof Error ? error.message : String(error), error);
22
+ }
23
+ configRegistry.cacheDirectory = config.cacheDirectory;
24
+ console.log(`✅ Cache directory set to: ${config.cacheDirectory}`);
25
+ }
26
+ if (config.swarmRelays !== undefined && config.swarmRelays !== null) {
27
+ configRegistry.swarmRelays = config.swarmRelays;
28
+ }
29
+ };
30
+ export const getSDKConfig = () => {
31
+ return { ...configRegistry };
32
+ };
33
+ const getDefaultCacheDir = () => {
34
+ const homeDir = getEnv().HOME_DIR;
35
+ return path.join(homeDir, ".qvac", "models");
36
+ };
37
+ export const getConfiguredCacheDir = () => {
38
+ return configRegistry.cacheDirectory || getDefaultCacheDir();
39
+ };
@@ -1,4 +1,5 @@
1
1
  import type EventEmitter from "events";
2
+ import type FilesystemDL from "@qvac/dl-filesystem";
2
3
  interface AddonInterface {
3
4
  cancel(jobId?: string): Promise<void>;
4
5
  }
@@ -8,6 +9,11 @@ export interface AnyModel {
8
9
  onUpdate(callback: (data: string) => void): {
9
10
  await: () => Promise<void>;
10
11
  };
12
+ onUpdate(callback: (data: {
13
+ outputArray: Int16Array;
14
+ }) => void): {
15
+ await: () => Promise<void>;
16
+ };
11
17
  onError(callback: (error: Error) => void): void;
12
18
  onUpdate(callback: (data: Array<{
13
19
  text: string;
@@ -20,6 +26,7 @@ export interface AnyModel {
20
26
  }>>;
21
27
  await(): Promise<void>;
22
28
  }>;
29
+ reload?(config: unknown): Promise<void>;
23
30
  unload?(): Promise<void>;
24
31
  addon?: AddonInterface;
25
32
  }
@@ -33,6 +40,8 @@ interface LocalOptions {
33
40
  path: string;
34
41
  loadedAt: Date;
35
42
  config: unknown;
43
+ name?: string | undefined;
44
+ loader: FilesystemDL;
36
45
  }
37
46
  export interface ModelEntry {
38
47
  id: string;
@@ -44,6 +53,8 @@ export declare function registerModel(id: string, options: {
44
53
  model: AnyModel;
45
54
  path: string;
46
55
  config: unknown;
56
+ loader: FilesystemDL;
57
+ name?: string | undefined;
47
58
  } | {
48
59
  topic: string;
49
60
  providerPublicKey: string;
@@ -59,8 +70,10 @@ export declare function getModelInfo(id: string): {
59
70
  path: string;
60
71
  loadedAt: Date;
61
72
  config: unknown;
73
+ name?: string;
62
74
  } | null;
63
75
  export declare function getModelConfig(id: string): unknown;
76
+ export declare function updateModelConfig(id: string, config: unknown): void;
64
77
  export declare function clearRegistry(): void;
65
78
  export declare function getRegistryStats(): {
66
79
  totalModels: number;