@qvac/sdk 0.2.1-dev.1760851161.68dc306 → 0.2.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.
package/README.md CHANGED
@@ -79,7 +79,7 @@ npm i expo-file-system react-native-bare-kit
79
79
  ```js
80
80
  export default {
81
81
  expo: {
82
- plugins: ["qvac-sdk/expo-plugin"],
82
+ plugins: ["@qvac/sdk/expo-plugin"],
83
83
  },
84
84
  };
85
85
  ```
@@ -141,6 +141,7 @@ const cachedResponse = completion({
141
141
 
142
142
  // Unload model to free up system resources
143
143
  await unloadModel({ modelId });
144
+ process.exit();
144
145
  ```
145
146
 
146
147
  **For more on how to use QVAC SDK, see [SDK at QVAC documentation](https://tether-2.gitbook.io/qvac-by-tether-or-reference/y2AsIh94H9DJ1pIBCNj9/sdk)**.
@@ -161,10 +162,10 @@ bun run build # or `watch` for hotreload
161
162
  bun run build:pack
162
163
  ```
163
164
 
164
- This outputs a tarball under `dist/tetherto-qvac-sdk-{version}.tgz` that you can install in your project, e.g.:
165
+ This outputs a tarball under `dist/qvac-sdk-{version}.tgz` that you can install in your project, e.g.:
165
166
 
166
167
  ```bash
167
- npm i path/to/tetherto-qvac-sdk-0.0.1.tgz
168
+ npm i path/to/qvac-sdk-0.1.0.tgz
168
169
  ```
169
170
 
170
171
  ## Examples
@@ -1,4 +1,4 @@
1
- import { completion, loadModel, unloadModel } from "@qvac/sdk";
1
+ import { completion, loadModel, SMOLVLM2_2_500M_MULTIMODAL_Q8_0, MMPROJ_SMOLVLM2_2_500M_MULTIMODAL_Q8_0, unloadModel, } from "@qvac/sdk";
2
2
  if (process.argv.length < 3) {
3
3
  console.error(`Specify an image file path as the first argument and a second image file path as the second (optional) argument`);
4
4
  process.exit(1);
@@ -8,9 +8,9 @@ try {
8
8
  const imageFilePath = process.argv[2];
9
9
  // Load the main model with projection in a single step
10
10
  const modelId = await loadModel({
11
- modelSrc: "https://huggingface.co/ggml-org/SmolVLM2-500M-Video-Instruct-GGUF/resolve/main/SmolVLM2-500M-Video-Instruct-Q8_0.gguf",
11
+ modelSrc: SMOLVLM2_2_500M_MULTIMODAL_Q8_0,
12
12
  modelType: "llm",
13
- projectionModelSrc: "https://huggingface.co/ggml-org/SmolVLM2-500M-Video-Instruct-GGUF/resolve/main/mmproj-SmolVLM2-500M-Video-Instruct-Q8_0.gguf",
13
+ projectionModelSrc: MMPROJ_SMOLVLM2_2_500M_MULTIMODAL_Q8_0,
14
14
  modelConfig: {
15
15
  ctx_size: 1024,
16
16
  },
@@ -41,9 +41,10 @@ try {
41
41
  documents: medicalArticle,
42
42
  chunk: true,
43
43
  chunkOpts: {
44
- chunkSize: 30,
44
+ chunkSize: 100,
45
45
  chunkOverlap: 10,
46
46
  chunkStrategy: "paragraph",
47
+ splitStrategy: "token",
47
48
  },
48
49
  });
49
50
  console.log(`✅ Created ${medicalResult.processed.length} chunks from medical article`);
@@ -62,6 +62,20 @@ export declare const models: readonly [{
62
62
  readonly addon: "llm";
63
63
  readonly expectedSize: 1056782912;
64
64
  readonly sha256Checksum: "c876f159707a4e4f70e045106c69db15bfc935a4981706fd4f65c6e7ea1e81c5";
65
+ }, {
66
+ readonly hyperdriveKey: "583f04c31d151b29e02aaf98f80d16aff585714ef9e2806a5067651c0f64ae31";
67
+ readonly hyperbeeKey: "generation:qwen2.5-omni:multimodal::3B::1.0.0";
68
+ readonly modelId: "Qwen2.5-Omni-3B-Q4_K_M.gguf";
69
+ readonly addon: "llm";
70
+ readonly expectedSize: 2104931648;
71
+ readonly sha256Checksum: "4b0bd358c1e9ec55dd3055ef6d71c958c821533d85916a10cfa89c4552a86e29";
72
+ }, {
73
+ readonly hyperdriveKey: "583f04c31d151b29e02aaf98f80d16aff585714ef9e2806a5067651c0f64ae31";
74
+ readonly hyperbeeKey: "generation:qwen2.5-omni:multimodal::3B::1.0.0";
75
+ readonly modelId: "mmproj-Qwen2.5-Omni-3B-Q8_0.gguf";
76
+ readonly addon: "llm";
77
+ readonly expectedSize: 1538031328;
78
+ readonly sha256Checksum: "4e6c816cd33f7298d07cb780c136a396631e50e62f6501660271f8c6e302e565";
65
79
  }, {
66
80
  readonly hyperdriveKey: "d331ed49c444f90b3b2a70aa5b820752685142bf2d769a0592ed666140477578";
67
81
  readonly hyperbeeKey: "generation:qwen3:instruct::0.6B::1.0.0";
@@ -97,6 +111,34 @@ export declare const models: readonly [{
97
111
  readonly addon: "llm";
98
112
  readonly expectedSize: 2401075552;
99
113
  readonly sha256Checksum: "9cfebb63cd7e6b6d1755ea8ef001fcdadfa17831da1db96eafe3fc554913d5e1";
114
+ }, {
115
+ readonly hyperdriveKey: "b99c6f5dcadaad827cdcb1a129a3b34aff6ad28056738e0bd559c7ffb807e30f";
116
+ readonly hyperbeeKey: "generation:smolVLM2:multimodal:2:500M:f16:1.0.0:video-instruct";
117
+ readonly modelId: "SmolVLM2-500M-Video-Instruct-f16.gguf";
118
+ readonly addon: "llm";
119
+ readonly expectedSize: 820424704;
120
+ readonly sha256Checksum: "80f7e3f04bc2d3324ac1a9f52f5776fe13a69912adf74f8e7edacf773d140d77";
121
+ }, {
122
+ readonly hyperdriveKey: "b99c6f5dcadaad827cdcb1a129a3b34aff6ad28056738e0bd559c7ffb807e30f";
123
+ readonly hyperbeeKey: "generation:smolVLM2:multimodal:2:500M:f16:1.0.0:video-instruct";
124
+ readonly modelId: "mmproj-SmolVLM2-500M-Video-Instruct-f16.gguf";
125
+ readonly addon: "llm";
126
+ readonly expectedSize: 199470624;
127
+ readonly sha256Checksum: "b5dc8ebe7cbeab66a5369693960a52515d7824f13d4063ceca78431f2a6b59b0";
128
+ }, {
129
+ readonly hyperdriveKey: "73b1bc01d01e25fa27be7d7f434337d14f054b0315e8463766ca31e778ac6576";
130
+ readonly hyperbeeKey: "generation:smolVLM2:multimodal:2:500M:q8_0:1.0.0:video-instruct";
131
+ readonly modelId: "SmolVLM2-500M-Video-Instruct-Q8_0.gguf";
132
+ readonly addon: "llm";
133
+ readonly expectedSize: 436808704;
134
+ readonly sha256Checksum: "6f67b8036b2469fcd71728702720c6b51aebd759b78137a8120733b4d66438bc";
135
+ }, {
136
+ readonly hyperdriveKey: "73b1bc01d01e25fa27be7d7f434337d14f054b0315e8463766ca31e778ac6576";
137
+ readonly hyperbeeKey: "generation:smolVLM2:multimodal:2:500M:q8_0:1.0.0:video-instruct";
138
+ readonly modelId: "mmproj-SmolVLM2-500M-Video-Instruct-Q8_0.gguf";
139
+ readonly addon: "llm";
140
+ readonly expectedSize: 108785184;
141
+ readonly sha256Checksum: "921dc7e259f308e5b027111fa185efcbf33db13f6e35749ddf7f5cdb60ef520b";
100
142
  }, {
101
143
  readonly hyperdriveKey: "268c2e9b2a3420632e4b6649e32822f42d5dfbda4c7e96daec5b629ed20f99f7";
102
144
  readonly hyperbeeKey: "translation:ggml-indictrans:dist:2:200M:q0f32:1.0.0:en-hi";
@@ -421,11 +463,17 @@ export declare const GTE_LARGE_FP16: "pear://d1896d9259692818df95bd2480e90c2d057
421
463
  export declare const LASER_DOLPHIN_2_6_2X7B_INST_Q2_K: "pear://bd40e4bfae48b5bf436d1b0b447ae26e4c384aebe101a5e7df6ae71c919dadf1/dolphin-mixtral-2x7b-dop-Q2_K.gguf";
422
464
  export declare const LLAMA_3_2_1B_INST_Q4_0: "pear://afa79ee07c0a138bb9f11bfaee771fb1bdfca8c82d961cff0474e49827bd1de3/Llama-3.2-1B-Instruct-Q4_0.gguf";
423
465
  export declare const QWEN_3_1_7B_INST_Q4: "pear://05d3d7ad9cd650f53c28f85e312ef09a645dd487845897958b3be8a19cb3aab9/Qwen3-1.7B-Q4_0.gguf";
466
+ export declare const QWEN2_5_OMNI_3B_MULTIMODAL: "pear://583f04c31d151b29e02aaf98f80d16aff585714ef9e2806a5067651c0f64ae31/Qwen2.5-Omni-3B-Q4_K_M.gguf";
467
+ export declare const MMPROJ_QWEN2_5_OMNI_3B_MULTIMODAL: "pear://583f04c31d151b29e02aaf98f80d16aff585714ef9e2806a5067651c0f64ae31/mmproj-Qwen2.5-Omni-3B-Q8_0.gguf";
424
468
  export declare const QWEN3_0_6B_INST: "pear://d331ed49c444f90b3b2a70aa5b820752685142bf2d769a0592ed666140477578/Qwen3-0.6B-UD-IQ1_S.gguf";
425
469
  export declare const QWEN3_4B_INST_Q4: "pear://19ffb75463149955ee24d786dfddd84d41fc872ea813cd4465f5f7299d165adc/model.gguf";
426
470
  export declare const QWEN3_600M_INST_Q4: "pear://211874c9885f6b88b9926904420e365f5e74e1b6ac47207b7536408539bef4b7/Qwen3-0.6B-Q4_0.gguf";
427
471
  export declare const SALAMANDRATA_2B_INST_Q4: "pear://1610d81772a9e7c37660666dbdfdcef915b6b83c522ea1ad31c19cab0075811d/salamandrata_2b_inst_q4.gguf";
428
472
  export declare const SALAMANDRATA_2B_INST_Q8: "pear://96860337b0bdffdbb8ef0df4c8b2c3ab5e78568f5f7e15815a0a6b392512c9b5/salamandrata_2b_inst_q8.gguf";
473
+ export declare const SMOLVLM2_2_500M_MULTIMODAL_F16: "pear://b99c6f5dcadaad827cdcb1a129a3b34aff6ad28056738e0bd559c7ffb807e30f/SmolVLM2-500M-Video-Instruct-f16.gguf";
474
+ export declare const MMPROJ_SMOLVLM2_2_500M_MULTIMODAL_F16: "pear://b99c6f5dcadaad827cdcb1a129a3b34aff6ad28056738e0bd559c7ffb807e30f/mmproj-SmolVLM2-500M-Video-Instruct-f16.gguf";
475
+ export declare const SMOLVLM2_2_500M_MULTIMODAL_Q8_0: "pear://73b1bc01d01e25fa27be7d7f434337d14f054b0315e8463766ca31e778ac6576/SmolVLM2-500M-Video-Instruct-Q8_0.gguf";
476
+ export declare const MMPROJ_SMOLVLM2_2_500M_MULTIMODAL_Q8_0: "pear://73b1bc01d01e25fa27be7d7f434337d14f054b0315e8463766ca31e778ac6576/mmproj-SmolVLM2-500M-Video-Instruct-Q8_0.gguf";
429
477
  export declare const MARIAN_EN_HI_INDIC_200M_Q0F32: "pear://268c2e9b2a3420632e4b6649e32822f42d5dfbda4c7e96daec5b629ed20f99f7/ggml-indictrans2-en-indic-dist-200M.bin";
430
478
  export declare const MARIAN_HI_EN_INDIC_200M_Q0F32: "pear://dfea395ffe1cb6d259029e5c81c290f8828981987855e23e7b66fd7c705901eb/ggml-indictrans2-indic-en-dist-200M.bin";
431
479
  export declare const MARIAN_HI_HI_INDIC_320M_Q0F32: "pear://9a66da960931c449b41e3315d9aea4d3925f2cda024e8a4c139b64d0a539ed41/ggml-indictrans2-indic-indic-dist-320M.bin";
@@ -471,5 +519,5 @@ export declare const WHISPER_LARGE_3: "pear://76fb36d7f16a430618962d3e78b0e22e61
471
519
  export declare const WHISPER_SMALL: "pear://c6a987fbb4ad8fba1526e446501f88ee45dfafbf1685410a7aeadb589fe18608/ggml-small.en-q8_0.bin";
472
520
  export declare const WHISPER_TINY: "pear://9281d61503593fdf3eaa9d5e5d44746c271ef930aed3b7f8ee9ce153c76399d6/ggml-tiny.bin";
473
521
  export declare const WHISPER_TINY_SILERO: "pear://ebfb94b378276da139554668f1ff737644eadff529c2ea0f2662d7df61fd86ca/ggml-tiny.bin";
474
- export declare function getModelBySrc(modelId: string, hyperdriveKey?: string): HyperdriveItem | undefined;
522
+ export declare function getModelBySrc(modelId: string, hyperdriveKey: string): HyperdriveItem | undefined;
475
523
  //# sourceMappingURL=models.d.ts.map
@@ -65,6 +65,22 @@ export const models = [
65
65
  expectedSize: 1056782912,
66
66
  sha256Checksum: "c876f159707a4e4f70e045106c69db15bfc935a4981706fd4f65c6e7ea1e81c5",
67
67
  },
68
+ {
69
+ hyperdriveKey: "583f04c31d151b29e02aaf98f80d16aff585714ef9e2806a5067651c0f64ae31",
70
+ hyperbeeKey: "generation:qwen2.5-omni:multimodal::3B::1.0.0",
71
+ modelId: "Qwen2.5-Omni-3B-Q4_K_M.gguf",
72
+ addon: "llm",
73
+ expectedSize: 2104931648,
74
+ sha256Checksum: "4b0bd358c1e9ec55dd3055ef6d71c958c821533d85916a10cfa89c4552a86e29",
75
+ },
76
+ {
77
+ hyperdriveKey: "583f04c31d151b29e02aaf98f80d16aff585714ef9e2806a5067651c0f64ae31",
78
+ hyperbeeKey: "generation:qwen2.5-omni:multimodal::3B::1.0.0",
79
+ modelId: "mmproj-Qwen2.5-Omni-3B-Q8_0.gguf",
80
+ addon: "llm",
81
+ expectedSize: 1538031328,
82
+ sha256Checksum: "4e6c816cd33f7298d07cb780c136a396631e50e62f6501660271f8c6e302e565",
83
+ },
68
84
  {
69
85
  hyperdriveKey: "d331ed49c444f90b3b2a70aa5b820752685142bf2d769a0592ed666140477578",
70
86
  hyperbeeKey: "generation:qwen3:instruct::0.6B::1.0.0",
@@ -105,6 +121,38 @@ export const models = [
105
121
  expectedSize: 2401075552,
106
122
  sha256Checksum: "9cfebb63cd7e6b6d1755ea8ef001fcdadfa17831da1db96eafe3fc554913d5e1",
107
123
  },
124
+ {
125
+ hyperdriveKey: "b99c6f5dcadaad827cdcb1a129a3b34aff6ad28056738e0bd559c7ffb807e30f",
126
+ hyperbeeKey: "generation:smolVLM2:multimodal:2:500M:f16:1.0.0:video-instruct",
127
+ modelId: "SmolVLM2-500M-Video-Instruct-f16.gguf",
128
+ addon: "llm",
129
+ expectedSize: 820424704,
130
+ sha256Checksum: "80f7e3f04bc2d3324ac1a9f52f5776fe13a69912adf74f8e7edacf773d140d77",
131
+ },
132
+ {
133
+ hyperdriveKey: "b99c6f5dcadaad827cdcb1a129a3b34aff6ad28056738e0bd559c7ffb807e30f",
134
+ hyperbeeKey: "generation:smolVLM2:multimodal:2:500M:f16:1.0.0:video-instruct",
135
+ modelId: "mmproj-SmolVLM2-500M-Video-Instruct-f16.gguf",
136
+ addon: "llm",
137
+ expectedSize: 199470624,
138
+ sha256Checksum: "b5dc8ebe7cbeab66a5369693960a52515d7824f13d4063ceca78431f2a6b59b0",
139
+ },
140
+ {
141
+ hyperdriveKey: "73b1bc01d01e25fa27be7d7f434337d14f054b0315e8463766ca31e778ac6576",
142
+ hyperbeeKey: "generation:smolVLM2:multimodal:2:500M:q8_0:1.0.0:video-instruct",
143
+ modelId: "SmolVLM2-500M-Video-Instruct-Q8_0.gguf",
144
+ addon: "llm",
145
+ expectedSize: 436808704,
146
+ sha256Checksum: "6f67b8036b2469fcd71728702720c6b51aebd759b78137a8120733b4d66438bc",
147
+ },
148
+ {
149
+ hyperdriveKey: "73b1bc01d01e25fa27be7d7f434337d14f054b0315e8463766ca31e778ac6576",
150
+ hyperbeeKey: "generation:smolVLM2:multimodal:2:500M:q8_0:1.0.0:video-instruct",
151
+ modelId: "mmproj-SmolVLM2-500M-Video-Instruct-Q8_0.gguf",
152
+ addon: "llm",
153
+ expectedSize: 108785184,
154
+ sha256Checksum: "921dc7e259f308e5b027111fa185efcbf33db13f6e35749ddf7f5cdb60ef520b",
155
+ },
108
156
  {
109
157
  hyperdriveKey: "268c2e9b2a3420632e4b6649e32822f42d5dfbda4c7e96daec5b629ed20f99f7",
110
158
  hyperbeeKey: "translation:ggml-indictrans:dist:2:200M:q0f32:1.0.0:en-hi",
@@ -475,60 +523,63 @@ export const GTE_LARGE_FP16 = `pear://${models[4].hyperdriveKey}/${models[4].mod
475
523
  export const LASER_DOLPHIN_2_6_2X7B_INST_Q2_K = `pear://${models[5].hyperdriveKey}/${models[5].modelId}`;
476
524
  export const LLAMA_3_2_1B_INST_Q4_0 = `pear://${models[6].hyperdriveKey}/${models[6].modelId}`;
477
525
  export const QWEN_3_1_7B_INST_Q4 = `pear://${models[7].hyperdriveKey}/${models[7].modelId}`;
478
- export const QWEN3_0_6B_INST = `pear://${models[8].hyperdriveKey}/${models[8].modelId}`;
479
- export const QWEN3_4B_INST_Q4 = `pear://${models[9].hyperdriveKey}/${models[9].modelId}`;
480
- export const QWEN3_600M_INST_Q4 = `pear://${models[10].hyperdriveKey}/${models[10].modelId}`;
481
- export const SALAMANDRATA_2B_INST_Q4 = `pear://${models[11].hyperdriveKey}/${models[11].modelId}`;
482
- export const SALAMANDRATA_2B_INST_Q8 = `pear://${models[12].hyperdriveKey}/${models[12].modelId}`;
483
- export const MARIAN_EN_HI_INDIC_200M_Q0F32 = `pear://${models[13].hyperdriveKey}/${models[13].modelId}`;
484
- export const MARIAN_HI_EN_INDIC_200M_Q0F32 = `pear://${models[14].hyperdriveKey}/${models[14].modelId}`;
485
- export const MARIAN_HI_HI_INDIC_320M_Q0F32 = `pear://${models[15].hyperdriveKey}/${models[15].modelId}`;
486
- export const MARIAN_EN_HI_INDIC_1B_Q0F16 = `pear://${models[16].hyperdriveKey}/${models[16].modelId}`;
487
- export const MARIAN_HI_EN_INDIC_1B_Q0F16 = `pear://${models[17].hyperdriveKey}/${models[17].modelId}`;
488
- export const MARIAN_HI_HI_INDIC_1B_Q0F16 = `pear://${models[18].hyperdriveKey}/${models[18].modelId}`;
489
- export const MARIAN_EN_HI_INDIC_1B_Q0F32 = `pear://${models[19].hyperdriveKey}/${models[19].modelId}`;
490
- export const MARIAN_HI_EN_INDIC_1B_Q0F32 = `pear://${models[20].hyperdriveKey}/${models[20].modelId}`;
491
- export const MARIAN_HI_HI_INDIC_1B_Q0F32 = `pear://${models[21].hyperdriveKey}/${models[21].modelId}`;
492
- export const MARIAN_EN_HI_INDIC_1B_Q4_0 = `pear://${models[22].hyperdriveKey}/${models[22].modelId}`;
493
- export const MARIAN_HI_EN_INDIC_1B_Q4_0 = `pear://${models[23].hyperdriveKey}/${models[23].modelId}`;
494
- export const MARIAN_HI_HI_INDIC_1B_Q4_0 = `pear://${models[24].hyperdriveKey}/${models[24].modelId}`;
495
- export const MARIAN_EN_HI_INDIC_200M_Q0F16 = `pear://${models[25].hyperdriveKey}/${models[25].modelId}`;
496
- export const MARIAN_HI_EN_INDIC_200M_Q0F16 = `pear://${models[26].hyperdriveKey}/${models[26].modelId}`;
497
- export const MARIAN_EN_HI_INDIC_200M_Q4_0 = `pear://${models[27].hyperdriveKey}/${models[27].modelId}`;
498
- export const MARIAN_HI_EN_INDIC_200M_Q4_0 = `pear://${models[28].hyperdriveKey}/${models[28].modelId}`;
499
- export const MARIAN_HI_HI_INDIC_320M_Q0F16 = `pear://${models[29].hyperdriveKey}/${models[29].modelId}`;
500
- export const MARIAN_HI_HI_INDIC_320M_Q4_0 = `pear://${models[30].hyperdriveKey}/${models[30].modelId}`;
501
- export const MARIAN_OPUS_EN_IT = `pear://${models[31].hyperdriveKey}/${models[31].modelId}`;
502
- export const MARIAN_OPUS_IT_EN = `pear://${models[32].hyperdriveKey}/${models[32].modelId}`;
503
- export const MARIAN_OPUS_DE_EN_Q0F32 = `pear://${models[33].hyperdriveKey}/${models[33].modelId}`;
504
- export const MARIAN_OPUS_DE_ES_Q0F32 = `pear://${models[34].hyperdriveKey}/${models[34].modelId}`;
505
- export const MARIAN_OPUS_DE_IT_Q0F32 = `pear://${models[35].hyperdriveKey}/${models[35].modelId}`;
506
- export const MARIAN_OPUS_EN_DE_Q0F32 = `pear://${models[36].hyperdriveKey}/${models[36].modelId}`;
507
- export const MARIAN_OPUS_EN_ES_Q0F32 = `pear://${models[37].hyperdriveKey}/${models[37].modelId}`;
508
- export const MARIAN_OPUS_EN_IT_Q0F32 = `pear://${models[38].hyperdriveKey}/${models[38].modelId}`;
509
- export const MARIAN_OPUS_ES_DE_Q0F32 = `pear://${models[39].hyperdriveKey}/${models[39].modelId}`;
510
- export const MARIAN_OPUS_ES_EN_Q0F32 = `pear://${models[40].hyperdriveKey}/${models[40].modelId}`;
511
- export const MARIAN_OPUS_ES_IT_Q0F32 = `pear://${models[41].hyperdriveKey}/${models[41].modelId}`;
512
- export const MARIAN_OPUS_IT_DE_Q0F32 = `pear://${models[42].hyperdriveKey}/${models[42].modelId}`;
513
- export const MARIAN_OPUS_IT_EN_Q0F32 = `pear://${models[43].hyperdriveKey}/${models[43].modelId}`;
514
- export const MARIAN_OPUS_IT_ES_Q0F32 = `pear://${models[44].hyperdriveKey}/${models[44].modelId}`;
515
- export const MARIAN_OPUS_EN_RU_Q0F16 = `pear://${models[45].hyperdriveKey}/${models[45].modelId}`;
516
- export const MARIAN_OPUS_RU_EN_Q0F16 = `pear://${models[46].hyperdriveKey}/${models[46].modelId}`;
517
- export const MARIAN_OPUS_EN_RU_Q0F32 = `pear://${models[47].hyperdriveKey}/${models[47].modelId}`;
518
- export const MARIAN_OPUS_RU_EN_Q0F32 = `pear://${models[48].hyperdriveKey}/${models[48].modelId}`;
519
- export const MARIAN_OPUS_EN_RU_Q4_0 = `pear://${models[49].hyperdriveKey}/${models[49].modelId}`;
520
- export const MARIAN_OPUS_RU_EN_Q4_0 = `pear://${models[50].hyperdriveKey}/${models[50].modelId}`;
521
- export const MARIAN_OPUS_EN_JA_Q4F16_1 = `pear://${models[51].hyperdriveKey}/${models[51].modelId}`;
522
- export const MARIAN_OPUS_JA_EN_Q4F16_1 = `pear://${models[52].hyperdriveKey}/${models[52].modelId}`;
523
- export const VAD_SILERO_5_1_2 = `pear://${models[53].hyperdriveKey}/${models[53].modelId}`;
524
- export const WHISPER_LARGE_3 = `pear://${models[54].hyperdriveKey}/${models[54].modelId}`;
525
- export const WHISPER_SMALL = `pear://${models[55].hyperdriveKey}/${models[55].modelId}`;
526
- export const WHISPER_TINY = `pear://${models[56].hyperdriveKey}/${models[56].modelId}`;
527
- export const WHISPER_TINY_SILERO = `pear://${models[57].hyperdriveKey}/${models[57].modelId}`;
526
+ export const QWEN2_5_OMNI_3B_MULTIMODAL = `pear://${models[8].hyperdriveKey}/${models[8].modelId}`;
527
+ export const MMPROJ_QWEN2_5_OMNI_3B_MULTIMODAL = `pear://${models[9].hyperdriveKey}/${models[9].modelId}`;
528
+ export const QWEN3_0_6B_INST = `pear://${models[10].hyperdriveKey}/${models[10].modelId}`;
529
+ export const QWEN3_4B_INST_Q4 = `pear://${models[11].hyperdriveKey}/${models[11].modelId}`;
530
+ export const QWEN3_600M_INST_Q4 = `pear://${models[12].hyperdriveKey}/${models[12].modelId}`;
531
+ export const SALAMANDRATA_2B_INST_Q4 = `pear://${models[13].hyperdriveKey}/${models[13].modelId}`;
532
+ export const SALAMANDRATA_2B_INST_Q8 = `pear://${models[14].hyperdriveKey}/${models[14].modelId}`;
533
+ export const SMOLVLM2_2_500M_MULTIMODAL_F16 = `pear://${models[15].hyperdriveKey}/${models[15].modelId}`;
534
+ export const MMPROJ_SMOLVLM2_2_500M_MULTIMODAL_F16 = `pear://${models[16].hyperdriveKey}/${models[16].modelId}`;
535
+ export const SMOLVLM2_2_500M_MULTIMODAL_Q8_0 = `pear://${models[17].hyperdriveKey}/${models[17].modelId}`;
536
+ export const MMPROJ_SMOLVLM2_2_500M_MULTIMODAL_Q8_0 = `pear://${models[18].hyperdriveKey}/${models[18].modelId}`;
537
+ export const MARIAN_EN_HI_INDIC_200M_Q0F32 = `pear://${models[19].hyperdriveKey}/${models[19].modelId}`;
538
+ export const MARIAN_HI_EN_INDIC_200M_Q0F32 = `pear://${models[20].hyperdriveKey}/${models[20].modelId}`;
539
+ export const MARIAN_HI_HI_INDIC_320M_Q0F32 = `pear://${models[21].hyperdriveKey}/${models[21].modelId}`;
540
+ export const MARIAN_EN_HI_INDIC_1B_Q0F16 = `pear://${models[22].hyperdriveKey}/${models[22].modelId}`;
541
+ export const MARIAN_HI_EN_INDIC_1B_Q0F16 = `pear://${models[23].hyperdriveKey}/${models[23].modelId}`;
542
+ export const MARIAN_HI_HI_INDIC_1B_Q0F16 = `pear://${models[24].hyperdriveKey}/${models[24].modelId}`;
543
+ export const MARIAN_EN_HI_INDIC_1B_Q0F32 = `pear://${models[25].hyperdriveKey}/${models[25].modelId}`;
544
+ export const MARIAN_HI_EN_INDIC_1B_Q0F32 = `pear://${models[26].hyperdriveKey}/${models[26].modelId}`;
545
+ export const MARIAN_HI_HI_INDIC_1B_Q0F32 = `pear://${models[27].hyperdriveKey}/${models[27].modelId}`;
546
+ export const MARIAN_EN_HI_INDIC_1B_Q4_0 = `pear://${models[28].hyperdriveKey}/${models[28].modelId}`;
547
+ export const MARIAN_HI_EN_INDIC_1B_Q4_0 = `pear://${models[29].hyperdriveKey}/${models[29].modelId}`;
548
+ export const MARIAN_HI_HI_INDIC_1B_Q4_0 = `pear://${models[30].hyperdriveKey}/${models[30].modelId}`;
549
+ export const MARIAN_EN_HI_INDIC_200M_Q0F16 = `pear://${models[31].hyperdriveKey}/${models[31].modelId}`;
550
+ export const MARIAN_HI_EN_INDIC_200M_Q0F16 = `pear://${models[32].hyperdriveKey}/${models[32].modelId}`;
551
+ export const MARIAN_EN_HI_INDIC_200M_Q4_0 = `pear://${models[33].hyperdriveKey}/${models[33].modelId}`;
552
+ export const MARIAN_HI_EN_INDIC_200M_Q4_0 = `pear://${models[34].hyperdriveKey}/${models[34].modelId}`;
553
+ export const MARIAN_HI_HI_INDIC_320M_Q0F16 = `pear://${models[35].hyperdriveKey}/${models[35].modelId}`;
554
+ export const MARIAN_HI_HI_INDIC_320M_Q4_0 = `pear://${models[36].hyperdriveKey}/${models[36].modelId}`;
555
+ export const MARIAN_OPUS_EN_IT = `pear://${models[37].hyperdriveKey}/${models[37].modelId}`;
556
+ export const MARIAN_OPUS_IT_EN = `pear://${models[38].hyperdriveKey}/${models[38].modelId}`;
557
+ export const MARIAN_OPUS_DE_EN_Q0F32 = `pear://${models[39].hyperdriveKey}/${models[39].modelId}`;
558
+ export const MARIAN_OPUS_DE_ES_Q0F32 = `pear://${models[40].hyperdriveKey}/${models[40].modelId}`;
559
+ export const MARIAN_OPUS_DE_IT_Q0F32 = `pear://${models[41].hyperdriveKey}/${models[41].modelId}`;
560
+ export const MARIAN_OPUS_EN_DE_Q0F32 = `pear://${models[42].hyperdriveKey}/${models[42].modelId}`;
561
+ export const MARIAN_OPUS_EN_ES_Q0F32 = `pear://${models[43].hyperdriveKey}/${models[43].modelId}`;
562
+ export const MARIAN_OPUS_EN_IT_Q0F32 = `pear://${models[44].hyperdriveKey}/${models[44].modelId}`;
563
+ export const MARIAN_OPUS_ES_DE_Q0F32 = `pear://${models[45].hyperdriveKey}/${models[45].modelId}`;
564
+ export const MARIAN_OPUS_ES_EN_Q0F32 = `pear://${models[46].hyperdriveKey}/${models[46].modelId}`;
565
+ export const MARIAN_OPUS_ES_IT_Q0F32 = `pear://${models[47].hyperdriveKey}/${models[47].modelId}`;
566
+ export const MARIAN_OPUS_IT_DE_Q0F32 = `pear://${models[48].hyperdriveKey}/${models[48].modelId}`;
567
+ export const MARIAN_OPUS_IT_EN_Q0F32 = `pear://${models[49].hyperdriveKey}/${models[49].modelId}`;
568
+ export const MARIAN_OPUS_IT_ES_Q0F32 = `pear://${models[50].hyperdriveKey}/${models[50].modelId}`;
569
+ export const MARIAN_OPUS_EN_RU_Q0F16 = `pear://${models[51].hyperdriveKey}/${models[51].modelId}`;
570
+ export const MARIAN_OPUS_RU_EN_Q0F16 = `pear://${models[52].hyperdriveKey}/${models[52].modelId}`;
571
+ export const MARIAN_OPUS_EN_RU_Q0F32 = `pear://${models[53].hyperdriveKey}/${models[53].modelId}`;
572
+ export const MARIAN_OPUS_RU_EN_Q0F32 = `pear://${models[54].hyperdriveKey}/${models[54].modelId}`;
573
+ export const MARIAN_OPUS_EN_RU_Q4_0 = `pear://${models[55].hyperdriveKey}/${models[55].modelId}`;
574
+ export const MARIAN_OPUS_RU_EN_Q4_0 = `pear://${models[56].hyperdriveKey}/${models[56].modelId}`;
575
+ export const MARIAN_OPUS_EN_JA_Q4F16_1 = `pear://${models[57].hyperdriveKey}/${models[57].modelId}`;
576
+ export const MARIAN_OPUS_JA_EN_Q4F16_1 = `pear://${models[58].hyperdriveKey}/${models[58].modelId}`;
577
+ export const VAD_SILERO_5_1_2 = `pear://${models[59].hyperdriveKey}/${models[59].modelId}`;
578
+ export const WHISPER_LARGE_3 = `pear://${models[60].hyperdriveKey}/${models[60].modelId}`;
579
+ export const WHISPER_SMALL = `pear://${models[61].hyperdriveKey}/${models[61].modelId}`;
580
+ export const WHISPER_TINY = `pear://${models[62].hyperdriveKey}/${models[62].modelId}`;
581
+ export const WHISPER_TINY_SILERO = `pear://${models[63].hyperdriveKey}/${models[63].modelId}`;
528
582
  // Helper function for our curated model list
529
583
  export function getModelBySrc(modelId, hyperdriveKey) {
530
- if (hyperdriveKey) {
531
- return models.find((model) => model.modelId === modelId && model.hyperdriveKey === hyperdriveKey);
532
- }
533
- return models.find((model) => model.modelId === modelId);
584
+ return models.find((model) => model.modelId === modelId && model.hyperdriveKey === hyperdriveKey);
534
585
  }
@@ -32,6 +32,7 @@ export declare const requestSchema: z.ZodUnion<readonly [z.ZodObject<{
32
32
  frequency_penalty: z.ZodOptional<z.ZodNumber>;
33
33
  repeat_penalty: z.ZodOptional<z.ZodNumber>;
34
34
  reverse_prompt: z.ZodOptional<z.ZodString>;
35
+ n_discarded: z.ZodOptional<z.ZodNumber>;
35
36
  }, z.core.$strip>;
36
37
  }, z.core.$strip>, z.ZodObject<{
37
38
  type: z.ZodLiteral<"loadModel">;
@@ -199,6 +200,7 @@ export declare const requestSchema: z.ZodUnion<readonly [z.ZodObject<{
199
200
  frequency_penalty?: number | undefined;
200
201
  repeat_penalty?: number | undefined;
201
202
  reverse_prompt?: string | undefined;
203
+ n_discarded?: number | undefined;
202
204
  };
203
205
  projectionModelSrc?: string | undefined;
204
206
  vadModelSrc?: string | undefined;
@@ -296,6 +298,7 @@ export declare const requestSchema: z.ZodUnion<readonly [z.ZodObject<{
296
298
  frequency_penalty?: number | undefined;
297
299
  repeat_penalty?: number | undefined;
298
300
  reverse_prompt?: string | undefined;
301
+ n_discarded?: number | undefined;
299
302
  };
300
303
  projectionModelSrc?: string | undefined;
301
304
  vadModelSrc?: string | undefined;
@@ -483,6 +486,7 @@ export declare const requestSchema: z.ZodUnion<readonly [z.ZodObject<{
483
486
  paragraph: "paragraph";
484
487
  }>>;
485
488
  splitStrategy: z.ZodOptional<z.ZodEnum<{
489
+ token: "token";
486
490
  character: "character";
487
491
  word: "word";
488
492
  sentence: "sentence";
@@ -21,6 +21,7 @@ export declare const llmConfigSchema: z.ZodObject<{
21
21
  frequency_penalty: z.ZodOptional<z.ZodNumber>;
22
22
  repeat_penalty: z.ZodOptional<z.ZodNumber>;
23
23
  reverse_prompt: z.ZodOptional<z.ZodString>;
24
+ n_discarded: z.ZodOptional<z.ZodNumber>;
24
25
  }, z.core.$strip>;
25
26
  export declare const embedConfigSchema: z.ZodObject<{
26
27
  config: z.ZodDefault<z.ZodString>;
@@ -32,8 +32,11 @@ export const llmConfigSchema = z.object({
32
32
  frequency_penalty: z.number().optional(),
33
33
  repeat_penalty: z.number().optional(),
34
34
  reverse_prompt: z.string().optional(),
35
+ n_discarded: z.number().optional(),
35
36
  });
36
37
  export const embedConfigSchema = z.object({
37
38
  // https://github.com/tetherto/qvac-lib-infer-llamacpp-embed/tree/main?tab=readme-ov-file#4-create-config
38
- config: z.string().default("-ngl\t25"),
39
+ config: z
40
+ .string()
41
+ .default("-ngl\t99\n-dev\tgpu\n--embd-separator\t⟪§§§EMBED_SEP§§§⟫\n-c\t512"),
39
42
  });
@@ -19,6 +19,7 @@ export declare const loadModelOptionsSchema: z.ZodPipe<z.ZodUnion<readonly [z.Zo
19
19
  frequency_penalty: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
20
20
  repeat_penalty: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
21
21
  reverse_prompt: z.ZodOptional<z.ZodOptional<z.ZodString>>;
22
+ n_discarded: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
22
23
  }, z.core.$strict>>;
23
24
  seed: z.ZodOptional<z.ZodBoolean>;
24
25
  projectionModelSrc: z.ZodOptional<z.ZodString>;
@@ -187,6 +188,7 @@ export declare const loadModelOptionsSchema: z.ZodPipe<z.ZodUnion<readonly [z.Zo
187
188
  frequency_penalty?: number | undefined;
188
189
  repeat_penalty?: number | undefined;
189
190
  reverse_prompt?: string | undefined;
191
+ n_discarded?: number | undefined;
190
192
  } | undefined;
191
193
  projectionModelSrc?: string | undefined;
192
194
  delegate?: {
@@ -271,6 +273,7 @@ export declare const loadModelOptionsSchema: z.ZodPipe<z.ZodUnion<readonly [z.Zo
271
273
  frequency_penalty?: number | undefined;
272
274
  repeat_penalty?: number | undefined;
273
275
  reverse_prompt?: string | undefined;
276
+ n_discarded?: number | undefined;
274
277
  } | undefined;
275
278
  seed?: boolean | undefined;
276
279
  projectionModelSrc?: string | undefined;
@@ -370,6 +373,7 @@ export declare const loadLlmModelRequestSchema: z.ZodObject<{
370
373
  frequency_penalty: z.ZodOptional<z.ZodNumber>;
371
374
  repeat_penalty: z.ZodOptional<z.ZodNumber>;
372
375
  reverse_prompt: z.ZodOptional<z.ZodString>;
376
+ n_discarded: z.ZodOptional<z.ZodNumber>;
373
377
  }, z.core.$strip>;
374
378
  }, z.core.$strip>;
375
379
  export declare const loadWhisperModelRequestSchema: z.ZodObject<{
@@ -550,6 +554,7 @@ export declare const loadModelRequestSchema: z.ZodPipe<z.ZodDiscriminatedUnion<[
550
554
  frequency_penalty: z.ZodOptional<z.ZodNumber>;
551
555
  repeat_penalty: z.ZodOptional<z.ZodNumber>;
552
556
  reverse_prompt: z.ZodOptional<z.ZodString>;
557
+ n_discarded: z.ZodOptional<z.ZodNumber>;
553
558
  }, z.core.$strip>;
554
559
  }, z.core.$strip>, z.ZodObject<{
555
560
  type: z.ZodLiteral<"loadModel">;
@@ -717,6 +722,7 @@ export declare const loadModelRequestSchema: z.ZodPipe<z.ZodDiscriminatedUnion<[
717
722
  frequency_penalty?: number | undefined;
718
723
  repeat_penalty?: number | undefined;
719
724
  reverse_prompt?: string | undefined;
725
+ n_discarded?: number | undefined;
720
726
  };
721
727
  projectionModelSrc?: string | undefined;
722
728
  vadModelSrc?: string | undefined;
@@ -814,6 +820,7 @@ export declare const loadModelRequestSchema: z.ZodPipe<z.ZodDiscriminatedUnion<[
814
820
  frequency_penalty?: number | undefined;
815
821
  repeat_penalty?: number | undefined;
816
822
  reverse_prompt?: string | undefined;
823
+ n_discarded?: number | undefined;
817
824
  };
818
825
  projectionModelSrc?: string | undefined;
819
826
  vadModelSrc?: string | undefined;
@@ -932,6 +939,7 @@ export declare const loadModelServerParamsSchema: z.ZodObject<{
932
939
  frequency_penalty: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
933
940
  repeat_penalty: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
934
941
  reverse_prompt: z.ZodOptional<z.ZodOptional<z.ZodString>>;
942
+ n_discarded: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
935
943
  }, z.core.$strict>>;
936
944
  seed: z.ZodOptional<z.ZodBoolean>;
937
945
  projectionModelSrc: z.ZodOptional<z.ZodString>;
@@ -1100,6 +1108,7 @@ export declare const loadModelServerParamsSchema: z.ZodObject<{
1100
1108
  frequency_penalty?: number | undefined;
1101
1109
  repeat_penalty?: number | undefined;
1102
1110
  reverse_prompt?: string | undefined;
1111
+ n_discarded?: number | undefined;
1103
1112
  } | undefined;
1104
1113
  projectionModelSrc?: string | undefined;
1105
1114
  delegate?: {
@@ -1184,6 +1193,7 @@ export declare const loadModelServerParamsSchema: z.ZodObject<{
1184
1193
  frequency_penalty?: number | undefined;
1185
1194
  repeat_penalty?: number | undefined;
1186
1195
  reverse_prompt?: string | undefined;
1196
+ n_discarded?: number | undefined;
1187
1197
  } | undefined;
1188
1198
  seed?: boolean | undefined;
1189
1199
  projectionModelSrc?: string | undefined;
@@ -25,6 +25,7 @@ declare const ragSaveEmbeddingsParamsSchema: z.ZodObject<{
25
25
  paragraph: "paragraph";
26
26
  }>>;
27
27
  splitStrategy: z.ZodOptional<z.ZodEnum<{
28
+ token: "token";
28
29
  character: "character";
29
30
  word: "word";
30
31
  sentence: "sentence";
@@ -45,6 +46,7 @@ export declare const ragSaveEmbeddingsOperationSchema: z.ZodObject<{
45
46
  paragraph: "paragraph";
46
47
  }>>;
47
48
  splitStrategy: z.ZodOptional<z.ZodEnum<{
49
+ token: "token";
48
50
  character: "character";
49
51
  word: "word";
50
52
  sentence: "sentence";
@@ -95,6 +97,7 @@ export declare const ragRequestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
95
97
  paragraph: "paragraph";
96
98
  }>>;
97
99
  splitStrategy: z.ZodOptional<z.ZodEnum<{
100
+ token: "token";
98
101
  character: "character";
99
102
  word: "word";
100
103
  sentence: "sentence";
@@ -4,7 +4,9 @@ const llmChunkOptsSchema = z.object({
4
4
  chunkSize: z.number().optional(),
5
5
  chunkOverlap: z.number().optional(),
6
6
  chunkStrategy: z.enum(["character", "paragraph"]).optional(),
7
- splitStrategy: z.enum(["character", "word", "sentence", "line"]).optional(),
7
+ splitStrategy: z
8
+ .enum(["character", "word", "token", "sentence", "line"])
9
+ .optional(),
8
10
  });
9
11
  const ragSaveEmbeddingsResultSchema = z.object({
10
12
  status: z.enum(["fulfilled", "rejected"]),
@@ -54,8 +54,34 @@ function prepareMessagesForCache(cachePathToUse, cacheExists, history) {
54
54
  }
55
55
  async function* processModelResponse(model, messagesToSend, shouldSaveCache) {
56
56
  const response = await model.run(messagesToSend);
57
- for await (const token of response.iterate()) {
58
- yield token;
57
+ // Create a promise that rejects when onError is triggered
58
+ let rejectOnError = null;
59
+ const errorPromise = new Promise((_, reject) => {
60
+ rejectOnError = reject;
61
+ });
62
+ response.onError((error) => {
63
+ if (rejectOnError) {
64
+ rejectOnError(error);
65
+ }
66
+ });
67
+ const iterator = response.iterate();
68
+ try {
69
+ while (true) {
70
+ // Race between getting the next token and an error occurring
71
+ const result = await Promise.race([iterator.next(), errorPromise]);
72
+ if (result.done) {
73
+ break;
74
+ }
75
+ yield result.value;
76
+ }
77
+ }
78
+ catch (error) {
79
+ if (error instanceof Error) {
80
+ throw error;
81
+ }
82
+ else {
83
+ throw new Error(String(error));
84
+ }
59
85
  }
60
86
  if (shouldSaveCache) {
61
87
  await model.run([{ role: "session", content: "save" }]);
@@ -8,6 +8,7 @@ export interface AnyModel {
8
8
  onUpdate(callback: (data: string) => void): {
9
9
  await: () => Promise<void>;
10
10
  };
11
+ onError(callback: (error: Error) => void): void;
11
12
  onUpdate(callback: (data: Array<{
12
13
  text: string;
13
14
  }>) => void): {
@@ -1,52 +1,38 @@
1
1
  import { completion } from "../../bare/addons/llamacpp/index.js";
2
2
  export async function* handleCompletionStream(request) {
3
- try {
4
- // Log tools if provided
5
- if (request.tools) {
6
- console.log("Tools passed to completionStream:", request.tools);
3
+ const filteredHistory = request.history.map(({ role, content, attachments }) => ({
4
+ role,
5
+ content,
6
+ attachments: attachments ?? [],
7
+ }));
8
+ const stream = completion({
9
+ history: filteredHistory,
10
+ modelId: request.modelId,
11
+ kvCache: request.kvCache,
12
+ });
13
+ let stats;
14
+ let done = false;
15
+ let buffer = "";
16
+ while (!done) {
17
+ const result = await stream.next();
18
+ if (result.done) {
19
+ stats = result.value;
20
+ done = true;
7
21
  }
8
- const filteredHistory = request.history.map(({ role, content, attachments }) => ({
9
- role,
10
- content,
11
- attachments: attachments ?? [],
12
- }));
13
- const stream = completion({
14
- history: filteredHistory,
15
- modelId: request.modelId,
16
- kvCache: request.kvCache,
17
- });
18
- let stats;
19
- let done = false;
20
- let buffer = "";
21
- while (!done) {
22
- const result = await stream.next();
23
- if (result.done) {
24
- stats = result.value;
25
- done = true;
26
- }
27
- else {
28
- buffer += result.value;
29
- if (request.stream) {
30
- yield {
31
- type: "completionStream",
32
- token: result.value,
33
- };
34
- }
22
+ else {
23
+ buffer += result.value;
24
+ if (request.stream) {
25
+ yield {
26
+ type: "completionStream",
27
+ token: result.value,
28
+ };
35
29
  }
36
30
  }
37
- yield {
38
- type: "completionStream",
39
- token: buffer,
40
- done: true,
41
- stats,
42
- };
43
- }
44
- catch (error) {
45
- console.error("Error during completion stream:", error);
46
- yield {
47
- type: "completionStream",
48
- token: "",
49
- error: error instanceof Error ? error.message : "Unknown error",
50
- };
51
31
  }
32
+ yield {
33
+ type: "completionStream",
34
+ token: buffer,
35
+ done: true,
36
+ stats,
37
+ };
52
38
  }
@@ -9,9 +9,11 @@ import { handleTranslate } from "./translate";
9
9
  import { handleLoggingStream } from "./logging-stream";
10
10
  import { handleRag } from "./rag";
11
11
  import { cancelHandler } from "./cancelHandler";
12
+ import { handleDeleteCache } from "./delete-cache";
12
13
  export declare const handlers: {
13
14
  completionStream: typeof handleCompletionStream;
14
15
  downloadAsset: typeof handleDownloadAsset;
16
+ deleteCache: typeof handleDeleteCache;
15
17
  loadModel: typeof handleLoadModel;
16
18
  unloadModel: typeof handleUnloadModel;
17
19
  embed: typeof handleEmbed;
@@ -9,9 +9,11 @@ import { handleTranslate } from "./translate.js";
9
9
  import { handleLoggingStream } from "./logging-stream.js";
10
10
  import { handleRag } from "./rag.js";
11
11
  import { cancelHandler } from "./cancelHandler.js";
12
+ import { handleDeleteCache } from "./delete-cache.js";
12
13
  export const handlers = {
13
14
  completionStream: handleCompletionStream,
14
15
  downloadAsset: handleDownloadAsset,
16
+ deleteCache: handleDeleteCache,
15
17
  loadModel: handleLoadModel,
16
18
  unloadModel: handleUnloadModel,
17
19
  embed: handleEmbed,
@@ -4,28 +4,9 @@ export declare const registerDownload: (key: string, entry: DownloadEntry) => vo
4
4
  export declare const unregisterDownload: (key: string) => void;
5
5
  export declare const createHyperdriveDownloadKey: (hyperdriveKey: string, modelFileName: string) => string;
6
6
  export declare const createHttpDownloadKey: (url: string) => string;
7
- export declare const getAllActiveDownloads: () => Map<string, DownloadEntry>;
8
7
  export declare const setClearCacheFlag: (downloadKey: string, clearCache: boolean) => void;
9
8
  export declare const shouldClearCache: (downloadKey: string) => boolean;
10
9
  export declare const clearClearCacheFlag: (downloadKey: string) => void;
11
10
  export declare const createCancelFunction: (downloadKey: string, clearCache?: boolean) => () => void;
12
11
  export declare const cancelAllDownloads: () => void;
13
- export declare const getDownloadStats: () => {
14
- activeCount: number;
15
- downloads: ({
16
- hyperdriveKey: string;
17
- modelFileName: string;
18
- key: string;
19
- startTime: number;
20
- duration: number;
21
- type: "hyperdrive" | "http";
22
- } | {
23
- url: string;
24
- modelPath: string;
25
- key: string;
26
- startTime: number;
27
- duration: number;
28
- type: "hyperdrive" | "http";
29
- })[];
30
- };
31
12
  //# sourceMappingURL=download-manager.d.ts.map
@@ -12,7 +12,6 @@ export const unregisterDownload = (key) => {
12
12
  };
13
13
  export const createHyperdriveDownloadKey = (hyperdriveKey, modelFileName) => `${hyperdriveKey}:${modelFileName}`;
14
14
  export const createHttpDownloadKey = (url) => `http:${url}`;
15
- export const getAllActiveDownloads = () => new Map(activeDownloads);
16
15
  export const setClearCacheFlag = (downloadKey, clearCache) => {
17
16
  if (clearCache) {
18
17
  clearCacheFlags.set(downloadKey, true);
@@ -39,24 +38,6 @@ export const cancelAllDownloads = () => {
39
38
  console.log(`🧹 Cancelling ${activeDownloads.size} active downloads`);
40
39
  Array.from(activeDownloads.keys()).forEach((key) => createCancelFunction(key)());
41
40
  };
42
- export const getDownloadStats = () => ({
43
- activeCount: activeDownloads.size,
44
- downloads: Array.from(activeDownloads.entries()).map(([key, entry]) => ({
45
- key,
46
- startTime: entry.startTime,
47
- duration: Date.now() - entry.startTime,
48
- type: entry.type,
49
- ...(entry.type === "hyperdrive"
50
- ? {
51
- hyperdriveKey: entry.hyperdriveKey,
52
- modelFileName: entry.modelFileName,
53
- }
54
- : {
55
- url: entry.url,
56
- modelPath: entry.modelPath,
57
- }),
58
- })),
59
- });
60
41
  // Register cleanup handlers for graceful shutdown
61
42
  let cleanupRegistered = false;
62
43
  let isCleaningUp = false;
@@ -79,10 +60,14 @@ const registerCleanupHandlers = () => {
79
60
  console.error("❌ Error during download cleanup:", error);
80
61
  }
81
62
  };
82
- process.on("SIGTERM", () => {
83
- void cleanup();
84
- });
85
- process.on("SIGINT", () => {
86
- void cleanup();
87
- });
63
+ let handlingExit = false;
64
+ const exitHandler = async () => {
65
+ if (handlingExit)
66
+ return;
67
+ handlingExit = true;
68
+ await cleanup();
69
+ process.exit(0);
70
+ };
71
+ process.once("SIGTERM", () => void exitHandler());
72
+ process.once("SIGINT", () => void exitHandler());
88
73
  };
@@ -10,24 +10,49 @@ import { getEnv } from "../../../worker.js";
10
10
  import { getModelsCacheDir, generateShortHash } from "../../../utils/index.js";
11
11
  import { getModelBySrc } from "../../../../models/hyperdrive/index.js";
12
12
  import { getActiveDownload, registerDownload, unregisterDownload, createHyperdriveDownloadKey, shouldClearCache, clearClearCacheFlag, } from "./download-manager.js";
13
+ function createProgressHandler(blob, progressCallback, downloadKey, initialBytes = 0) {
14
+ let downloadedBytes = initialBytes;
15
+ return (index, bytes) => {
16
+ if (index >= blob.blockOffset &&
17
+ index < blob.blockOffset + blob.blockLength) {
18
+ downloadedBytes += bytes;
19
+ if (progressCallback && downloadKey) {
20
+ progressCallback({
21
+ type: "modelProgress",
22
+ downloaded: downloadedBytes,
23
+ total: blob.byteLength,
24
+ percentage: blob.byteLength > 0 ? (downloadedBytes / blob.byteLength) * 100 : 0,
25
+ downloadKey,
26
+ });
27
+ }
28
+ }
29
+ };
30
+ }
13
31
  async function setupHyperdrive(hyperdriveKey, corestoreDir) {
14
32
  const corestore = new Corestore(corestoreDir);
15
33
  await corestore.ready();
16
34
  const drive = new Hyperdrive(corestore, Buffer.from(hyperdriveKey, "hex"));
17
35
  await drive.ready();
18
36
  const swarm = new Hyperswarm();
19
- swarm.join(drive.discoveryKey, { server: false, client: true });
37
+ const doneFindingPeers = drive.findingPeers();
20
38
  swarm.on("connection", (connection) => {
21
39
  console.log(`🤝 Connected to peer for hyperdrive download`);
22
40
  drive.replicate(connection);
23
41
  });
24
- const doneFindingPeers = drive.findingPeers();
25
- await swarm.flush();
26
- doneFindingPeers();
42
+ swarm.join(drive.discoveryKey, { server: false, client: true });
43
+ swarm.flush().then(doneFindingPeers, doneFindingPeers);
27
44
  return { corestore, drive, swarm, corestoreDir };
28
45
  }
29
46
  async function cleanupHyperdrive(setup) {
30
47
  console.log("🧹 Cleaning up hyperdrive setup");
48
+ if (!setup.swarm.suspended) {
49
+ try {
50
+ await setup.swarm.suspend();
51
+ }
52
+ catch {
53
+ // If suspend fails, continue with cleanup
54
+ }
55
+ }
31
56
  await setup.swarm.destroy();
32
57
  await setup.drive.close();
33
58
  await setup.corestore.close();
@@ -42,43 +67,81 @@ export async function deleteCorestoreDirectory(corestoreDir) {
42
67
  }
43
68
  }
44
69
  async function findFileInHyperdrive(drive, modelFileName) {
70
+ if (drive.core.length === 0) {
71
+ // this method will update the length of the core using the first peer it finds
72
+ // this will ensure that the hyperdrive is usable
73
+ await drive.core.update();
74
+ }
45
75
  const paths = [modelFileName, `/${modelFileName}`, `./${modelFileName}`];
46
- let entry = null;
47
- let targetPath = modelFileName;
48
76
  for (const pathVariation of paths) {
49
77
  try {
50
- entry = await drive.entry(pathVariation);
78
+ const entry = await drive.entry(pathVariation, { wait: true });
51
79
  if (entry) {
52
- targetPath = pathVariation;
53
- break;
80
+ return { entry, targetPath: pathVariation };
54
81
  }
55
82
  }
56
83
  catch {
57
84
  // Continue trying other paths
58
85
  }
59
86
  }
60
- if (!entry) {
61
- // Try listing available files to help debug
62
- try {
63
- const rootFiles = drive.list("/", false);
64
- const availableFiles = [];
65
- for await (const file of rootFiles) {
87
+ // If not found, list available files for debugging
88
+ const availableFiles = [];
89
+ try {
90
+ // Try both with and without leading slash
91
+ for (const prefix of ["/", ""]) {
92
+ const files = drive.list(prefix, { recursive: true, wait: true });
93
+ for await (const file of files) {
66
94
  availableFiles.push(file.key);
67
95
  }
68
- if (availableFiles.length === 0) {
69
- // Try without leading slash
70
- const noSlashFiles = drive.list("", false);
71
- for await (const file of noSlashFiles) {
72
- availableFiles.push(file.key);
73
- }
74
- }
75
- throw new Error(`File ${modelFileName} not found in hyperdrive. Available files: ${availableFiles.join(", ")}`);
96
+ if (availableFiles.length > 0)
97
+ break;
76
98
  }
77
- catch (listError) {
78
- throw new Error(`File ${modelFileName} not found in hyperdrive. Could not list available files: ${listError instanceof Error ? listError.message : String(listError)}`);
99
+ }
100
+ catch {
101
+ // Ignore listing errors
102
+ }
103
+ const filesInfo = availableFiles.length > 0
104
+ ? `Available files: ${availableFiles.join(", ")}`
105
+ : "Could not list available files";
106
+ throw new Error(`File ${modelFileName} not found in hyperdrive. ${filesInfo}`);
107
+ }
108
+ async function checkFileDownloaded(drive, entry) {
109
+ const blobs = await drive.getBlobs();
110
+ const blob = entry?.value?.blob;
111
+ if (!blob) {
112
+ return {
113
+ blobs,
114
+ blocksDownloaded: 0,
115
+ totalBlocks: 0,
116
+ totalBytes: 0,
117
+ };
118
+ }
119
+ // Check how many blocks are already downloaded
120
+ let blocksDownloaded = 0;
121
+ for (let i = blob.blockOffset; i < blob.blockOffset + blob.blockLength; i++) {
122
+ const hasBlock = await blobs.core.has(i);
123
+ if (hasBlock) {
124
+ blocksDownloaded++;
79
125
  }
80
126
  }
81
- return { entry, targetPath };
127
+ return {
128
+ blobs,
129
+ blocksDownloaded,
130
+ totalBlocks: blob.blockLength,
131
+ totalBytes: blob.byteLength,
132
+ };
133
+ }
134
+ async function validateFileExistence(drive, file) {
135
+ const { entry, targetPath } = await findFileInHyperdrive(drive, file);
136
+ const { blobs, blocksDownloaded, totalBlocks, totalBytes } = await checkFileDownloaded(drive, entry);
137
+ return {
138
+ entry,
139
+ blobs,
140
+ targetPath,
141
+ blocksDownloaded,
142
+ totalBlocks,
143
+ totalBytes,
144
+ };
82
145
  }
83
146
  async function validateFileChecksum(filePath, expectedChecksum) {
84
147
  console.log(`🔍 Validating SHA256 checksum...`);
@@ -153,13 +216,15 @@ async function performHyperdriveDownload(modelPath, modelFileName, hyperdriveKey
153
216
  }
154
217
  console.log(`Downloading model from hyperdrive ${hyperdriveKey} to ${modelPath}`);
155
218
  const setup = await setupHyperdrive(hyperdriveKey, corestoreDir);
156
- let downloadedBytes = 0;
157
- let totalBytes = 0;
158
219
  // Set up abort handler
159
220
  let readStream;
160
221
  let writeStream;
161
222
  const cleanup = () => {
162
223
  console.log("🛑 Aborting hyperdrive download...");
224
+ setup.swarm.suspended = true;
225
+ setup.swarm.suspend().catch(() => {
226
+ // Ignore errors during emergency suspend
227
+ });
163
228
  // Destroy streams if they exist
164
229
  if (readStream) {
165
230
  readStream.destroy();
@@ -169,48 +234,19 @@ async function performHyperdriveDownload(modelPath, modelFileName, hyperdriveKey
169
234
  }
170
235
  };
171
236
  signal?.addEventListener("abort", cleanup);
237
+ let downloadHandler;
172
238
  try {
173
- const result = await findFileInHyperdrive(setup.drive, modelFileName);
174
- const { entry, targetPath } = result;
175
- totalBytes = entry?.value?.blob?.byteLength || 0;
176
- console.log(`📏 Model size: ${totalBytes} bytes (${(totalBytes / 1024 / 1024).toFixed(2)} MB)`);
177
- // Get blobs and file blob range
178
- const blobs = await setup.drive.getBlobs();
239
+ const { entry, blobs, targetPath, blocksDownloaded, totalBlocks, totalBytes, } = await validateFileExistence(setup.drive, modelFileName);
179
240
  const blob = entry?.value?.blob;
180
241
  if (!blob) {
181
242
  throw new Error(`No blob found for ${modelFileName}`);
182
243
  }
183
- // Check what blocks are already downloaded in corestore for this specific file
184
- let alreadyDownloaded = 0;
185
- for (let i = blob.blockOffset; i < blob.blockOffset + blob.blockLength; i++) {
186
- const hasBlock = await blobs.core.has(i);
187
- if (hasBlock) {
188
- alreadyDownloaded++;
189
- }
190
- }
191
- downloadedBytes = 0;
192
- if (alreadyDownloaded > 0) {
193
- console.log(`📥 Resuming download (${alreadyDownloaded}/${blob.blockLength} blocks already in corestore)`);
194
- }
195
- else {
196
- console.log(`📥 Starting fresh download`);
197
- }
244
+ // Calculate already downloaded bytes for resuming
245
+ const bytesPerBlock = totalBlocks > 0 ? totalBytes / totalBlocks : 0;
246
+ const initialBytes = Math.floor(blocksDownloaded * bytesPerBlock);
198
247
  // Track only downloads for blocks within our file's blob range
199
- blobs.core.on("download", (index, bytes) => {
200
- if (index >= blob.blockOffset &&
201
- index < blob.blockOffset + blob.blockLength) {
202
- downloadedBytes += bytes;
203
- if (progressCallback) {
204
- progressCallback({
205
- type: "modelProgress",
206
- downloaded: downloadedBytes,
207
- total: totalBytes,
208
- percentage: totalBytes > 0 ? (downloadedBytes / totalBytes) * 100 : 0,
209
- downloadKey,
210
- });
211
- }
212
- }
213
- });
248
+ downloadHandler = createProgressHandler(blob, progressCallback, downloadKey, initialBytes);
249
+ blobs.core.on("download", downloadHandler);
214
250
  // Check if aborted before starting streams
215
251
  if (signal?.aborted) {
216
252
  throw new Error("Download cancelled");
@@ -223,15 +259,13 @@ async function performHyperdriveDownload(modelPath, modelFileName, hyperdriveKey
223
259
  readStream.pipe(writeStream);
224
260
  // Wait for download to complete
225
261
  await new Promise((resolve, reject) => {
226
- writeStream.on("finish", () => resolve(undefined));
262
+ writeStream.on("finish", resolve);
227
263
  writeStream.on("error", reject);
228
264
  readStream.on("error", reject);
229
265
  // Also reject on abort
230
- if (signal) {
231
- signal.addEventListener("abort", () => {
232
- reject(new Error("Download cancelled"));
233
- }, { once: true });
234
- }
266
+ signal?.addEventListener("abort", () => {
267
+ reject(new Error("Download cancelled"));
268
+ }, { once: true });
235
269
  });
236
270
  console.log(`✅ Model downloaded successfully to ${modelPath}`);
237
271
  // Delete corestore directory after successful download (only when not seeding, to save space)
@@ -249,22 +283,29 @@ async function performHyperdriveDownload(modelPath, modelFileName, hyperdriveKey
249
283
  }
250
284
  finally {
251
285
  signal?.removeEventListener("abort", cleanup);
286
+ if (downloadHandler) {
287
+ try {
288
+ const { blobs } = await validateFileExistence(setup.drive, modelFileName);
289
+ blobs.core.off("download", downloadHandler);
290
+ }
291
+ catch {
292
+ // If we can't get blobs, setup is already closed
293
+ }
294
+ }
252
295
  if (!seed) {
253
296
  await cleanupHyperdrive(setup);
254
297
  }
255
298
  // Only delete corestore and partial file if user explicitly requested clearCache
256
- if (signal?.aborted) {
257
- if (shouldClearCache(downloadKey)) {
258
- try {
259
- await fsPromises.unlink(modelPath);
260
- }
261
- catch {
262
- // no-op
263
- }
264
- await deleteCorestoreDirectory(corestoreDir);
299
+ if (signal?.aborted && shouldClearCache(downloadKey)) {
300
+ try {
301
+ await fsPromises.unlink(modelPath);
302
+ }
303
+ catch {
304
+ // no-op
265
305
  }
266
- clearClearCacheFlag(downloadKey);
306
+ await deleteCorestoreDirectory(corestoreDir);
267
307
  }
308
+ clearClearCacheFlag(downloadKey);
268
309
  }
269
310
  }
270
311
  export async function downloadModelFromHyperdrive(hyperdriveKey, modelFileName, seed, progressCallback, expectedChecksum) {
@@ -1,46 +1,10 @@
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
- }
44
8
  /**
45
9
  * Resolves a local file path or cached file
46
10
  */
@@ -84,10 +48,7 @@ export async function resolveModelPath(modelSrc, progressCallback, seed) {
84
48
  let actualPath;
85
49
  // Validate seeding is only used with hyperdrive models
86
50
  if (seed && !hyperdriveKey) {
87
- const model = getModelBySrc(actualModelSrc);
88
- if (!model) {
89
- throw new Error("Seeding is only supported for hyperdrive models");
90
- }
51
+ throw new Error("Seeding is only supported for hyperdrive models");
91
52
  }
92
53
  // Check if it's an HTTP/HTTPS URL
93
54
  if (actualModelSrc.startsWith("http://") ||
@@ -101,21 +62,13 @@ export async function resolveModelPath(modelSrc, progressCallback, seed) {
101
62
  console.log(`Loading from hyperdrive: ${hyperdriveKey}`);
102
63
  actualPath = await downloadModelFromHyperdrive(hyperdriveKey, actualModelSrc, seed, progressCallback);
103
64
  }
65
+ else if (actualModelSrc.includes("/") || actualModelSrc.includes("\\")) {
66
+ // Handle file paths (absolute or relative with slashes)
67
+ actualPath = actualModelSrc;
68
+ }
104
69
  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
- }
70
+ // Handle local files and cached files
71
+ actualPath = await resolveLocalOrCachedFile(actualModelSrc);
119
72
  }
120
73
  return actualPath;
121
74
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qvac/sdk",
3
- "version": "0.2.1-dev.1760851161.68dc306",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -45,7 +45,7 @@
45
45
  "bare:ensureprebuilds:whispercpp": "cp -r node_modules/@qvac/transcription-whispercpp/prebuilds/android-arm64 node_modules/@qvac/transcription-whispercpp/prebuilds/android-ia32 && cp -r node_modules/@qvac/transcription-whispercpp/prebuilds/android-arm64 node_modules/@qvac/transcription-whispercpp/prebuilds/android-arm && cp -r node_modules/@qvac/transcription-whispercpp/prebuilds/android-arm64 node_modules/@qvac/transcription-whispercpp/prebuilds/android-x64",
46
46
  "bare:ensureprebuilds:embeddings": "cp -r node_modules/@qvac/embed-llamacpp/prebuilds/android-arm64 node_modules/@qvac/embed-llamacpp/prebuilds/android-ia32 && cp -r node_modules/@qvac/embed-llamacpp/prebuilds/android-arm64 node_modules/@qvac/embed-llamacpp/prebuilds/android-arm && cp -r node_modules/@qvac/embed-llamacpp/prebuilds/android-arm64 node_modules/@qvac/embed-llamacpp/prebuilds/android-x64",
47
47
  "bare:ensureprebuilds": "bun run bare:ensureprebuilds:llamacpp && bun run bare:ensureprebuilds:whispercpp && bun run bare:ensureprebuilds:embeddings",
48
- "prepare": "bun run husky",
48
+ "prepare:husky": "bun run husky",
49
49
  "bare:example": "./scripts/run-with-bare.sh",
50
50
  "docs_api:website": "typedoc --out ./docs/api/website --entryPoints index.ts --entryPointStrategy expand --readme none",
51
51
  "docs_api:markdown": "typedoc --plugin typedoc-plugin-markdown --out ./docs/api/markdown --entryPoints index.ts --entryPointStrategy expand --readme none && sed -i '1,4d' ./docs/api/markdown/README.md",
@@ -53,13 +53,13 @@
53
53
  "update-models": "node ./scripts/update-models.js"
54
54
  },
55
55
  "dependencies": {
56
- "@qvac/embed-llamacpp": "^0.1.0",
57
- "@qvac/llm-llamacpp": "^0.2.2",
56
+ "@qvac/embed-llamacpp": "^0.3.1",
57
+ "@qvac/llm-llamacpp": "^0.3.2",
58
58
  "@qvac/decoder-audio": "^0.1.0",
59
59
  "@qvac/error": "^0.1.0",
60
60
  "@qvac/langdetect-text": "^0.1.0",
61
61
  "@qvac/logging": "^0.1.0",
62
- "@qvac/rag": "^0.1.0",
62
+ "@qvac/rag": "^0.2.1",
63
63
  "@qvac/transcription-whispercpp": "^0.1.4",
64
64
  "@qvac/translation-nmtcpp": "^0.1.0",
65
65
  "fast-safe-stringify": "2.1.1",
@@ -126,4 +126,4 @@
126
126
  "patchedDependencies": {
127
127
  "bare-rpc@0.2.11": "patches/bare-rpc@0.2.11.patch"
128
128
  }
129
- }
129
+ }