@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,55 +1,86 @@
1
- import { promises as fsPromises } from "bare-fs";
2
- import path from "bare-path";
3
- import process from "bare-process";
4
- import { registerModel, isModelLoaded, } from "../registry/model-registry.js";
5
1
  import { loadModelServerParamsSchema, } from "../../../schemas/index.js";
6
- import { createWhisperModel } from "./whispercpp/index.js";
7
- import { createLlmModel } from "./llamacpp/index.js";
8
- import { createEmbeddingsModel } from "./llamacpp/index.js";
2
+ import { createEmbeddingsModel, createLlmModel, } from "./llamacpp/index.js";
9
3
  import { createNmtModel } from "./translation/index.js";
4
+ import { createTtsModel } from "./tts/index.js";
5
+ import { createWhisperModel } from "./whispercpp/index.js";
6
+ import { isModelLoaded, registerModel, } from "../registry/model-registry.js";
7
+ import { detectShardedModel, generateShardFilenames } from "../../utils/index.js";
8
+ import { ESpeakDataPathRequiredError, UnknownModelTypeError, ModelFileNotFoundError, ModelFileNotFoundInDirError, ModelFileLocateFailedError, } from "../../../utils/errors-server.js";
9
+ import { promises as fsPromises } from "bare-fs";
10
+ import path from "bare-path";
10
11
  export async function loadModel(params) {
11
- const { modelId, modelPath, options, projectionModelPath, vadModelPath } = loadModelServerParamsSchema.parse(params);
12
+ const { modelId, modelPath, options, projectionModelPath, vadModelPath, ttsConfigModelPath, eSpeakDataPath, modelName, } = loadModelServerParamsSchema.parse(params);
12
13
  const { modelConfig, modelType } = options;
13
14
  // Check if model is already loaded
14
15
  if (isModelLoaded(modelId)) {
15
16
  console.log(`${modelType} model ${modelId} is already loaded`);
16
17
  return;
17
18
  }
18
- // Validate the file exists
19
- console.log("cwd", process.cwd());
20
- try {
21
- const modelDir = path.dirname(modelPath);
22
- const modelFile = path.basename(modelPath);
23
- const files = (await fsPromises.readdir(modelDir));
24
- if (!files.includes(modelFile)) {
25
- throw new Error(`${modelType} model file ${modelFile} not found in directory ${modelDir}`);
19
+ // Detect if sharded model
20
+ const modelFileName = path.basename(modelPath);
21
+ const shardInfo = detectShardedModel(modelFileName);
22
+ const isShardedModel = shardInfo.isSharded;
23
+ if (isShardedModel) {
24
+ // For sharded models, validate all required files exist
25
+ const shardDir = path.dirname(modelPath);
26
+ const allRequiredFiles = generateShardFilenames(modelFileName);
27
+ for (const shardFile of allRequiredFiles) {
28
+ const shardPath = path.join(shardDir, shardFile);
29
+ try {
30
+ await fsPromises.access(shardPath);
31
+ }
32
+ catch (error) {
33
+ throw new ModelFileNotFoundError(`${shardFile}. Expected ${allRequiredFiles.length} files (shards + companion files) in ${shardDir}`, error);
34
+ }
26
35
  }
27
- // File exists, continue
28
36
  }
29
- catch (error) {
30
- console.error(`Error reading ${modelType} model directory:`, error instanceof Error ? error.message : String(error));
31
- throw new Error(`Failed to locate ${modelType} model file: ${modelPath}`);
37
+ else {
38
+ // For non-sharded models, validate single file exists
39
+ try {
40
+ const modelDir = path.dirname(modelPath);
41
+ const modelFile = path.basename(modelPath);
42
+ const files = (await fsPromises.readdir(modelDir));
43
+ if (!files.includes(modelFile)) {
44
+ throw new ModelFileNotFoundInDirError(modelFile, modelDir, modelType);
45
+ }
46
+ }
47
+ catch (error) {
48
+ console.error(`Error reading ${modelType} model directory:`, error instanceof Error ? error.message : String(error));
49
+ throw new ModelFileLocateFailedError(modelType, modelPath, error);
50
+ }
32
51
  }
33
- let model;
52
+ let result;
34
53
  switch (modelType) {
35
54
  case "llm":
36
- model = createLlmModel(modelId, modelPath, modelConfig, projectionModelPath);
55
+ result = createLlmModel(modelId, modelPath, modelConfig, projectionModelPath);
37
56
  break;
38
57
  case "whisper":
39
- model = createWhisperModel(modelId, modelPath, modelConfig, vadModelPath);
58
+ result = createWhisperModel(modelId, modelPath, modelConfig, vadModelPath);
40
59
  break;
41
60
  case "embeddings":
42
- model = createEmbeddingsModel(modelId, modelPath, modelConfig);
61
+ result = createEmbeddingsModel(modelId, modelPath, modelConfig);
43
62
  break;
44
63
  case "nmt":
45
- model = createNmtModel(modelId, modelPath, modelConfig);
64
+ result = createNmtModel(modelId, modelPath, modelConfig);
65
+ break;
66
+ case "tts":
67
+ if (!eSpeakDataPath) {
68
+ throw new ESpeakDataPathRequiredError();
69
+ }
70
+ result = createTtsModel(modelId, modelPath, modelConfig, ttsConfigModelPath, eSpeakDataPath);
46
71
  break;
47
72
  default:
48
73
  // Should never happen
49
- throw new Error(`Unknown model type`);
74
+ throw new UnknownModelTypeError(modelType);
50
75
  }
51
76
  console.log(`${modelType}: Loading model ${modelId}...`);
52
- await model.load(false);
77
+ await result.model.load(false);
53
78
  console.log(`${modelType} model ${modelId} loaded`);
54
- registerModel(modelId, { model, path: modelPath, config: modelConfig });
79
+ registerModel(modelId, {
80
+ model: result.model,
81
+ path: modelPath,
82
+ config: modelConfig,
83
+ name: modelName,
84
+ loader: result.loader,
85
+ });
55
86
  }
@@ -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
  }