@qvac/sdk 0.11.0 → 0.12.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.
- package/NOTICE +1427 -39
- package/README.md +2 -0
- package/dist/client/api/classify.d.ts +23 -0
- package/dist/client/api/classify.js +43 -0
- package/dist/client/api/get-model-info.d.ts +1 -1
- package/dist/client/api/index.d.ts +4 -0
- package/dist/client/api/index.js +4 -0
- package/dist/client/api/load-model.js +24 -1
- package/dist/client/api/transcribe.d.ts +3 -0
- package/dist/client/api/transcribe.js +13 -2
- package/dist/client/api/video.d.ts +64 -0
- package/dist/client/api/video.js +147 -0
- package/dist/client/api/vla-helpers.d.ts +45 -0
- package/dist/client/api/vla-helpers.js +130 -0
- package/dist/client/api/vla.d.ts +65 -0
- package/dist/client/api/vla.js +109 -0
- package/dist/client/config-loader/resolve-config.node.d.ts +16 -0
- package/dist/client/config-loader/resolve-config.node.js +77 -23
- package/dist/client/plugins-factory.d.ts +8 -0
- package/dist/client/plugins-factory.js +10 -0
- package/dist/client/rpc/bare-client.js +62 -66
- package/dist/client/rpc/ensure-worker-ready.d.ts +9 -0
- package/dist/client/rpc/ensure-worker-ready.js +17 -0
- package/dist/client/rpc/node-rpc-client.js +4 -1
- package/dist/client/rpc/rpc-error.js +14 -1
- package/dist/commands/bundle/bare-pack.d.ts +13 -0
- package/dist/commands/bundle/bare-pack.js +54 -0
- package/dist/commands/bundle/constants.d.ts +7 -0
- package/dist/commands/bundle/constants.js +23 -0
- package/dist/commands/bundle/entry-gen.d.ts +2 -0
- package/dist/commands/bundle/entry-gen.js +48 -0
- package/dist/commands/bundle/index.d.ts +20 -0
- package/dist/commands/bundle/index.js +141 -0
- package/dist/commands/bundle/manifest.d.ts +21 -0
- package/dist/commands/bundle/manifest.js +193 -0
- package/dist/commands/bundle/plugins.d.ts +9 -0
- package/dist/commands/bundle/plugins.js +51 -0
- package/dist/commands/index.d.ts +5 -0
- package/dist/commands/index.js +2 -0
- package/dist/commands/verify/abi.d.ts +52 -0
- package/dist/commands/verify/abi.js +125 -0
- package/dist/commands/verify/addon-source.d.ts +43 -0
- package/dist/commands/verify/addon-source.js +75 -0
- package/dist/commands/verify/bundle-source.d.ts +12 -0
- package/dist/commands/verify/bundle-source.js +53 -0
- package/dist/commands/verify/index.d.ts +59 -0
- package/dist/commands/verify/index.js +371 -0
- package/dist/commands/verify/node-modules-source.d.ts +11 -0
- package/dist/commands/verify/node-modules-source.js +76 -0
- package/dist/commands/verify/prebuilds.d.ts +15 -0
- package/dist/commands/verify/prebuilds.js +39 -0
- package/dist/examples/classification/classify-image.d.ts +2 -0
- package/dist/examples/classification/classify-image.js +23 -0
- package/dist/examples/diffusion-txt2vid.d.ts +2 -0
- package/dist/examples/diffusion-txt2vid.js +81 -0
- package/dist/examples/plugins.js +3 -7
- package/dist/examples/tools/llamacpp-tools-gemma4.js +2 -5
- package/dist/examples/tools/llamacpp-tools-qwen35.js +2 -3
- package/dist/examples/transcription/parakeet-ctc-filesystem.js +18 -12
- package/dist/examples/transcription/parakeet-microphone-record.js +7 -12
- package/dist/examples/transcription/parakeet-microphone-stream.d.ts +2 -0
- package/dist/examples/transcription/parakeet-microphone-stream.js +79 -0
- package/dist/examples/transcription/parakeet-sortformer-streaming.d.ts +2 -0
- package/dist/examples/transcription/parakeet-sortformer-streaming.js +121 -0
- package/dist/examples/transcription/parakeet-sortformer.js +58 -55
- package/dist/examples/transcription/parakeet-tdt-filesystem.js +18 -15
- package/dist/examples/transcription/whispercpp-microphone-conversation.js +6 -1
- package/dist/examples/tts/chatterbox.js +7 -16
- package/dist/examples/tts/llm-to-tts-streaming.js +3 -10
- package/dist/examples/tts/supertonic-multilingual.js +4 -12
- package/dist/examples/tts/supertonic.js +5 -12
- package/dist/examples/vla-smolvla.d.ts +2 -0
- package/dist/examples/vla-smolvla.js +75 -0
- package/dist/examples/voice-assistant/voice-assistant.js +3 -10
- package/dist/expo/plugins/find-in-ancestor-node-modules.d.ts +14 -0
- package/dist/expo/plugins/find-in-ancestor-node-modules.js +24 -0
- package/dist/expo/plugins/get-project-root.d.ts +22 -0
- package/dist/expo/plugins/get-project-root.js +23 -0
- package/dist/expo/plugins/index.d.ts +4 -0
- package/dist/expo/plugins/index.js +4 -0
- package/dist/expo/plugins/resolve-sdk-package-dir.d.ts +9 -2
- package/dist/expo/plugins/resolve-sdk-package-dir.js +38 -11
- package/dist/expo/plugins/withDeviceInfo.js +2 -1
- package/dist/expo/plugins/withMobileBundle.d.ts +2 -17
- package/dist/expo/plugins/withMobileBundle.js +31 -85
- package/dist/index.d.ts +4 -3
- package/dist/index.js +4 -3
- package/dist/models/registry/models.d.ts +3711 -368
- package/dist/models/registry/models.js +7066 -3562
- package/dist/models/update-models/naming.js +22 -8
- package/dist/pear/pre.js +6 -2
- package/dist/schemas/cancel.d.ts +5 -0
- package/dist/schemas/cancel.js +1 -0
- package/dist/schemas/classification.d.ts +53 -0
- package/dist/schemas/classification.js +33 -0
- package/dist/schemas/common.d.ts +1001 -1739
- package/dist/schemas/common.js +6 -1
- package/dist/schemas/completion-event.d.ts +3 -0
- package/dist/schemas/completion-event.js +1 -0
- package/dist/schemas/completion-stream.d.ts +1 -0
- package/dist/schemas/download-asset.d.ts +13 -3
- package/dist/schemas/engine-addon-map.d.ts +3 -0
- package/dist/schemas/engine-addon-map.js +18 -5
- package/dist/schemas/get-model-info.d.ts +4 -0
- package/dist/schemas/get-model-info.js +2 -0
- package/dist/schemas/index.d.ts +3 -0
- package/dist/schemas/index.js +3 -0
- package/dist/schemas/llamacpp-config.d.ts +12 -2
- package/dist/schemas/load-model.d.ts +6152 -10764
- package/dist/schemas/load-model.js +75 -7
- package/dist/schemas/model-src-utils.d.ts +22 -2
- package/dist/schemas/model-types.d.ts +46 -6
- package/dist/schemas/model-types.js +28 -5
- package/dist/schemas/ocr.d.ts +5 -0
- package/dist/schemas/plugin.d.ts +20 -5
- package/dist/schemas/plugin.js +21 -4
- package/dist/schemas/registry.d.ts +44 -0
- package/dist/schemas/registry.js +5 -0
- package/dist/schemas/reload-config.d.ts +22 -2
- package/dist/schemas/sdcpp-config.d.ts +316 -1
- package/dist/schemas/sdcpp-config.js +232 -33
- package/dist/schemas/sdk-config.d.ts +654 -1324
- package/dist/schemas/sdk-config.js +16 -1
- package/dist/schemas/sdk-errors-client.d.ts +5 -0
- package/dist/schemas/sdk-errors-client.js +26 -1
- package/dist/schemas/sdk-errors-server.d.ts +3 -1
- package/dist/schemas/sdk-errors-server.js +20 -5
- package/dist/schemas/text-to-speech.d.ts +79 -696
- package/dist/schemas/text-to-speech.js +46 -19
- package/dist/schemas/transcription-config.d.ts +37 -226
- package/dist/schemas/transcription-config.js +76 -15
- package/dist/schemas/transcription.d.ts +63 -11
- package/dist/schemas/transcription.js +56 -2
- package/dist/schemas/translation-config.d.ts +60 -10
- package/dist/schemas/vla.d.ts +87 -0
- package/dist/schemas/vla.js +108 -0
- package/dist/scripts/run-unit-tests.js +8 -2
- package/dist/server/bare/ops/transcribe.d.ts +2 -1
- package/dist/server/bare/ops/transcribe.js +59 -34
- package/dist/server/bare/plugins/ggml-classification/ops/classify.d.ts +6 -0
- package/dist/server/bare/plugins/ggml-classification/ops/classify.js +30 -0
- package/dist/server/bare/plugins/ggml-classification/plugin.d.ts +32 -0
- package/dist/server/bare/plugins/ggml-classification/plugin.js +55 -0
- package/dist/server/bare/plugins/ggml-vla/ops/vla-hparams.d.ts +3 -0
- package/dist/server/bare/plugins/ggml-vla/ops/vla-hparams.js +12 -0
- package/dist/server/bare/plugins/ggml-vla/ops/vla-run.d.ts +3 -0
- package/dist/server/bare/plugins/ggml-vla/ops/vla-run.js +75 -0
- package/dist/server/bare/plugins/ggml-vla/plugin.d.ts +54 -0
- package/dist/server/bare/plugins/ggml-vla/plugin.js +57 -0
- package/dist/server/bare/plugins/index.d.ts +3 -1
- package/dist/server/bare/plugins/index.js +3 -1
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +3 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/context-overflow.d.ts +29 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/context-overflow.js +65 -0
- package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +6 -0
- package/dist/server/bare/plugins/llamacpp-completion/plugin.js +26 -0
- package/dist/server/bare/plugins/nmtcpp-translation/plugin.d.ts +25 -0
- package/dist/server/bare/plugins/onnx-ocr/plugin.d.ts +5 -0
- package/dist/server/bare/plugins/parakeet-transcription/plugin.d.ts +67 -246
- package/dist/server/bare/plugins/parakeet-transcription/plugin.js +66 -97
- package/dist/server/bare/plugins/sdcpp-generation/ops/video.d.ts +3 -0
- package/dist/server/bare/plugins/sdcpp-generation/ops/video.js +199 -0
- package/dist/server/bare/plugins/sdcpp-generation/plugin.d.ts +200 -2
- package/dist/server/bare/plugins/sdcpp-generation/plugin.js +61 -8
- package/dist/server/bare/plugins/{onnx-tts → tts-ggml}/ops/text-to-speech-stream.js +2 -15
- package/dist/server/bare/plugins/{onnx-tts → tts-ggml}/ops/text-to-speech.js +2 -1
- package/dist/server/bare/plugins/tts-ggml/plugin.d.ts +75 -0
- package/dist/server/bare/plugins/tts-ggml/plugin.js +189 -0
- package/dist/server/bare/plugins/whispercpp-transcription/plugin.d.ts +29 -4
- package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +12 -1
- package/dist/server/bare/registry/model-config-utils.js +7 -0
- package/dist/server/bare/runtime/request-context.d.ts +1 -1
- package/dist/server/bare/runtime-lifecycle.js +9 -9
- package/dist/server/bare/types/addon-responses.d.ts +1 -0
- package/dist/server/env.js +4 -1
- package/dist/server/plugins/index.d.ts +1 -1
- package/dist/server/plugins/index.js +1 -1
- package/dist/server/plugins/registry.d.ts +1 -0
- package/dist/server/plugins/registry.js +5 -0
- package/dist/server/rpc/handler-registry.js +4 -0
- package/dist/server/rpc/handler-selection.d.ts +9 -0
- package/dist/server/rpc/handler-selection.js +14 -0
- package/dist/server/rpc/handler-utils.js +5 -13
- package/dist/server/rpc/handlers/classify.d.ts +3 -0
- package/dist/server/rpc/handlers/classify.js +4 -0
- package/dist/server/rpc/handlers/index.d.ts +2 -0
- package/dist/server/rpc/handlers/index.js +2 -0
- package/dist/server/rpc/handlers/load-model/handler.js +4 -1
- package/dist/server/rpc/handlers/load-model/resolve.js +9 -0
- package/dist/server/rpc/handlers/video-stream.d.ts +3 -0
- package/dist/server/rpc/handlers/video-stream.js +4 -0
- package/dist/server/rpc/profiling/operation-metrics.js +23 -0
- package/dist/server/utils/config-transform.js +1 -1
- package/dist/server/worker.js +14 -11
- package/dist/utils/errors-client.d.ts +15 -0
- package/dist/utils/errors-client.js +26 -0
- package/dist/utils/errors-server.d.ts +30 -2
- package/dist/utils/errors-server.js +51 -3
- package/package.json +66 -80
- package/dist/server/bare/plugins/onnx-tts/plugin.d.ts +0 -490
- package/dist/server/bare/plugins/onnx-tts/plugin.js +0 -272
- package/dist/server/bare/plugins/onnx-tts/wav-helper.d.ts +0 -14
- package/dist/server/bare/plugins/onnx-tts/wav-helper.js +0 -107
- /package/dist/server/bare/plugins/{onnx-tts → tts-ggml}/ops/text-to-speech-stream.d.ts +0 -0
- /package/dist/server/bare/plugins/{onnx-tts → tts-ggml}/ops/text-to-speech.d.ts +0 -0
|
@@ -1,75 +1,78 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Parakeet Sortformer diarization + TDT transcription
|
|
2
|
+
* Parakeet Sortformer diarization + TDT transcription pipeline.
|
|
3
3
|
*
|
|
4
4
|
* Usage:
|
|
5
|
-
* bun examples/transcription/parakeet-sortformer.ts [sortformer-
|
|
5
|
+
* bun run examples/transcription/parakeet-sortformer.ts [sortformer-gguf] [wav-file]
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* Two-step flow: Sortformer v2.1 diarizes the audio, then TDT transcribes each
|
|
8
|
+
* speaker segment. Defaults to registry GGUFs and
|
|
9
|
+
* `examples/audio/diarization-sample-16k.wav`. For live streaming + AOSC, see
|
|
10
|
+
* `parakeet-sortformer-streaming.ts`.
|
|
11
|
+
*
|
|
12
|
+
* Sample audio is in the QVAC source repo but not the published npm package.
|
|
13
|
+
* Download the default file into `examples/audio/`:
|
|
10
14
|
* https://github.com/tetherto/qvac/blob/main/packages/sdk/examples/audio/diarization-sample-16k.wav
|
|
11
15
|
*/
|
|
12
|
-
import { loadModel, unloadModel, transcribe,
|
|
16
|
+
import { loadModel, unloadModel, transcribe, PARAKEET_TDT_0_6B_V3_Q8_0, PARAKEET_SORTFORMER_4SPK_V2_1_Q8_0, } from "@qvac/sdk";
|
|
13
17
|
import { dirname, join } from "path";
|
|
14
18
|
import { fileURLToPath } from "url";
|
|
15
19
|
import { readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
16
20
|
import { tmpdir } from "os";
|
|
17
21
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
18
22
|
const args = process.argv.slice(2);
|
|
19
|
-
const sortformerSrc = args[0] ??
|
|
23
|
+
const sortformerSrc = args[0] ?? PARAKEET_SORTFORMER_4SPK_V2_1_Q8_0;
|
|
20
24
|
const defaultAudioPath = join(__dirname, "..", "audio", "diarization-sample-16k.wav");
|
|
21
25
|
const audioFilePath = args[1] ?? defaultAudioPath;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
modelId: sfModelId
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
await
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
26
|
+
try {
|
|
27
|
+
// ── Step 1: Diarize with Sortformer ──
|
|
28
|
+
const sfModelId = await loadModel({
|
|
29
|
+
modelSrc: sortformerSrc,
|
|
30
|
+
modelType: "parakeet",
|
|
31
|
+
});
|
|
32
|
+
const diarization = await transcribe({
|
|
33
|
+
modelId: sfModelId,
|
|
34
|
+
audioChunk: audioFilePath,
|
|
35
|
+
});
|
|
36
|
+
await unloadModel({ modelId: sfModelId });
|
|
37
|
+
const segments = parseDiarization(diarization);
|
|
38
|
+
// ── Step 2: Transcribe each segment with TDT ──
|
|
39
|
+
const tdtModelId = await loadModel({
|
|
40
|
+
modelSrc: PARAKEET_TDT_0_6B_V3_Q8_0,
|
|
41
|
+
modelType: "parakeet",
|
|
42
|
+
});
|
|
43
|
+
const pcm = readPcm(audioFilePath);
|
|
44
|
+
const sliceDir = join(tmpdir(), `qvac-diarize-${Date.now()}`);
|
|
45
|
+
mkdirSync(sliceDir, { recursive: true });
|
|
46
|
+
const results = [];
|
|
47
|
+
for (let i = 0; i < segments.length; i++) {
|
|
48
|
+
const seg = segments[i];
|
|
49
|
+
const slicePath = join(sliceDir, `seg-${i}.wav`);
|
|
50
|
+
if (!writeWavSlice(pcm, seg.start, seg.end, slicePath)) {
|
|
51
|
+
results.push({ ...seg, text: "[No speech detected]" });
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const text = await transcribe({
|
|
55
|
+
modelId: tdtModelId,
|
|
56
|
+
audioChunk: slicePath,
|
|
57
|
+
});
|
|
58
|
+
results.push({ ...seg, text: text.trim() || "[No speech detected]" });
|
|
59
|
+
}
|
|
60
|
+
await unloadModel({ modelId: tdtModelId });
|
|
61
|
+
// ── Step 3: Merge consecutive same-speaker segments and print ──
|
|
62
|
+
const merged = mergeSpeakers(results);
|
|
63
|
+
console.log("\n=== DIARIZED TRANSCRIPTION ===");
|
|
64
|
+
console.log("=".repeat(60));
|
|
65
|
+
for (const entry of merged) {
|
|
66
|
+
console.log(`Speaker ${entry.speaker} (${entry.start.toFixed(2)}s - ${entry.end.toFixed(2)}s):`);
|
|
67
|
+
console.log(` ${entry.text}\n`);
|
|
58
68
|
}
|
|
59
|
-
|
|
60
|
-
|
|
69
|
+
console.log("=".repeat(60));
|
|
70
|
+
console.log("\nDone!");
|
|
61
71
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
console.log("\n=== DIARIZED TRANSCRIPTION ===");
|
|
66
|
-
console.log("=".repeat(60));
|
|
67
|
-
for (const entry of merged) {
|
|
68
|
-
console.log(`Speaker ${entry.speaker} (${entry.start.toFixed(2)}s - ${entry.end.toFixed(2)}s):`);
|
|
69
|
-
console.log(` ${entry.text}\n`);
|
|
72
|
+
catch (error) {
|
|
73
|
+
console.error("❌ Error:", error);
|
|
74
|
+
process.exit(1);
|
|
70
75
|
}
|
|
71
|
-
console.log("=".repeat(60));
|
|
72
|
-
console.log("\nDone!");
|
|
73
76
|
// ── Helpers ──
|
|
74
77
|
function parseDiarization(text) {
|
|
75
78
|
const segs = [];
|
|
@@ -1,28 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Parakeet TDT transcription from a WAV file.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* bun run examples/transcription/parakeet-tdt-filesystem.ts <wav-file> [parakeet-tdt-gguf]
|
|
6
|
+
*
|
|
7
|
+
* Loads a single GGUF checkpoint (`PARAKEET_TDT_0_6B_V3_Q8_0` by default) and
|
|
8
|
+
* transcribes the file with the batch `transcribe` API. Omit the model
|
|
9
|
+
* argument to use the registry constant.
|
|
10
|
+
*
|
|
11
|
+
* Audio should be 16 kHz mono PCM in a WAV container.
|
|
12
|
+
*/
|
|
13
|
+
import { loadModel, unloadModel, transcribe, PARAKEET_TDT_0_6B_V3_Q8_0, } from "@qvac/sdk";
|
|
2
14
|
const args = process.argv.slice(2);
|
|
3
15
|
if (!args[0]) {
|
|
4
16
|
console.error("Usage: bun run examples/transcription/parakeet-tdt-filesystem.ts <wav-file-path> " +
|
|
5
|
-
"[
|
|
6
|
-
console.error("\nIf model
|
|
17
|
+
"[parakeet-tdt-gguf]");
|
|
18
|
+
console.error("\nIf the model path is omitted, defaults to the registry model.");
|
|
7
19
|
process.exit(1);
|
|
8
20
|
}
|
|
9
21
|
const audioFilePath = args[0];
|
|
10
|
-
const
|
|
11
|
-
const parakeetDecoderSrc = args[2] ?? PARAKEET_TDT_DECODER_FP32;
|
|
12
|
-
const parakeetVocabSrc = args[3] ?? PARAKEET_TDT_VOCAB;
|
|
13
|
-
const parakeetPreprocessorSrc = args[4] ?? PARAKEET_TDT_PREPROCESSOR_FP32;
|
|
22
|
+
const parakeetModelSrc = args[1] ?? PARAKEET_TDT_0_6B_V3_Q8_0;
|
|
14
23
|
try {
|
|
15
24
|
console.log("Starting Parakeet transcription example...");
|
|
16
25
|
console.log("Loading Parakeet model...");
|
|
17
26
|
const modelId = await loadModel({
|
|
18
|
-
modelSrc:
|
|
27
|
+
modelSrc: parakeetModelSrc,
|
|
19
28
|
modelType: "parakeet",
|
|
20
|
-
modelConfig: {
|
|
21
|
-
parakeetEncoderSrc,
|
|
22
|
-
parakeetDecoderSrc,
|
|
23
|
-
parakeetVocabSrc,
|
|
24
|
-
parakeetPreprocessorSrc,
|
|
25
|
-
},
|
|
26
29
|
onProgress: (progress) => {
|
|
27
30
|
console.log(`Download progress: ${progress.percentage.toFixed(1)}%`);
|
|
28
31
|
},
|
|
@@ -37,6 +40,6 @@ try {
|
|
|
37
40
|
console.log("Parakeet model unloaded successfully");
|
|
38
41
|
}
|
|
39
42
|
catch (error) {
|
|
40
|
-
console.error("Error:", error);
|
|
43
|
+
console.error("❌ Error:", error);
|
|
41
44
|
process.exit(1);
|
|
42
45
|
}
|
|
@@ -90,7 +90,12 @@ try {
|
|
|
90
90
|
}
|
|
91
91
|
break;
|
|
92
92
|
case "endOfTurn":
|
|
93
|
-
|
|
93
|
+
if (event.source === "whisper") {
|
|
94
|
+
console.log(`[endOfTurn] silence ${event.silenceDurationMs}ms — turn complete\n`);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
console.log(`[endOfTurn] turn complete (token-driven EOU)\n`);
|
|
98
|
+
}
|
|
94
99
|
break;
|
|
95
100
|
}
|
|
96
101
|
}
|
|
@@ -1,28 +1,19 @@
|
|
|
1
|
-
import { loadModel, textToSpeech, unloadModel,
|
|
1
|
+
import { loadModel, textToSpeech, unloadModel, TTS_T3_TURBO_EN_CHATTERBOX_Q8_0, TTS_S3GEN_EN_CHATTERBOX, } from "@qvac/sdk";
|
|
2
2
|
import { createWav, playAudio, int16ArrayToBuffer, createWavHeader, } from "./utils.js";
|
|
3
|
-
// Chatterbox TTS: voice cloning with reference audio.
|
|
4
|
-
// Uses registry model constants
|
|
5
|
-
//
|
|
6
|
-
// Usage: node chatterbox-filesystem.js <referenceAudioSrc>
|
|
3
|
+
// Chatterbox TTS (GGML): voice cloning with optional reference audio.
|
|
4
|
+
// Uses registry model constants — downloads automatically from QVAC Registry.
|
|
5
|
+
// Usage: node chatterbox.ts [referenceAudioSrc]
|
|
7
6
|
const [referenceAudioSrc] = process.argv.slice(2);
|
|
8
|
-
if (!referenceAudioSrc) {
|
|
9
|
-
console.error("Usage: node chatterbox-filesystem.js <referenceAudioSrc>");
|
|
10
|
-
process.exit(1);
|
|
11
|
-
}
|
|
12
7
|
const CHATTERBOX_SAMPLE_RATE = 24000;
|
|
13
8
|
try {
|
|
14
9
|
const modelId = await loadModel({
|
|
15
|
-
modelSrc:
|
|
10
|
+
modelSrc: TTS_T3_TURBO_EN_CHATTERBOX_Q8_0.src,
|
|
16
11
|
modelType: "tts",
|
|
17
12
|
modelConfig: {
|
|
18
13
|
ttsEngine: "chatterbox",
|
|
19
14
|
language: "en",
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
ttsEmbedTokensSrc: TTS_EMBED_TOKENS_EN_CHATTERBOX_FP32.src,
|
|
23
|
-
ttsConditionalDecoderSrc: TTS_CONDITIONAL_DECODER_EN_CHATTERBOX_FP32.src,
|
|
24
|
-
ttsLanguageModelSrc: TTS_LANGUAGE_MODEL_EN_CHATTERBOX_FP32.src,
|
|
25
|
-
referenceAudioSrc,
|
|
15
|
+
s3genModelSrc: TTS_S3GEN_EN_CHATTERBOX.src,
|
|
16
|
+
...(referenceAudioSrc ? { referenceAudioSrc } : {}),
|
|
26
17
|
},
|
|
27
18
|
onProgress: (progress) => {
|
|
28
19
|
console.log(progress);
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* Usage:
|
|
13
13
|
* bun run examples/tts/llm-to-tts-streaming.ts
|
|
14
14
|
*/
|
|
15
|
-
import { completion, loadModel, textToSpeechStream, unloadModel, LLAMA_3_2_1B_INST_Q4_0,
|
|
15
|
+
import { completion, loadModel, textToSpeechStream, unloadModel, LLAMA_3_2_1B_INST_Q4_0, TTS_EN_SUPERTONIC_Q8_0, } from "@qvac/sdk";
|
|
16
16
|
import { createWav, playPcmInt16Chunk } from "./utils.js";
|
|
17
17
|
const SUPERTONIC_SAMPLE_RATE = 44100;
|
|
18
18
|
/**
|
|
@@ -69,21 +69,14 @@ try {
|
|
|
69
69
|
console.log(`LLM ready: ${llmModelId}`);
|
|
70
70
|
console.log("Loading Supertonic TTS (registry)…");
|
|
71
71
|
const ttsModelId = await loadModel({
|
|
72
|
-
modelSrc:
|
|
72
|
+
modelSrc: TTS_EN_SUPERTONIC_Q8_0.src,
|
|
73
73
|
modelType: "tts",
|
|
74
74
|
modelConfig: {
|
|
75
75
|
ttsEngine: "supertonic",
|
|
76
76
|
language: "en",
|
|
77
|
+
voice: "F1",
|
|
77
78
|
ttsSpeed: 1.05,
|
|
78
79
|
ttsNumInferenceSteps: 10,
|
|
79
|
-
ttsSupertonicMultilingual: true,
|
|
80
|
-
ttsTextEncoderSrc: TTS_SUPERTONIC2_OFFICIAL_TEXT_ENCODER_SUPERTONE_FP32.src,
|
|
81
|
-
ttsDurationPredictorSrc: TTS_SUPERTONIC2_OFFICIAL_DURATION_PREDICTOR_SUPERTONE_FP32.src,
|
|
82
|
-
ttsVectorEstimatorSrc: TTS_SUPERTONIC2_OFFICIAL_VECTOR_ESTIMATOR_SUPERTONE_FP32.src,
|
|
83
|
-
ttsVocoderSrc: TTS_SUPERTONIC2_OFFICIAL_VOCODER_SUPERTONE_FP32.src,
|
|
84
|
-
ttsUnicodeIndexerSrc: TTS_SUPERTONIC2_OFFICIAL_UNICODE_INDEXER_SUPERTONE_FP32.src,
|
|
85
|
-
ttsTtsConfigSrc: TTS_SUPERTONIC2_OFFICIAL_TTS_CONFIG_SUPERTONE.src,
|
|
86
|
-
ttsVoiceStyleSrc: TTS_SUPERTONIC2_OFFICIAL_VOICE_STYLE_SUPERTONE.src,
|
|
87
80
|
},
|
|
88
81
|
onProgress: (progress) => console.log(`TTS load: ${progress.percentage.toFixed(1)}%`),
|
|
89
82
|
});
|
|
@@ -1,25 +1,17 @@
|
|
|
1
|
-
import { loadModel, textToSpeech, unloadModel,
|
|
1
|
+
import { loadModel, textToSpeech, unloadModel, TTS_MULTILINGUAL_SUPERTONIC2_Q8_0, } from "@qvac/sdk";
|
|
2
2
|
import { createWav, playAudio, int16ArrayToBuffer, createWavHeader, } from "./utils.js";
|
|
3
|
-
// Supertonic TTS:
|
|
4
|
-
// Uses registry model constants - downloads automatically from QVAC Registry.
|
|
3
|
+
// Supertonic 2 TTS (GGML): multilingual synthesis (en/ko/es/pt/fr).
|
|
5
4
|
const SUPERTONIC_SAMPLE_RATE = 44100;
|
|
6
5
|
try {
|
|
7
6
|
const modelId = await loadModel({
|
|
8
|
-
modelSrc:
|
|
7
|
+
modelSrc: TTS_MULTILINGUAL_SUPERTONIC2_Q8_0.src,
|
|
9
8
|
modelType: "tts",
|
|
10
9
|
modelConfig: {
|
|
11
10
|
ttsEngine: "supertonic",
|
|
12
11
|
language: "es",
|
|
12
|
+
voice: "F1",
|
|
13
13
|
ttsSpeed: 1.05,
|
|
14
14
|
ttsNumInferenceSteps: 5,
|
|
15
|
-
ttsSupertonicMultilingual: true, //false for English quality.
|
|
16
|
-
ttsTextEncoderSrc: TTS_SUPERTONIC2_OFFICIAL_TEXT_ENCODER_SUPERTONE_FP32.src,
|
|
17
|
-
ttsDurationPredictorSrc: TTS_SUPERTONIC2_OFFICIAL_DURATION_PREDICTOR_SUPERTONE_FP32.src,
|
|
18
|
-
ttsVectorEstimatorSrc: TTS_SUPERTONIC2_OFFICIAL_VECTOR_ESTIMATOR_SUPERTONE_FP32.src,
|
|
19
|
-
ttsVocoderSrc: TTS_SUPERTONIC2_OFFICIAL_VOCODER_SUPERTONE_FP32.src,
|
|
20
|
-
ttsUnicodeIndexerSrc: TTS_SUPERTONIC2_OFFICIAL_UNICODE_INDEXER_SUPERTONE_FP32.src,
|
|
21
|
-
ttsTtsConfigSrc: TTS_SUPERTONIC2_OFFICIAL_TTS_CONFIG_SUPERTONE.src,
|
|
22
|
-
ttsVoiceStyleSrc: TTS_SUPERTONIC2_OFFICIAL_VOICE_STYLE_SUPERTONE.src,
|
|
23
15
|
},
|
|
24
16
|
onProgress: (progress) => {
|
|
25
17
|
console.log(progress);
|
|
@@ -1,25 +1,18 @@
|
|
|
1
|
-
import { loadModel, textToSpeech, unloadModel,
|
|
1
|
+
import { loadModel, textToSpeech, unloadModel, TTS_EN_SUPERTONIC_Q8_0, } from "@qvac/sdk";
|
|
2
2
|
import { createWav, playAudio, int16ArrayToBuffer, createWavHeader, } from "./utils.js";
|
|
3
|
-
// Supertonic TTS:
|
|
4
|
-
// Uses registry model constants
|
|
3
|
+
// Supertonic TTS (GGML): fast English synthesis with baked-in voices.
|
|
4
|
+
// Uses registry model constants — downloads automatically from QVAC Registry.
|
|
5
5
|
const SUPERTONIC_SAMPLE_RATE = 44100;
|
|
6
6
|
try {
|
|
7
7
|
const modelId = await loadModel({
|
|
8
|
-
modelSrc:
|
|
8
|
+
modelSrc: TTS_EN_SUPERTONIC_Q8_0.src,
|
|
9
9
|
modelType: "tts",
|
|
10
10
|
modelConfig: {
|
|
11
11
|
ttsEngine: "supertonic",
|
|
12
12
|
language: "en",
|
|
13
|
+
voice: "F1",
|
|
13
14
|
ttsSpeed: 1.05,
|
|
14
15
|
ttsNumInferenceSteps: 5,
|
|
15
|
-
ttsSupertonicMultilingual: true,
|
|
16
|
-
ttsTextEncoderSrc: TTS_SUPERTONIC2_OFFICIAL_TEXT_ENCODER_SUPERTONE_FP32.src,
|
|
17
|
-
ttsDurationPredictorSrc: TTS_SUPERTONIC2_OFFICIAL_DURATION_PREDICTOR_SUPERTONE_FP32.src,
|
|
18
|
-
ttsVectorEstimatorSrc: TTS_SUPERTONIC2_OFFICIAL_VECTOR_ESTIMATOR_SUPERTONE_FP32.src,
|
|
19
|
-
ttsVocoderSrc: TTS_SUPERTONIC2_OFFICIAL_VOCODER_SUPERTONE_FP32.src,
|
|
20
|
-
ttsUnicodeIndexerSrc: TTS_SUPERTONIC2_OFFICIAL_UNICODE_INDEXER_SUPERTONE_FP32.src,
|
|
21
|
-
ttsTtsConfigSrc: TTS_SUPERTONIC2_OFFICIAL_TTS_CONFIG_SUPERTONE.src,
|
|
22
|
-
ttsVoiceStyleSrc: TTS_SUPERTONIC2_OFFICIAL_VOICE_STYLE_SUPERTONE.src,
|
|
23
16
|
},
|
|
24
17
|
onProgress: (progress) => {
|
|
25
18
|
console.log(progress);
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SmolVLA (vision-language-action) example using the QVAC SDK.
|
|
3
|
+
*
|
|
4
|
+
* Loads the SmolVLA-LIBERO GGUF model, runs a single inference pass with
|
|
5
|
+
* synthetic inputs (zero-filled gray images + BOS-only tokens + zero state +
|
|
6
|
+
* zero noise), and prints the produced action chunk + per-stage timings.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* bun examples/vla-smolvla.ts [path-to-smolvla.gguf]
|
|
10
|
+
*
|
|
11
|
+
* By default the example pulls the registry-baked SmolVLA-LIBERO GGUF
|
|
12
|
+
* (~1.9 GB) on first run and caches it locally. Pass an absolute path on
|
|
13
|
+
* the command line to override and load a local GGUF instead.
|
|
14
|
+
*/
|
|
15
|
+
import { close, loadModel, SMOLVLA_LIBERO_VISION_Q8, unloadModel, vla, vlaHparams, vlaPadState, vlaPreprocessImage, } from "@qvac/sdk";
|
|
16
|
+
const modelSrcOverride = process.argv[2];
|
|
17
|
+
const modelSrc = modelSrcOverride ?? SMOLVLA_LIBERO_VISION_Q8;
|
|
18
|
+
try {
|
|
19
|
+
console.log("Loading SmolVLA model...");
|
|
20
|
+
const modelId = await loadModel({
|
|
21
|
+
modelSrc,
|
|
22
|
+
modelType: "vla",
|
|
23
|
+
modelConfig: { backend: "cpu" },
|
|
24
|
+
onProgress: (p) => typeof modelSrc === "string"
|
|
25
|
+
? undefined
|
|
26
|
+
: process.stdout.write(`\rDownloading: ${p.percentage.toFixed(1)}%`),
|
|
27
|
+
});
|
|
28
|
+
if (typeof modelSrc !== "string")
|
|
29
|
+
process.stdout.write("\n");
|
|
30
|
+
console.log(`Model loaded: ${modelId}`);
|
|
31
|
+
const { hparams, backendName } = await vlaHparams({ modelId });
|
|
32
|
+
console.log(`Backend: ${backendName ?? "(unknown)"}`);
|
|
33
|
+
console.log("Hparams:", hparams);
|
|
34
|
+
// Build synthetic inputs sized to the model's expectations. A real
|
|
35
|
+
// consumer would: read camera frames, tokenize the instruction with the
|
|
36
|
+
// SmolVLM2 tokenizer, and read the robot's current end-effector pose.
|
|
37
|
+
const size = hparams.visionImageSize;
|
|
38
|
+
const dummyPixels = new Uint8Array(size * size * 3).fill(128);
|
|
39
|
+
const front = vlaPreprocessImage(dummyPixels, size, size, { size });
|
|
40
|
+
const wrist = vlaPreprocessImage(dummyPixels, size, size, { size });
|
|
41
|
+
const tokens = new Int32Array(hparams.tokenizerMaxLength);
|
|
42
|
+
const mask = new Uint8Array(hparams.tokenizerMaxLength);
|
|
43
|
+
// BOS-only "instruction" for the smoke test.
|
|
44
|
+
tokens[0] = 1;
|
|
45
|
+
mask[0] = 1;
|
|
46
|
+
const state = vlaPadState([0, 0, 0, 0, 0, 0], hparams.maxStateDim);
|
|
47
|
+
const noise = new Float32Array(hparams.chunkSize * hparams.maxActionDim);
|
|
48
|
+
console.log("Running VLA inference...");
|
|
49
|
+
const { actions, actionDim, chunkSize, stats } = await vla({
|
|
50
|
+
modelId,
|
|
51
|
+
images: [front, wrist],
|
|
52
|
+
imgWidth: size,
|
|
53
|
+
imgHeight: size,
|
|
54
|
+
state,
|
|
55
|
+
tokens,
|
|
56
|
+
mask,
|
|
57
|
+
noise,
|
|
58
|
+
});
|
|
59
|
+
console.log(`Got ${chunkSize} action steps of dim ${actionDim}.`);
|
|
60
|
+
console.log("First step:", Array.from(actions.subarray(0, actionDim)));
|
|
61
|
+
if (stats) {
|
|
62
|
+
console.log(`Timing: vision=${stats.vision_ms?.toFixed(0)}ms ` +
|
|
63
|
+
`smollm2=${stats.smollm2_total_ms?.toFixed(0)}ms ` +
|
|
64
|
+
`ode=${stats.ode_ms?.toFixed(0)}ms ` +
|
|
65
|
+
`total=${stats.total_ms?.toFixed(0)}ms`);
|
|
66
|
+
}
|
|
67
|
+
await unloadModel({ modelId, clearStorage: false });
|
|
68
|
+
console.log("Model unloaded.");
|
|
69
|
+
process.exit(0);
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
console.error("VLA example failed:", error);
|
|
73
|
+
await close();
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Requirements: FFmpeg installed, microphone access, speakers.
|
|
12
12
|
*/
|
|
13
|
-
import { loadModel, unloadModel, transcribeStream, completion, textToSpeech, WHISPER_TINY, VAD_SILERO_5_1_2, LLAMA_3_2_1B_INST_Q4_0,
|
|
13
|
+
import { loadModel, unloadModel, transcribeStream, completion, textToSpeech, WHISPER_TINY, VAD_SILERO_5_1_2, LLAMA_3_2_1B_INST_Q4_0, TTS_EN_SUPERTONIC_Q8_0, } from "@qvac/sdk";
|
|
14
14
|
import { spawnSync } from "child_process";
|
|
15
15
|
import { startMicrophone } from "../audio/mic-input";
|
|
16
16
|
import { createWavHeader, int16ArrayToBuffer, playAudio } from "../tts/utils";
|
|
@@ -100,21 +100,14 @@ const llmModelId = await loadModel({
|
|
|
100
100
|
});
|
|
101
101
|
console.log("Loading Supertonic TTS...");
|
|
102
102
|
const ttsModelId = await loadModel({
|
|
103
|
-
modelSrc:
|
|
103
|
+
modelSrc: TTS_EN_SUPERTONIC_Q8_0.src,
|
|
104
104
|
modelType: "tts",
|
|
105
105
|
modelConfig: {
|
|
106
106
|
ttsEngine: "supertonic",
|
|
107
107
|
language: "en",
|
|
108
|
+
voice: "F1",
|
|
108
109
|
ttsSpeed: 1.05,
|
|
109
110
|
ttsNumInferenceSteps: 5,
|
|
110
|
-
ttsSupertonicMultilingual: false,
|
|
111
|
-
ttsTextEncoderSrc: TTS_SUPERTONIC2_OFFICIAL_TEXT_ENCODER_SUPERTONE_FP32.src,
|
|
112
|
-
ttsDurationPredictorSrc: TTS_SUPERTONIC2_OFFICIAL_DURATION_PREDICTOR_SUPERTONE_FP32.src,
|
|
113
|
-
ttsVectorEstimatorSrc: TTS_SUPERTONIC2_OFFICIAL_VECTOR_ESTIMATOR_SUPERTONE_FP32.src,
|
|
114
|
-
ttsVocoderSrc: TTS_SUPERTONIC2_OFFICIAL_VOCODER_SUPERTONE_FP32.src,
|
|
115
|
-
ttsUnicodeIndexerSrc: TTS_SUPERTONIC2_OFFICIAL_UNICODE_INDEXER_SUPERTONE_FP32.src,
|
|
116
|
-
ttsTtsConfigSrc: TTS_SUPERTONIC2_OFFICIAL_TTS_CONFIG_SUPERTONE.src,
|
|
117
|
-
ttsVoiceStyleSrc: TTS_SUPERTONIC2_OFFICIAL_VOICE_STYLE_SUPERTONE.src,
|
|
118
111
|
},
|
|
119
112
|
});
|
|
120
113
|
console.log("All models loaded.\n");
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walks from `startDir` up to the filesystem root, returning the first
|
|
3
|
+
* `<dir>/node_modules/<name>` that exists, or `null`. Matches Node's own
|
|
4
|
+
* module resolution so packages hoisted to a monorepo root (e.g. by bun or
|
|
5
|
+
* yarn workspaces) are found from a nested project directory.
|
|
6
|
+
*
|
|
7
|
+
* Use this as the building block for any plugin lookup that historically
|
|
8
|
+
* checked only `<projectRoot>/node_modules`. For SDK resolution specifically
|
|
9
|
+
* use `resolveSDKPackageDir`, which layers multi-package disambiguation and
|
|
10
|
+
* shadowed-copy warnings on top of this.
|
|
11
|
+
*/
|
|
12
|
+
declare function findInAncestorNodeModules(startDir: string, name: string): string | null;
|
|
13
|
+
export { findInAncestorNodeModules };
|
|
14
|
+
//# sourceMappingURL=find-in-ancestor-node-modules.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
/**
|
|
4
|
+
* Walks from `startDir` up to the filesystem root, returning the first
|
|
5
|
+
* `<dir>/node_modules/<name>` that exists, or `null`. Matches Node's own
|
|
6
|
+
* module resolution so packages hoisted to a monorepo root (e.g. by bun or
|
|
7
|
+
* yarn workspaces) are found from a nested project directory.
|
|
8
|
+
*
|
|
9
|
+
* Use this as the building block for any plugin lookup that historically
|
|
10
|
+
* checked only `<projectRoot>/node_modules`. For SDK resolution specifically
|
|
11
|
+
* use `resolveSDKPackageDir`, which layers multi-package disambiguation and
|
|
12
|
+
* shadowed-copy warnings on top of this.
|
|
13
|
+
*/
|
|
14
|
+
function findInAncestorNodeModules(startDir, name) {
|
|
15
|
+
let dir = startDir;
|
|
16
|
+
let parent = path.dirname(dir);
|
|
17
|
+
for (; dir !== parent; dir = parent, parent = path.dirname(dir)) {
|
|
18
|
+
const candidate = path.join(dir, "node_modules", name);
|
|
19
|
+
if (fs.existsSync(candidate))
|
|
20
|
+
return candidate;
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
export { findInAncestorNodeModules };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ExportedConfigWithProps } from "@expo/config-plugins";
|
|
2
|
+
import type { ExpoConfig } from "expo/config";
|
|
3
|
+
/**
|
|
4
|
+
* `projectRoot` resolution in Expo plugins depends on plugin type:
|
|
5
|
+
*
|
|
6
|
+
* - **Mod plugins** (callbacks passed to `withDangerousMod` etc.) receive an
|
|
7
|
+
* `ExportedConfigWithProps<...>` whose `modRequest.projectRoot` is the
|
|
8
|
+
* documented public API for the consumer's project directory.
|
|
9
|
+
* - **Base plugins** (called with the bare `ExpoConfig`) run before any mod
|
|
10
|
+
* cycle and have no `modRequest`. The only way to recover the project root
|
|
11
|
+
* is the (undocumented but stable) `_internal.projectRoot` escape hatch
|
|
12
|
+
* Expo's config-plugins runtime attaches to the config it hands plugins.
|
|
13
|
+
*
|
|
14
|
+
* Both helpers exist so the two access patterns are picked deliberately —
|
|
15
|
+
* call the one that matches the plugin shape you're in. Don't reach into the
|
|
16
|
+
* raw fields directly; that's how `withMobileBundle` and `withDeviceInfo`
|
|
17
|
+
* silently disagreed on which directory they were resolving against.
|
|
18
|
+
*/
|
|
19
|
+
declare function getProjectRootFromMod(config: ExportedConfigWithProps<unknown>): string;
|
|
20
|
+
declare function getProjectRootFromBaseConfig(config: ExpoConfig): string | undefined;
|
|
21
|
+
export { getProjectRootFromMod, getProjectRootFromBaseConfig };
|
|
22
|
+
//# sourceMappingURL=get-project-root.d.ts.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `projectRoot` resolution in Expo plugins depends on plugin type:
|
|
3
|
+
*
|
|
4
|
+
* - **Mod plugins** (callbacks passed to `withDangerousMod` etc.) receive an
|
|
5
|
+
* `ExportedConfigWithProps<...>` whose `modRequest.projectRoot` is the
|
|
6
|
+
* documented public API for the consumer's project directory.
|
|
7
|
+
* - **Base plugins** (called with the bare `ExpoConfig`) run before any mod
|
|
8
|
+
* cycle and have no `modRequest`. The only way to recover the project root
|
|
9
|
+
* is the (undocumented but stable) `_internal.projectRoot` escape hatch
|
|
10
|
+
* Expo's config-plugins runtime attaches to the config it hands plugins.
|
|
11
|
+
*
|
|
12
|
+
* Both helpers exist so the two access patterns are picked deliberately —
|
|
13
|
+
* call the one that matches the plugin shape you're in. Don't reach into the
|
|
14
|
+
* raw fields directly; that's how `withMobileBundle` and `withDeviceInfo`
|
|
15
|
+
* silently disagreed on which directory they were resolving against.
|
|
16
|
+
*/
|
|
17
|
+
function getProjectRootFromMod(config) {
|
|
18
|
+
return config.modRequest.projectRoot;
|
|
19
|
+
}
|
|
20
|
+
function getProjectRootFromBaseConfig(config) {
|
|
21
|
+
return config._internal?.["projectRoot"];
|
|
22
|
+
}
|
|
23
|
+
export { getProjectRootFromMod, getProjectRootFromBaseConfig };
|
|
@@ -4,5 +4,9 @@ export { default as withDeviceInfo } from "./withDeviceInfo";
|
|
|
4
4
|
export { default as withMobileBundle } from "./withMobileBundle";
|
|
5
5
|
export { default as withOpenCL } from "./withOpenCL";
|
|
6
6
|
export { default as withQvacSDK } from "./withQvacSDK";
|
|
7
|
+
export { getProjectRootFromMod, getProjectRootFromBaseConfig, } from "./get-project-root";
|
|
8
|
+
export { resolveSDKPackageDir, SDK_PACKAGE_NAMES, } from "./resolve-sdk-package-dir";
|
|
9
|
+
export type { SDKPackageInfo } from "./resolve-sdk-package-dir";
|
|
10
|
+
export { findInAncestorNodeModules } from "./find-in-ancestor-node-modules";
|
|
7
11
|
export { default } from "./withQvacSDK";
|
|
8
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -4,5 +4,9 @@ export { default as withDeviceInfo } from "./withDeviceInfo.js";
|
|
|
4
4
|
export { default as withMobileBundle } from "./withMobileBundle.js";
|
|
5
5
|
export { default as withOpenCL } from "./withOpenCL.js";
|
|
6
6
|
export { default as withQvacSDK } from "./withQvacSDK.js";
|
|
7
|
+
// Helpers for downstream plugin authors composing on top of these plugins.
|
|
8
|
+
export { getProjectRootFromMod, getProjectRootFromBaseConfig, } from "./get-project-root.js";
|
|
9
|
+
export { resolveSDKPackageDir, SDK_PACKAGE_NAMES, } from "./resolve-sdk-package-dir.js";
|
|
10
|
+
export { findInAncestorNodeModules } from "./find-in-ancestor-node-modules.js";
|
|
7
11
|
// Export the main plugin as default for easy usage
|
|
8
12
|
export { default } from "./withQvacSDK.js";
|
|
@@ -6,8 +6,15 @@ type SDKPackageInfo = {
|
|
|
6
6
|
/**
|
|
7
7
|
* Resolves the installed SDK package directory from node_modules.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* Walks from `projectRoot` up to the filesystem root, checking each
|
|
10
|
+
* `node_modules` directory along the way. This matches Node's own module
|
|
11
|
+
* resolution so packages hoisted to a monorepo root (e.g. by bun or yarn
|
|
12
|
+
* workspaces) are found correctly.
|
|
13
|
+
*
|
|
14
|
+
* When multiple SDK installs are found across the tree, the one closest to
|
|
15
|
+
* `projectRoot` wins and a warning lists the others. Only throws
|
|
16
|
+
* `MultipleSDKInstallationsError` when two *different* SDK package names
|
|
17
|
+
* coexist at the same nesting level (a real ambiguity in package selection).
|
|
11
18
|
*/
|
|
12
19
|
declare function resolveSDKPackageDir(projectRoot: string): SDKPackageInfo;
|
|
13
20
|
export { resolveSDKPackageDir, SDK_PACKAGE_NAMES };
|