@qvac/sdk 0.10.2 → 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 +1455 -29
- package/README.md +2 -0
- package/dist/client/api/cancel.d.ts +24 -32
- package/dist/client/api/cancel.js +58 -31
- package/dist/client/api/classify.d.ts +23 -0
- package/dist/client/api/classify.js +43 -0
- package/dist/client/api/client-request-id.d.ts +17 -0
- package/dist/client/api/client-request-id.js +27 -0
- package/dist/client/api/completion-stream.d.ts +1 -1
- package/dist/client/api/completion-stream.js +34 -3
- package/dist/client/api/diffusion.d.ts +46 -0
- package/dist/client/api/diffusion.js +50 -1
- package/dist/client/api/download-asset.d.ts +12 -2
- package/dist/client/api/download-asset.js +21 -3
- package/dist/client/api/embed.d.ts +8 -4
- package/dist/client/api/embed.js +14 -1
- package/dist/client/api/get-model-info.d.ts +1 -1
- package/dist/client/api/index.d.ts +5 -0
- package/dist/client/api/index.js +5 -0
- package/dist/client/api/load-model.d.ts +12 -4
- package/dist/client/api/load-model.js +49 -2
- package/dist/client/api/rag.d.ts +9 -3
- package/dist/client/api/rag.js +23 -3
- package/dist/client/api/transcribe.d.ts +23 -8
- package/dist/client/api/transcribe.js +69 -4
- package/dist/client/api/unload-model.d.ts +5 -2
- package/dist/client/api/unload-model.js +9 -4
- package/dist/client/api/upscale.d.ts +45 -0
- package/dist/client/api/upscale.js +99 -0
- 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/expo-rpc-client.js +2 -1
- package/dist/client/rpc/node-rpc-client.js +22 -8
- package/dist/client/rpc/rpc-client.d.ts +2 -2
- package/dist/client/rpc/rpc-client.js +10 -4
- package/dist/client/rpc/rpc-error.d.ts +9 -0
- package/dist/client/rpc/rpc-error.js +105 -0
- 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/cancel-by-request-id.d.ts +38 -0
- package/dist/examples/cancel-by-request-id.js +103 -0
- package/dist/examples/classification/classify-image.d.ts +2 -0
- package/dist/examples/classification/classify-image.js +23 -0
- package/dist/examples/diffusion-esrgan-upscale.d.ts +2 -0
- package/dist/examples/diffusion-esrgan-upscale.js +78 -0
- package/dist/examples/diffusion-txt2vid.d.ts +2 -0
- package/dist/examples/diffusion-txt2vid.js +81 -0
- package/dist/examples/download-with-cancel.js +10 -10
- package/dist/examples/embed-multi-gpu.d.ts +2 -0
- package/dist/examples/embed-multi-gpu.js +46 -0
- package/dist/examples/llamacpp-multi-gpu.d.ts +2 -0
- package/dist/examples/llamacpp-multi-gpu.js +57 -0
- package/dist/examples/plugins.js +3 -7
- package/dist/examples/rag/rag-hyperdb/cancellation.js +20 -17
- package/dist/examples/tools/llamacpp-tools-gemma4.d.ts +2 -0
- package/dist/examples/tools/llamacpp-tools-gemma4.js +73 -0
- package/dist/examples/tools/llamacpp-tools-qwen35.d.ts +2 -0
- package/dist/examples/tools/llamacpp-tools-qwen35.js +69 -0
- 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.d.ts +2 -0
- package/dist/examples/transcription/whispercpp-microphone-conversation.js +107 -0
- 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 +5 -4
- package/dist/expo/plugins/withMobileBundle.js +42 -58
- package/dist/index.d.ts +6 -2
- package/dist/index.js +23 -2
- package/dist/models/registry/models.d.ts +3725 -514
- package/dist/models/registry/models.js +7269 -3910
- package/dist/models/update-models/naming.js +22 -8
- package/dist/pear/pre.d.ts +3 -0
- package/dist/pear/pre.js +9 -2
- package/dist/schemas/cancel.d.ts +172 -28
- package/dist/schemas/cancel.js +120 -19
- package/dist/schemas/classification.d.ts +53 -0
- package/dist/schemas/classification.js +33 -0
- package/dist/schemas/common.d.ts +860 -1379
- package/dist/schemas/common.js +8 -1
- package/dist/schemas/completion-event.d.ts +17 -0
- package/dist/schemas/completion-event.js +12 -1
- package/dist/schemas/completion-stream.d.ts +16 -1
- package/dist/schemas/completion-stream.js +25 -7
- package/dist/schemas/download-asset.d.ts +25 -9
- package/dist/schemas/download-asset.js +17 -6
- package/dist/schemas/embed.d.ts +1 -0
- package/dist/schemas/embed.js +5 -0
- package/dist/schemas/engine-addon-map.d.ts +3 -0
- package/dist/schemas/engine-addon-map.js +18 -5
- package/dist/schemas/error.d.ts +31 -0
- package/dist/schemas/error.js +29 -1
- package/dist/schemas/finetune.d.ts +2 -0
- package/dist/schemas/finetune.js +5 -0
- package/dist/schemas/get-model-info.d.ts +10 -6
- 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 +64 -8
- package/dist/schemas/llamacpp-config.js +12 -0
- package/dist/schemas/load-model.d.ts +4644 -8605
- package/dist/schemas/load-model.js +90 -7
- package/dist/schemas/model-src-utils.d.ts +34 -14
- package/dist/schemas/model-types.d.ts +54 -14
- package/dist/schemas/model-types.js +28 -5
- package/dist/schemas/ocr.d.ts +8 -3
- package/dist/schemas/plugin.d.ts +60 -6
- package/dist/schemas/plugin.js +31 -5
- package/dist/schemas/rag.d.ts +9 -0
- package/dist/schemas/rag.js +17 -9
- package/dist/schemas/registry.d.ts +74 -30
- package/dist/schemas/registry.js +5 -0
- package/dist/schemas/reload-config.d.ts +34 -14
- package/dist/schemas/sdcpp-config.d.ts +445 -16
- package/dist/schemas/sdcpp-config.js +387 -26
- package/dist/schemas/sdk-config.d.ts +2431 -2723
- package/dist/schemas/sdk-config.js +16 -1
- package/dist/schemas/sdk-errors-client.d.ts +6 -0
- package/dist/schemas/sdk-errors-client.js +31 -1
- package/dist/schemas/sdk-errors-server.d.ts +8 -1
- package/dist/schemas/sdk-errors-server.js +45 -5
- package/dist/schemas/text-to-speech.d.ts +81 -698
- package/dist/schemas/text-to-speech.js +46 -19
- package/dist/schemas/transcription-config.d.ts +40 -229
- package/dist/schemas/transcription-config.js +76 -15
- package/dist/schemas/transcription.d.ts +108 -2
- package/dist/schemas/transcription.js +81 -0
- package/dist/schemas/translate.d.ts +2 -0
- package/dist/schemas/translate.js +13 -2
- package/dist/schemas/translation-config.d.ts +90 -40
- package/dist/schemas/unload-model.d.ts +2 -1
- package/dist/schemas/unload-model.js +4 -1
- package/dist/schemas/vla.d.ts +87 -0
- package/dist/schemas/vla.js +108 -0
- package/dist/scripts/run-unit-tests.js +22 -3
- package/dist/server/bare/ops/cancel.d.ts +27 -1
- package/dist/server/bare/ops/cancel.js +36 -10
- package/dist/server/bare/ops/embed.d.ts +3 -3
- package/dist/server/bare/ops/embed.js +144 -28
- package/dist/server/bare/ops/kv-cache-utils.d.ts +0 -7
- package/dist/server/bare/ops/kv-cache-utils.js +8 -47
- package/dist/server/bare/ops/transcribe.d.ts +11 -5
- package/dist/server/bare/ops/transcribe.js +230 -50
- package/dist/server/bare/ops/translate.d.ts +1 -1
- package/dist/server/bare/ops/translate.js +197 -88
- 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.d.ts +12 -3
- package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +173 -172
- 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/ops/finetune.js +125 -21
- package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-session.d.ts +154 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-session.js +448 -0
- package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.d.ts +21 -73
- package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.js +18 -101
- package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +36 -3
- package/dist/server/bare/plugins/llamacpp-completion/plugin.js +183 -85
- package/dist/server/bare/plugins/llamacpp-completion/transform.d.ts +10 -0
- package/dist/server/bare/plugins/llamacpp-completion/transform.js +34 -0
- package/dist/server/bare/plugins/llamacpp-embedding/plugin.d.ts +7 -0
- package/dist/server/bare/plugins/llamacpp-embedding/plugin.js +10 -1
- package/dist/server/bare/plugins/nmtcpp-translation/plugin.d.ts +42 -15
- package/dist/server/bare/plugins/nmtcpp-translation/plugin.js +5 -1
- package/dist/server/bare/plugins/onnx-ocr/plugin.d.ts +8 -3
- package/dist/server/bare/plugins/onnx-ocr/plugin.js +3 -0
- package/dist/server/bare/plugins/parakeet-transcription/plugin.d.ts +73 -244
- package/dist/server/bare/plugins/parakeet-transcription/plugin.js +68 -96
- package/dist/server/bare/plugins/sdcpp-generation/ops/diffusion.js +8 -0
- package/dist/server/bare/plugins/sdcpp-generation/ops/upscale.d.ts +3 -0
- package/dist/server/bare/plugins/sdcpp-generation/ops/upscale.js +40 -0
- 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 +288 -15
- package/dist/server/bare/plugins/sdcpp-generation/plugin.js +150 -7
- 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 +47 -3
- package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +61 -14
- package/dist/server/bare/rag-hyperdb/index.d.ts +1 -1
- package/dist/server/bare/rag-hyperdb/index.js +1 -1
- package/dist/server/bare/rag-hyperdb/rag-operation-manager.d.ts +26 -4
- package/dist/server/bare/rag-hyperdb/rag-operation-manager.js +65 -28
- package/dist/server/bare/registry/model-config-utils.js +7 -0
- package/dist/server/bare/runtime/disposable-scope.d.ts +36 -0
- package/dist/server/bare/runtime/disposable-scope.js +69 -0
- package/dist/server/bare/runtime/index.d.ts +8 -0
- package/dist/server/bare/runtime/index.js +3 -0
- package/dist/server/bare/runtime/request-context.d.ts +49 -0
- package/dist/server/bare/runtime/request-context.js +1 -0
- package/dist/server/bare/runtime/request-id.d.ts +12 -0
- package/dist/server/bare/runtime/request-id.js +14 -0
- package/dist/server/bare/runtime/request-registry-singleton.d.ts +4 -0
- package/dist/server/bare/runtime/request-registry-singleton.js +27 -0
- package/dist/server/bare/runtime/request-registry.d.ts +136 -0
- package/dist/server/bare/runtime/request-registry.js +297 -0
- package/dist/server/bare/runtime/with-request-context.d.ts +22 -0
- package/dist/server/bare/runtime/with-request-context.js +53 -0
- package/dist/server/bare/runtime-lifecycle.js +9 -9
- package/dist/server/bare/types/addon-responses.d.ts +12 -1
- 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 +30 -7
- 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/cancel-delegated.js +28 -31
- package/dist/server/rpc/handlers/cancelHandler.d.ts +30 -1
- package/dist/server/rpc/handlers/cancelHandler.js +54 -22
- package/dist/server/rpc/handlers/classify.d.ts +3 -0
- package/dist/server/rpc/handlers/classify.js +4 -0
- package/dist/server/rpc/handlers/delete-cache.d.ts +9 -0
- package/dist/server/rpc/handlers/delete-cache.js +13 -15
- package/dist/server/rpc/handlers/download-asset.js +133 -40
- package/dist/server/rpc/handlers/index.d.ts +4 -0
- package/dist/server/rpc/handlers/index.js +4 -0
- package/dist/server/rpc/handlers/load-model/download-manager.d.ts +60 -2
- package/dist/server/rpc/handlers/load-model/download-manager.js +141 -8
- package/dist/server/rpc/handlers/load-model/handler.js +216 -98
- package/dist/server/rpc/handlers/load-model/http.js +3 -3
- package/dist/server/rpc/handlers/load-model/hyperdrive.js +1 -1
- package/dist/server/rpc/handlers/load-model/registry.js +1 -1
- package/dist/server/rpc/handlers/load-model/resolve-session.d.ts +20 -1
- package/dist/server/rpc/handlers/load-model/resolve-session.js +6 -5
- package/dist/server/rpc/handlers/load-model/resolve.d.ts +3 -2
- package/dist/server/rpc/handlers/load-model/resolve.js +18 -6
- package/dist/server/rpc/handlers/load-model/types.d.ts +24 -0
- package/dist/server/rpc/handlers/rag.js +133 -15
- package/dist/server/rpc/handlers/upscale-stream.d.ts +3 -0
- package/dist/server/rpc/handlers/upscale-stream.js +4 -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/completion-normalizer.js +8 -0
- package/dist/server/utils/config-transform.js +1 -1
- package/dist/server/utils/tools/dialect.js +4 -0
- package/dist/server/utils/tools/parser.js +16 -1
- package/dist/server/utils/tools/parsers/gemma4native.d.ts +4 -0
- package/dist/server/utils/tools/parsers/gemma4native.js +60 -0
- package/dist/server/utils/tools/parsers/qwen35.d.ts +4 -0
- package/dist/server/utils/tools/parsers/qwen35.js +120 -0
- package/dist/server/worker.js +14 -11
- package/dist/utils/aggregate-events.d.ts +9 -0
- package/dist/utils/aggregate-events.js +18 -3
- package/dist/utils/decorate-promise.d.ts +34 -0
- package/dist/utils/decorate-promise.js +35 -0
- package/dist/utils/errors-client.d.ts +18 -0
- package/dist/utils/errors-client.js +31 -0
- package/dist/utils/errors-server.d.ts +115 -2
- package/dist/utils/errors-server.js +148 -3
- package/package.json +68 -77
- package/dist/server/bare/plugins/onnx-tts/plugin.d.ts +0 -490
- package/dist/server/bare/plugins/onnx-tts/plugin.js +0 -266
- 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
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import { promises as fsp } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { resolveConfigFileInProject, loadConfigFromPath, } from "../../client/config-loader/resolve-config.node.js";
|
|
4
|
+
import { createCollectDiagnostics, formatAddonId, } from "./addon-source.js";
|
|
5
|
+
import { collectAddonsFromBundle, InvalidBundleSourceError, } from "./bundle-source.js";
|
|
6
|
+
import { collectAddonsFromNodeModules, InvalidNodeModulesSourceError, } from "./node-modules-source.js";
|
|
7
|
+
import { checkPrebuilds, } from "./prebuilds.js";
|
|
8
|
+
import { checkAbi, formatConfigLabel, normalizeVersion, resolveBareRuntime, } from "./abi.js";
|
|
9
|
+
export async function verifyBundle(options) {
|
|
10
|
+
const { projectRoot, addonsSource, hosts, bareRuntimeVersion, configPath } = options;
|
|
11
|
+
const resolvedAddonsSource = path.isAbsolute(addonsSource)
|
|
12
|
+
? addonsSource
|
|
13
|
+
: path.resolve(projectRoot, addonsSource);
|
|
14
|
+
if (hosts.length === 0) {
|
|
15
|
+
return {
|
|
16
|
+
addonsSource,
|
|
17
|
+
resolvedAddonsSource,
|
|
18
|
+
sourceKind: null,
|
|
19
|
+
hosts,
|
|
20
|
+
runtime: null,
|
|
21
|
+
addons: [],
|
|
22
|
+
issues: [
|
|
23
|
+
{
|
|
24
|
+
code: 'invalid-source',
|
|
25
|
+
level: 'error',
|
|
26
|
+
addonsSource,
|
|
27
|
+
message: 'At least one host is required.'
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
let invalidRuntimeVersion = null;
|
|
33
|
+
if (bareRuntimeVersion !== undefined && normalizeVersion(bareRuntimeVersion) === null) {
|
|
34
|
+
invalidRuntimeVersion = {
|
|
35
|
+
code: 'invalid-runtime-version',
|
|
36
|
+
level: 'error',
|
|
37
|
+
providedValue: bareRuntimeVersion,
|
|
38
|
+
source: 'flag',
|
|
39
|
+
message: `bareRuntimeVersion "${bareRuntimeVersion}" is not a valid semver. ` +
|
|
40
|
+
'Use a version like 1.15.0 (with optional v-prefix and pre-release tag) or omit it to use auto-detection.'
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
let configRuntimeVersion;
|
|
44
|
+
let resolvedConfigPath = null;
|
|
45
|
+
let configLoadFailed = null;
|
|
46
|
+
try {
|
|
47
|
+
resolvedConfigPath = await resolveConfigFileInProject(projectRoot, configPath ?? undefined);
|
|
48
|
+
if (resolvedConfigPath !== null) {
|
|
49
|
+
const config = await loadConfigFromPath(resolvedConfigPath);
|
|
50
|
+
if (typeof config.bareRuntimeVersion === "string") {
|
|
51
|
+
configRuntimeVersion = config.bareRuntimeVersion;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
57
|
+
if (configPath !== undefined) {
|
|
58
|
+
return {
|
|
59
|
+
addonsSource,
|
|
60
|
+
resolvedAddonsSource,
|
|
61
|
+
sourceKind: null,
|
|
62
|
+
hosts,
|
|
63
|
+
runtime: null,
|
|
64
|
+
addons: [],
|
|
65
|
+
issues: [
|
|
66
|
+
{
|
|
67
|
+
code: 'invalid-source',
|
|
68
|
+
level: 'error',
|
|
69
|
+
addonsSource,
|
|
70
|
+
message: `Failed to load config from '${configPath}': ${message}`
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
if (resolvedConfigPath !== null) {
|
|
76
|
+
configLoadFailed = {
|
|
77
|
+
code: 'config-load-failed',
|
|
78
|
+
level: 'warning',
|
|
79
|
+
configPath: resolvedConfigPath,
|
|
80
|
+
reason: message,
|
|
81
|
+
message: `Found ${formatConfigLabel(projectRoot, resolvedConfigPath)} but failed to load it: ${message}. ` +
|
|
82
|
+
'Falling back to auto-detection for Bare runtime; the project-pinned ' +
|
|
83
|
+
'`bareRuntimeVersion` is being ignored. Fix the config file or pass `configPath` explicitly to surface it as an error.'
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (invalidRuntimeVersion === null &&
|
|
88
|
+
bareRuntimeVersion === undefined &&
|
|
89
|
+
configRuntimeVersion !== undefined &&
|
|
90
|
+
normalizeVersion(configRuntimeVersion) === null) {
|
|
91
|
+
invalidRuntimeVersion = {
|
|
92
|
+
code: 'invalid-runtime-version',
|
|
93
|
+
level: 'error',
|
|
94
|
+
providedValue: configRuntimeVersion,
|
|
95
|
+
source: 'config',
|
|
96
|
+
message: `\`bareRuntimeVersion\` in ${formatConfigLabel(projectRoot, resolvedConfigPath ?? undefined)} ` +
|
|
97
|
+
`"${configRuntimeVersion}" is not a valid semver. ` +
|
|
98
|
+
'Use a version like 1.15.0 (with optional v-prefix and pre-release tag), or remove the field to use auto-detection.'
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
const sourceKind = await detectSourceKind(resolvedAddonsSource);
|
|
102
|
+
if (sourceKind === null) {
|
|
103
|
+
return {
|
|
104
|
+
addonsSource,
|
|
105
|
+
resolvedAddonsSource,
|
|
106
|
+
sourceKind: null,
|
|
107
|
+
hosts,
|
|
108
|
+
runtime: null,
|
|
109
|
+
addons: [],
|
|
110
|
+
issues: [
|
|
111
|
+
{
|
|
112
|
+
code: 'invalid-source',
|
|
113
|
+
level: 'error',
|
|
114
|
+
addonsSource,
|
|
115
|
+
message: `--addons-source ${addonsSource} is not a readable file or directory ` +
|
|
116
|
+
`(resolved to ${resolvedAddonsSource}).`
|
|
117
|
+
}
|
|
118
|
+
]
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
const diagnostics = createCollectDiagnostics();
|
|
122
|
+
let addons;
|
|
123
|
+
try {
|
|
124
|
+
addons = sourceKind === 'bare-pack-bundle'
|
|
125
|
+
? await collectAddonsFromBundle({
|
|
126
|
+
bundlePath: resolvedAddonsSource,
|
|
127
|
+
projectRoot,
|
|
128
|
+
diagnostics
|
|
129
|
+
})
|
|
130
|
+
: await collectAddonsFromNodeModules({
|
|
131
|
+
nodeModulesRoot: resolvedAddonsSource,
|
|
132
|
+
diagnostics
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
if (error instanceof InvalidBundleSourceError ||
|
|
137
|
+
error instanceof InvalidNodeModulesSourceError) {
|
|
138
|
+
return {
|
|
139
|
+
addonsSource,
|
|
140
|
+
resolvedAddonsSource,
|
|
141
|
+
sourceKind,
|
|
142
|
+
hosts,
|
|
143
|
+
runtime: null,
|
|
144
|
+
addons: [],
|
|
145
|
+
issues: [
|
|
146
|
+
{
|
|
147
|
+
code: 'invalid-source',
|
|
148
|
+
level: 'error',
|
|
149
|
+
addonsSource,
|
|
150
|
+
message: error.message
|
|
151
|
+
}
|
|
152
|
+
]
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
const issues = [];
|
|
158
|
+
if (configLoadFailed !== null)
|
|
159
|
+
issues.push(configLoadFailed);
|
|
160
|
+
if (invalidRuntimeVersion !== null)
|
|
161
|
+
issues.push(invalidRuntimeVersion);
|
|
162
|
+
issues.push(...buildInvalidPackageJsonIssues(diagnostics.invalidPackageJsons));
|
|
163
|
+
if (sourceKind === 'bare-pack-bundle' && diagnostics.emptyResolutions) {
|
|
164
|
+
issues.push({
|
|
165
|
+
code: 'empty-bundle-resolutions',
|
|
166
|
+
level: 'warning',
|
|
167
|
+
bundlePath: resolvedAddonsSource,
|
|
168
|
+
message: `Bundle at ${resolvedAddonsSource} has no resolutions in its bare-pack header ` +
|
|
169
|
+
'(0 packages discoverable). The verifier cannot inspect any addons in this bundle; ' +
|
|
170
|
+
'`Native addon verification passed` would be vacuous. Regenerate the bundle via ' +
|
|
171
|
+
'`qvac bundle sdk` and re-run, or check for a corrupted/empty bundle file.'
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
for (const addon of addons) {
|
|
175
|
+
const prebuildIssues = await checkPrebuilds({ addon, hosts });
|
|
176
|
+
issues.push(...prebuildIssues);
|
|
177
|
+
}
|
|
178
|
+
let runtime = null;
|
|
179
|
+
if (invalidRuntimeVersion === null) {
|
|
180
|
+
const runtimeOptions = { projectRoot };
|
|
181
|
+
if (bareRuntimeVersion !== undefined) {
|
|
182
|
+
runtimeOptions.explicitVersion = bareRuntimeVersion;
|
|
183
|
+
runtimeOptions.explicitSource = 'flag';
|
|
184
|
+
}
|
|
185
|
+
else if (configRuntimeVersion !== undefined) {
|
|
186
|
+
runtimeOptions.explicitVersion = configRuntimeVersion;
|
|
187
|
+
runtimeOptions.explicitSource = 'config';
|
|
188
|
+
}
|
|
189
|
+
runtime = await resolveBareRuntime(runtimeOptions);
|
|
190
|
+
issues.push(...checkAbi({ addons, runtime }));
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
addonsSource,
|
|
194
|
+
resolvedAddonsSource,
|
|
195
|
+
sourceKind,
|
|
196
|
+
hosts,
|
|
197
|
+
runtime,
|
|
198
|
+
addons,
|
|
199
|
+
issues
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function buildInvalidPackageJsonIssues(records) {
|
|
203
|
+
return records.map((record) => {
|
|
204
|
+
const issue = {
|
|
205
|
+
code: 'invalid-package-json',
|
|
206
|
+
level: 'warning',
|
|
207
|
+
packageJsonPath: record.packageJsonPath,
|
|
208
|
+
reason: record.reason,
|
|
209
|
+
message: `Skipping ${record.expectedName ?? record.packageJsonPath}: ` +
|
|
210
|
+
`${record.reason}. The package is being treated as a non-addon; if it ships ` +
|
|
211
|
+
'native code, the verifier cannot check its prebuilds or ABI. ' +
|
|
212
|
+
'Fix the package.json or remove the package.'
|
|
213
|
+
};
|
|
214
|
+
if (record.expectedName !== undefined)
|
|
215
|
+
issue.expectedName = record.expectedName;
|
|
216
|
+
return issue;
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
async function detectSourceKind(resolvedAddonsSource) {
|
|
220
|
+
try {
|
|
221
|
+
const stat = await fsp.stat(resolvedAddonsSource);
|
|
222
|
+
if (stat.isFile())
|
|
223
|
+
return 'bare-pack-bundle';
|
|
224
|
+
if (stat.isDirectory())
|
|
225
|
+
return 'node-modules';
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
export function hasErrors(result) {
|
|
233
|
+
return result.issues.some((issue) => issue.level === 'error');
|
|
234
|
+
}
|
|
235
|
+
export function hasWarnings(result) {
|
|
236
|
+
return result.issues.some((issue) => issue.level === 'warning');
|
|
237
|
+
}
|
|
238
|
+
export function formatVerifyBundleResult(result) {
|
|
239
|
+
const sections = [];
|
|
240
|
+
const hostList = result.hosts.join(', ');
|
|
241
|
+
if (result.issues.length === 0) {
|
|
242
|
+
sections.push(`Native addon verification passed for ${result.addons.length} ` +
|
|
243
|
+
`addon${result.addons.length === 1 ? '' : 's'} across ${result.hosts.length} ` +
|
|
244
|
+
`host${result.hosts.length === 1 ? '' : 's'}: ${hostList}`);
|
|
245
|
+
if (result.addons.length > 0) {
|
|
246
|
+
sections.push('');
|
|
247
|
+
sections.push(' Verified addons:');
|
|
248
|
+
for (const addon of result.addons) {
|
|
249
|
+
sections.push(` - ${formatAddonId(addon)}`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return sections.join('\n');
|
|
253
|
+
}
|
|
254
|
+
if (hasErrors(result)) {
|
|
255
|
+
sections.push('Native addon verification failed:');
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
sections.push('Native addon verification produced warnings:');
|
|
259
|
+
}
|
|
260
|
+
sections.push('');
|
|
261
|
+
sections.push(...formatMissingPrebuilds(result.issues));
|
|
262
|
+
sections.push(...formatAbiMismatches(result.issues));
|
|
263
|
+
sections.push(...formatInvalidRuntimeVersions(result.issues));
|
|
264
|
+
sections.push(...formatMalformedEnginesBare(result.issues));
|
|
265
|
+
sections.push(...formatConfigLoadFailed(result.issues));
|
|
266
|
+
sections.push(...formatInvalidPackageJsons(result.issues));
|
|
267
|
+
sections.push(...formatEmptyBundleResolutions(result.issues));
|
|
268
|
+
sections.push(...formatUnknownRuntime(result.issues));
|
|
269
|
+
sections.push(...formatInvalidSources(result.issues));
|
|
270
|
+
return sections.join('\n').trimEnd();
|
|
271
|
+
}
|
|
272
|
+
function formatConfigLoadFailed(issues) {
|
|
273
|
+
const matches = issues.filter((issue) => issue.code === 'config-load-failed');
|
|
274
|
+
if (matches.length === 0)
|
|
275
|
+
return [];
|
|
276
|
+
const lines = [' Config load failed:'];
|
|
277
|
+
for (const issue of matches) {
|
|
278
|
+
lines.push(` - ${issue.message}`);
|
|
279
|
+
}
|
|
280
|
+
lines.push('');
|
|
281
|
+
return lines;
|
|
282
|
+
}
|
|
283
|
+
function formatMissingPrebuilds(issues) {
|
|
284
|
+
const matches = issues.filter((issue) => issue.code === 'missing-prebuild');
|
|
285
|
+
if (matches.length === 0)
|
|
286
|
+
return [];
|
|
287
|
+
const lines = [' Missing prebuild:'];
|
|
288
|
+
for (const issue of matches) {
|
|
289
|
+
lines.push(` - ${issue.addon} for ${issue.host}`);
|
|
290
|
+
}
|
|
291
|
+
lines.push('');
|
|
292
|
+
return lines;
|
|
293
|
+
}
|
|
294
|
+
function formatAbiMismatches(issues) {
|
|
295
|
+
const matches = issues.filter((issue) => issue.code === 'abi-mismatch');
|
|
296
|
+
if (matches.length === 0)
|
|
297
|
+
return [];
|
|
298
|
+
const lines = [' ABI mismatch:'];
|
|
299
|
+
for (const issue of matches) {
|
|
300
|
+
lines.push(` - ${issue.addon} requires bare ${issue.enginesBare}, ` +
|
|
301
|
+
`runtime is ${issue.runtimeVersion}`);
|
|
302
|
+
}
|
|
303
|
+
lines.push('');
|
|
304
|
+
return lines;
|
|
305
|
+
}
|
|
306
|
+
function formatUnknownRuntime(issues) {
|
|
307
|
+
const matches = issues.filter((issue) => issue.code === 'unknown-runtime-version');
|
|
308
|
+
if (matches.length === 0)
|
|
309
|
+
return [];
|
|
310
|
+
const lines = [' Unknown runtime version:'];
|
|
311
|
+
for (const issue of matches) {
|
|
312
|
+
lines.push(` - ${issue.message}`);
|
|
313
|
+
}
|
|
314
|
+
lines.push('');
|
|
315
|
+
return lines;
|
|
316
|
+
}
|
|
317
|
+
function formatMalformedEnginesBare(issues) {
|
|
318
|
+
const matches = issues.filter((issue) => issue.code === 'malformed-engines-bare');
|
|
319
|
+
if (matches.length === 0)
|
|
320
|
+
return [];
|
|
321
|
+
const lines = [' Malformed engines.bare:'];
|
|
322
|
+
for (const issue of matches) {
|
|
323
|
+
lines.push(` - ${issue.message}`);
|
|
324
|
+
}
|
|
325
|
+
lines.push('');
|
|
326
|
+
return lines;
|
|
327
|
+
}
|
|
328
|
+
function formatInvalidSources(issues) {
|
|
329
|
+
const matches = issues.filter((issue) => issue.code === 'invalid-source');
|
|
330
|
+
if (matches.length === 0)
|
|
331
|
+
return [];
|
|
332
|
+
const lines = [' Invalid source:'];
|
|
333
|
+
for (const issue of matches) {
|
|
334
|
+
lines.push(` - ${issue.message}`);
|
|
335
|
+
}
|
|
336
|
+
lines.push('');
|
|
337
|
+
return lines;
|
|
338
|
+
}
|
|
339
|
+
function formatInvalidRuntimeVersions(issues) {
|
|
340
|
+
const matches = issues.filter((issue) => issue.code === 'invalid-runtime-version');
|
|
341
|
+
if (matches.length === 0)
|
|
342
|
+
return [];
|
|
343
|
+
const lines = [' Invalid Bare runtime version:'];
|
|
344
|
+
for (const issue of matches) {
|
|
345
|
+
lines.push(` - ${issue.message}`);
|
|
346
|
+
}
|
|
347
|
+
lines.push('');
|
|
348
|
+
return lines;
|
|
349
|
+
}
|
|
350
|
+
function formatInvalidPackageJsons(issues) {
|
|
351
|
+
const matches = issues.filter((issue) => issue.code === 'invalid-package-json');
|
|
352
|
+
if (matches.length === 0)
|
|
353
|
+
return [];
|
|
354
|
+
const lines = [' Invalid package.json (skipped):'];
|
|
355
|
+
for (const issue of matches) {
|
|
356
|
+
lines.push(` - ${issue.message}`);
|
|
357
|
+
}
|
|
358
|
+
lines.push('');
|
|
359
|
+
return lines;
|
|
360
|
+
}
|
|
361
|
+
function formatEmptyBundleResolutions(issues) {
|
|
362
|
+
const matches = issues.filter((issue) => issue.code === 'empty-bundle-resolutions');
|
|
363
|
+
if (matches.length === 0)
|
|
364
|
+
return [];
|
|
365
|
+
const lines = [' Empty bundle resolutions:'];
|
|
366
|
+
for (const issue of matches) {
|
|
367
|
+
lines.push(` - ${issue.message}`);
|
|
368
|
+
}
|
|
369
|
+
lines.push('');
|
|
370
|
+
return lines;
|
|
371
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type CollectDiagnostics, type NativeAddon } from "./addon-source";
|
|
2
|
+
export declare class InvalidNodeModulesSourceError extends Error {
|
|
3
|
+
nodeModulesPath: string;
|
|
4
|
+
constructor(nodeModulesPath: string, cause: unknown);
|
|
5
|
+
}
|
|
6
|
+
export interface CollectAddonsFromNodeModulesOptions {
|
|
7
|
+
nodeModulesRoot: string;
|
|
8
|
+
diagnostics?: CollectDiagnostics;
|
|
9
|
+
}
|
|
10
|
+
export declare function collectAddonsFromNodeModules(options: CollectAddonsFromNodeModulesOptions): Promise<NativeAddon[]>;
|
|
11
|
+
//# sourceMappingURL=node-modules-source.d.ts.map
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { promises as fsp } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { deduplicateAddons, readAddonPackageJson, } from "./addon-source.js";
|
|
4
|
+
export class InvalidNodeModulesSourceError extends Error {
|
|
5
|
+
nodeModulesPath;
|
|
6
|
+
constructor(nodeModulesPath, cause) {
|
|
7
|
+
const reason = cause instanceof Error ? cause.message : String(cause);
|
|
8
|
+
super(`node_modules at ${nodeModulesPath} could not be read.\n\n` +
|
|
9
|
+
` Reason: ${reason}\n\n` +
|
|
10
|
+
" Run `npm install` before invoking verifyBundle against a node_modules tree.");
|
|
11
|
+
this.name = "InvalidNodeModulesSourceError";
|
|
12
|
+
this.nodeModulesPath = nodeModulesPath;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export async function collectAddonsFromNodeModules(options) {
|
|
16
|
+
const { nodeModulesRoot, diagnostics } = options;
|
|
17
|
+
const addons = [];
|
|
18
|
+
await walkNodeModules(nodeModulesRoot, addons, diagnostics, true);
|
|
19
|
+
return deduplicateAddons(addons);
|
|
20
|
+
}
|
|
21
|
+
async function walkNodeModules(nodeModulesDir, addons, diagnostics, isRoot) {
|
|
22
|
+
let entries;
|
|
23
|
+
try {
|
|
24
|
+
entries = await fsp.readdir(nodeModulesDir, { withFileTypes: true });
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
if (isRoot)
|
|
28
|
+
throw new InvalidNodeModulesSourceError(nodeModulesDir, error);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
for (const entry of entries) {
|
|
32
|
+
if (entry.name.startsWith("."))
|
|
33
|
+
continue;
|
|
34
|
+
if (!isPackageEntry(entry))
|
|
35
|
+
continue;
|
|
36
|
+
if (entry.name.startsWith("@")) {
|
|
37
|
+
await walkScopeDirectory(path.join(nodeModulesDir, entry.name), addons, diagnostics);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
await visitPackageDirectory(path.join(nodeModulesDir, entry.name), entry.name, addons, diagnostics);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function walkScopeDirectory(scopeDir, addons, diagnostics) {
|
|
44
|
+
const scope = path.basename(scopeDir);
|
|
45
|
+
let entries;
|
|
46
|
+
try {
|
|
47
|
+
entries = await fsp.readdir(scopeDir, { withFileTypes: true });
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
for (const entry of entries) {
|
|
53
|
+
if (entry.name.startsWith("."))
|
|
54
|
+
continue;
|
|
55
|
+
if (!isPackageEntry(entry))
|
|
56
|
+
continue;
|
|
57
|
+
await visitPackageDirectory(path.join(scopeDir, entry.name), `${scope}/${entry.name}`, addons, diagnostics);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function isPackageEntry(entry) {
|
|
61
|
+
return entry.isDirectory() || entry.isSymbolicLink();
|
|
62
|
+
}
|
|
63
|
+
async function visitPackageDirectory(packageDir, packageName, addons, diagnostics) {
|
|
64
|
+
const result = await readAddonPackageJson({
|
|
65
|
+
packageJsonPath: path.join(packageDir, "package.json"),
|
|
66
|
+
expectedName: packageName,
|
|
67
|
+
});
|
|
68
|
+
if (result.isAddon && result.addon) {
|
|
69
|
+
addons.push(result.addon);
|
|
70
|
+
}
|
|
71
|
+
else if (result.invalid !== undefined && diagnostics !== undefined) {
|
|
72
|
+
diagnostics.invalidPackageJsons.push(result.invalid);
|
|
73
|
+
}
|
|
74
|
+
const nestedNodeModules = path.join(packageDir, "node_modules");
|
|
75
|
+
await walkNodeModules(nestedNodeModules, addons, diagnostics, false);
|
|
76
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type NativeAddon } from "./addon-source";
|
|
2
|
+
export interface MissingPrebuildIssue {
|
|
3
|
+
code: "missing-prebuild";
|
|
4
|
+
level: "error";
|
|
5
|
+
addon: string;
|
|
6
|
+
host: string;
|
|
7
|
+
message: string;
|
|
8
|
+
packageRoot: string;
|
|
9
|
+
}
|
|
10
|
+
export interface CheckPrebuildsOptions {
|
|
11
|
+
addon: NativeAddon;
|
|
12
|
+
hosts: string[];
|
|
13
|
+
}
|
|
14
|
+
export declare function checkPrebuilds(options: CheckPrebuildsOptions): Promise<MissingPrebuildIssue[]>;
|
|
15
|
+
//# sourceMappingURL=prebuilds.d.ts.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { promises as fsp } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { formatAddonId } from "./addon-source.js";
|
|
4
|
+
export async function checkPrebuilds(options) {
|
|
5
|
+
const { addon, hosts } = options;
|
|
6
|
+
const issues = [];
|
|
7
|
+
for (const host of hosts) {
|
|
8
|
+
const hostDir = path.join(addon.packageRoot, "prebuilds", host);
|
|
9
|
+
const present = await hasBarePrebuild(hostDir);
|
|
10
|
+
if (!present) {
|
|
11
|
+
issues.push({
|
|
12
|
+
code: "missing-prebuild",
|
|
13
|
+
level: "error",
|
|
14
|
+
addon: formatAddonId(addon),
|
|
15
|
+
host,
|
|
16
|
+
packageRoot: addon.packageRoot,
|
|
17
|
+
message: `${formatAddonId(addon)} is missing a prebuild for ${host} ` +
|
|
18
|
+
`(expected ${path.join(hostDir, "*.bare")}).`,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return issues;
|
|
23
|
+
}
|
|
24
|
+
async function hasBarePrebuild(hostDir) {
|
|
25
|
+
let entries;
|
|
26
|
+
try {
|
|
27
|
+
entries = await fsp.readdir(hostDir, { withFileTypes: true });
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
for (const entry of entries) {
|
|
33
|
+
if (!entry.isFile() && !entry.isSymbolicLink())
|
|
34
|
+
continue;
|
|
35
|
+
if (entry.name.endsWith(".bare"))
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cancel a specific in-flight completion by `requestId`.
|
|
3
|
+
*
|
|
4
|
+
* `completion(...)` exposes a stable `requestId` (UUIDv4, generated
|
|
5
|
+
* client-side) on the returned `CompletionRun`. Pass it to
|
|
6
|
+
* `cancel({ requestId })` to abort that exact run without affecting any
|
|
7
|
+
* other inference happening on the same model.
|
|
8
|
+
*
|
|
9
|
+
* Two cancel paths exist:
|
|
10
|
+
*
|
|
11
|
+
* 1. `cancel({ requestId })` — targeted cancel, the primary path
|
|
12
|
+
* introduced in 0.11.0. The `requestId` is available synchronously
|
|
13
|
+
* on the `CompletionRun`. Same-tick cancels (issued before the
|
|
14
|
+
* server has registered the request) are recorded and applied
|
|
15
|
+
* retroactively when `begin(...)` arrives, so they aren't silently
|
|
16
|
+
* dropped.
|
|
17
|
+
* 2. `cancel({ operation: "inference", modelId })` — broad cancel
|
|
18
|
+
* (escape hatch, kept indefinitely). Cancels every inference running
|
|
19
|
+
* on the model. Useful for unload, app shutdown, admin sweeps when
|
|
20
|
+
* the caller doesn't have a `requestId` to hand.
|
|
21
|
+
*
|
|
22
|
+
* --- Cancel outcomes (0.11.0+) ---
|
|
23
|
+
*
|
|
24
|
+
* A cancel surfaces on two channels:
|
|
25
|
+
*
|
|
26
|
+
* - `run.events` ends *normally* with a `completionDone` event carrying
|
|
27
|
+
* `stopReason: "cancelled"`. The loop exits cleanly, no thrown error.
|
|
28
|
+
* - `run.text` / `run.final` / `run.stats` / `run.toolCalls` reject
|
|
29
|
+
* with `InferenceCancelledError(requestId, partial)`, where `partial`
|
|
30
|
+
* holds whatever the model produced before the cancel landed
|
|
31
|
+
* (accumulated `text`, completed `toolCalls`, last-known `stats`).
|
|
32
|
+
*
|
|
33
|
+
* Pick the channel that matches how you consume the run: event-loop
|
|
34
|
+
* consumers don't need to catch anything; promise-aggregate consumers
|
|
35
|
+
* pattern-match on `instanceof InferenceCancelledError`.
|
|
36
|
+
*/
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=cancel-by-request-id.d.ts.map
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cancel a specific in-flight completion by `requestId`.
|
|
3
|
+
*
|
|
4
|
+
* `completion(...)` exposes a stable `requestId` (UUIDv4, generated
|
|
5
|
+
* client-side) on the returned `CompletionRun`. Pass it to
|
|
6
|
+
* `cancel({ requestId })` to abort that exact run without affecting any
|
|
7
|
+
* other inference happening on the same model.
|
|
8
|
+
*
|
|
9
|
+
* Two cancel paths exist:
|
|
10
|
+
*
|
|
11
|
+
* 1. `cancel({ requestId })` — targeted cancel, the primary path
|
|
12
|
+
* introduced in 0.11.0. The `requestId` is available synchronously
|
|
13
|
+
* on the `CompletionRun`. Same-tick cancels (issued before the
|
|
14
|
+
* server has registered the request) are recorded and applied
|
|
15
|
+
* retroactively when `begin(...)` arrives, so they aren't silently
|
|
16
|
+
* dropped.
|
|
17
|
+
* 2. `cancel({ operation: "inference", modelId })` — broad cancel
|
|
18
|
+
* (escape hatch, kept indefinitely). Cancels every inference running
|
|
19
|
+
* on the model. Useful for unload, app shutdown, admin sweeps when
|
|
20
|
+
* the caller doesn't have a `requestId` to hand.
|
|
21
|
+
*
|
|
22
|
+
* --- Cancel outcomes (0.11.0+) ---
|
|
23
|
+
*
|
|
24
|
+
* A cancel surfaces on two channels:
|
|
25
|
+
*
|
|
26
|
+
* - `run.events` ends *normally* with a `completionDone` event carrying
|
|
27
|
+
* `stopReason: "cancelled"`. The loop exits cleanly, no thrown error.
|
|
28
|
+
* - `run.text` / `run.final` / `run.stats` / `run.toolCalls` reject
|
|
29
|
+
* with `InferenceCancelledError(requestId, partial)`, where `partial`
|
|
30
|
+
* holds whatever the model produced before the cancel landed
|
|
31
|
+
* (accumulated `text`, completed `toolCalls`, last-known `stats`).
|
|
32
|
+
*
|
|
33
|
+
* Pick the channel that matches how you consume the run: event-loop
|
|
34
|
+
* consumers don't need to catch anything; promise-aggregate consumers
|
|
35
|
+
* pattern-match on `instanceof InferenceCancelledError`.
|
|
36
|
+
*/
|
|
37
|
+
import { cancel, completion, loadModel, unloadModel, InferenceCancelledError, QWEN3_600M_INST_Q4, } from "@qvac/sdk";
|
|
38
|
+
try {
|
|
39
|
+
const modelId = await loadModel({
|
|
40
|
+
modelSrc: QWEN3_600M_INST_Q4,
|
|
41
|
+
modelType: "llm",
|
|
42
|
+
modelConfig: { ctx_size: 4096 },
|
|
43
|
+
});
|
|
44
|
+
const run = completion({
|
|
45
|
+
modelId,
|
|
46
|
+
history: [
|
|
47
|
+
{
|
|
48
|
+
role: "user",
|
|
49
|
+
content: "Write a long, detailed essay about the history of the Roman Empire.",
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
stream: true,
|
|
53
|
+
});
|
|
54
|
+
console.log(`requestId: ${run.requestId}`);
|
|
55
|
+
// Cancel after a short delay so we exercise the cancel-mid-decode path.
|
|
56
|
+
setTimeout(() => {
|
|
57
|
+
void cancel({ requestId: run.requestId });
|
|
58
|
+
console.log("(cancel issued)");
|
|
59
|
+
}, 250);
|
|
60
|
+
// Channel 1: the events stream ends normally on cancel. The
|
|
61
|
+
// `completionDone` event's `stopReason` tells you why the loop is
|
|
62
|
+
// about to exit ("eos" | "length" | "cancelled" | "error" | ...).
|
|
63
|
+
let tokenCount = 0;
|
|
64
|
+
let endReason;
|
|
65
|
+
for await (const event of run.events) {
|
|
66
|
+
if (event.type === "contentDelta") {
|
|
67
|
+
tokenCount++;
|
|
68
|
+
process.stdout.write(event.text);
|
|
69
|
+
}
|
|
70
|
+
else if (event.type === "completionDone") {
|
|
71
|
+
endReason = event.stopReason;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
console.log(`\n\nstreamed ${tokenCount} content deltas, stopReason=${endReason}.`);
|
|
75
|
+
// Channel 2: promise-aggregates reject with InferenceCancelledError
|
|
76
|
+
// on cancel. The accumulated state up to the cancel point is preserved
|
|
77
|
+
// on `err.partial`.
|
|
78
|
+
try {
|
|
79
|
+
const text = await run.text;
|
|
80
|
+
console.log(`completed normally (${text.length} chars).`);
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
if (err instanceof InferenceCancelledError) {
|
|
84
|
+
console.log(`run.text rejected: cancelled (requestId=${err.requestId})`);
|
|
85
|
+
console.log(`partial text length: ${(err.partial.text ?? "").length}`);
|
|
86
|
+
if (err.partial.stats?.tokensPerSecond !== undefined) {
|
|
87
|
+
console.log(`partial stats: ${err.partial.stats.tokensPerSecond.toFixed(1)} tok/s`);
|
|
88
|
+
}
|
|
89
|
+
if (err.partial.toolCalls && err.partial.toolCalls.length > 0) {
|
|
90
|
+
console.log(`partial tool calls: ${err.partial.toolCalls.length}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
throw err;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
await unloadModel({ modelId });
|
|
98
|
+
process.exit(0);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.error("Error:", error);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import { startQVACProvider, stopQVACProvider, loadModel, classify, unloadModel } from "@qvac/sdk";
|
|
3
|
+
/**
|
|
4
|
+
* Classify an image using the bundled MobileNetV3-Small model.
|
|
5
|
+
*
|
|
6
|
+
* The bundled model produces three classes: "food", "report", "other".
|
|
7
|
+
* No modelSrc is needed — the model ships inside @qvac/classification-ggml.
|
|
8
|
+
*/
|
|
9
|
+
async function main() {
|
|
10
|
+
await startQVACProvider({});
|
|
11
|
+
const modelId = await loadModel({
|
|
12
|
+
modelType: "ggml-classification",
|
|
13
|
+
});
|
|
14
|
+
const image = fs.readFileSync("image.jpg");
|
|
15
|
+
const results = await classify({ modelId, image });
|
|
16
|
+
console.log("Classification results:");
|
|
17
|
+
for (const { label, confidence } of results) {
|
|
18
|
+
console.log(` ${label}: ${(confidence * 100).toFixed(1)}%`);
|
|
19
|
+
}
|
|
20
|
+
await unloadModel({ modelId });
|
|
21
|
+
await stopQVACProvider();
|
|
22
|
+
}
|
|
23
|
+
main().catch(console.error);
|