@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
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ModelProgressUpdate } from "../../../../schemas/index";
|
|
2
2
|
import type { ResolveResult, DownloadHooks } from "./types";
|
|
3
|
-
|
|
4
|
-
export declare function
|
|
3
|
+
import type { AbortSignal } from "bare-abort-controller";
|
|
4
|
+
export declare function resolveModelPath(modelSrc: unknown, progressCallback?: (progress: ModelProgressUpdate) => void, seed?: boolean, signal?: AbortSignal, hooks?: DownloadHooks): Promise<string>;
|
|
5
|
+
export declare function resolveModelPathWithStats(modelSrc: unknown, progressCallback?: (progress: ModelProgressUpdate) => void, seed?: boolean, signal?: AbortSignal, hooks?: DownloadHooks): Promise<ResolveResult>;
|
|
5
6
|
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -7,7 +7,7 @@ import { downloadModelFromHttp } from "./http.js";
|
|
|
7
7
|
import { downloadModelFromHyperdrive } from "./hyperdrive.js";
|
|
8
8
|
import { downloadModelFromRegistry } from "./registry.js";
|
|
9
9
|
import { downloadModelFromHttpWithStats, downloadModelFromHyperdriveWithStats, downloadModelFromRegistryWithStats, } from "./download-stats.js";
|
|
10
|
-
import { ModelLoadFailedError, ModelNotFoundError, SeedingNotSupportedError, } from "../../../../utils/errors-server.js";
|
|
10
|
+
import { InferenceCancelledError, ModelLoadFailedError, ModelNotFoundError, SeedingNotSupportedError, } from "../../../../utils/errors-server.js";
|
|
11
11
|
import { validateAndJoinPath } from "../../../utils/path-security.js";
|
|
12
12
|
import { getServerLogger } from "../../../../logging/index.js";
|
|
13
13
|
import { modelInputToSrcSchema } from "../../../../schemas/index.js";
|
|
@@ -74,8 +74,20 @@ function buildResult(pathOrResult, sourceType) {
|
|
|
74
74
|
}
|
|
75
75
|
return { path: pathOrResult, sourceType };
|
|
76
76
|
}
|
|
77
|
-
async function resolveModelPathCore(modelSrc, progressCallback, seed, mode, hooks) {
|
|
77
|
+
async function resolveModelPathCore(modelSrc, progressCallback, seed, mode, signal, hooks) {
|
|
78
|
+
if (signal?.aborted) {
|
|
79
|
+
throw new InferenceCancelledError(hooks?.requestBinding?.requestId ?? "unknown");
|
|
80
|
+
}
|
|
78
81
|
const srcString = modelInputToSrcSchema.parse(modelSrc);
|
|
82
|
+
// Empty modelSrc is reserved for plugins that ship bundled weights
|
|
83
|
+
// (e.g. `@qvac/classification-ggml`). The handler skips this resolver
|
|
84
|
+
// for them when `skipPrimaryModelPathValidation` is set, but if it
|
|
85
|
+
// somehow gets called we return an empty path so the plugin's
|
|
86
|
+
// `params.modelPath` falls through to undefined instead of being set
|
|
87
|
+
// to the cache directory itself.
|
|
88
|
+
if (srcString === "") {
|
|
89
|
+
return { path: "", sourceType: "filesystem" };
|
|
90
|
+
}
|
|
79
91
|
// Parse hyperdrive URLs if present
|
|
80
92
|
let hyperdriveKey;
|
|
81
93
|
let actualModelSrc = srcString;
|
|
@@ -137,10 +149,10 @@ async function resolveModelPathCore(modelSrc, progressCallback, seed, mode, hook
|
|
|
137
149
|
}
|
|
138
150
|
return { path: resolvedPath, sourceType: "filesystem" };
|
|
139
151
|
}
|
|
140
|
-
export async function resolveModelPath(modelSrc, progressCallback, seed, hooks) {
|
|
141
|
-
const result = await resolveModelPathCore(modelSrc, progressCallback, seed, "base", hooks);
|
|
152
|
+
export async function resolveModelPath(modelSrc, progressCallback, seed, signal, hooks) {
|
|
153
|
+
const result = await resolveModelPathCore(modelSrc, progressCallback, seed, "base", signal, hooks);
|
|
142
154
|
return result.path;
|
|
143
155
|
}
|
|
144
|
-
export async function resolveModelPathWithStats(modelSrc, progressCallback, seed, hooks) {
|
|
145
|
-
return resolveModelPathCore(modelSrc, progressCallback, seed, "stats", hooks);
|
|
156
|
+
export async function resolveModelPathWithStats(modelSrc, progressCallback, seed, signal, hooks) {
|
|
157
|
+
return resolveModelPathCore(modelSrc, progressCallback, seed, "stats", signal, hooks);
|
|
146
158
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { SourceType } from "../../../../schemas/index";
|
|
2
|
+
import type { AbortSignal } from "bare-abort-controller";
|
|
3
|
+
import type { DisposableScope } from "../../../bare/runtime/disposable-scope";
|
|
2
4
|
export interface DownloadStats {
|
|
3
5
|
downloadTimeMs?: number;
|
|
4
6
|
totalBytesDownloaded?: number;
|
|
@@ -16,12 +18,34 @@ export interface DownloadResult {
|
|
|
16
18
|
path: string;
|
|
17
19
|
stats?: DownloadStats;
|
|
18
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Internal request binding threaded through `DownloadHooks` so the
|
|
23
|
+
* download manager's `startOrJoinDownload` can register a per-subscriber
|
|
24
|
+
* cancel hook against the caller's `RequestContext`. The binding's
|
|
25
|
+
* fields mirror the registry context's surface area: `signal` is wired
|
|
26
|
+
* to a subscriber-removing listener, `scope` registers the idempotent
|
|
27
|
+
* cleanup, and `requestId` lets `cancelTransfer` (legacy entry point)
|
|
28
|
+
* route cancels through `registry.cancel(...)` rather than reaching
|
|
29
|
+
* into the transfer directly.
|
|
30
|
+
*/
|
|
31
|
+
export interface DownloadRequestBinding {
|
|
32
|
+
signal: AbortSignal;
|
|
33
|
+
scope: DisposableScope;
|
|
34
|
+
requestId: string;
|
|
35
|
+
}
|
|
19
36
|
export interface DownloadHooks {
|
|
20
37
|
onDownloadKey?: (key: string) => void;
|
|
21
38
|
markCacheHit?: () => void;
|
|
22
39
|
markCacheMiss?: () => void;
|
|
23
40
|
markSharedTransfer?: () => void;
|
|
24
41
|
addChecksumValidationTimeMs?: (durationMs: number) => void;
|
|
42
|
+
/**
|
|
43
|
+
* When set, `startOrJoinDownload` attaches a per-subscriber cancel
|
|
44
|
+
* listener bound to this request. `registry.cancel({ requestId })`
|
|
45
|
+
* aborts only this subscriber; the transfer keeps running for siblings
|
|
46
|
+
* joined on the same `downloadKey` until the last subscriber leaves.
|
|
47
|
+
*/
|
|
48
|
+
requestBinding?: DownloadRequestBinding;
|
|
25
49
|
}
|
|
26
50
|
export interface LoadModelProfilingMeta {
|
|
27
51
|
sourceType?: string;
|
|
@@ -1,4 +1,59 @@
|
|
|
1
|
-
|
|
1
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
2
|
+
if (value !== null && value !== void 0) {
|
|
3
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
4
|
+
var dispose, inner;
|
|
5
|
+
if (async) {
|
|
6
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
7
|
+
dispose = value[Symbol.asyncDispose];
|
|
8
|
+
}
|
|
9
|
+
if (dispose === void 0) {
|
|
10
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
11
|
+
dispose = value[Symbol.dispose];
|
|
12
|
+
if (async) inner = dispose;
|
|
13
|
+
}
|
|
14
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
16
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
17
|
+
}
|
|
18
|
+
else if (async) {
|
|
19
|
+
env.stack.push({ async: true });
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
};
|
|
23
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
24
|
+
return function (env) {
|
|
25
|
+
function fail(e) {
|
|
26
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
27
|
+
env.hasError = true;
|
|
28
|
+
}
|
|
29
|
+
var r, s = 0;
|
|
30
|
+
function next() {
|
|
31
|
+
while (r = env.stack.pop()) {
|
|
32
|
+
try {
|
|
33
|
+
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
34
|
+
if (r.dispose) {
|
|
35
|
+
var result = r.dispose.call(r.value);
|
|
36
|
+
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
37
|
+
}
|
|
38
|
+
else s |= 1;
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
fail(e);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
45
|
+
if (env.hasError) throw env.error;
|
|
46
|
+
}
|
|
47
|
+
return next();
|
|
48
|
+
};
|
|
49
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
50
|
+
var e = new Error(message);
|
|
51
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
|
+
});
|
|
53
|
+
import { chunk, ingest, reindex, saveEmbeddings, search, deleteEmbeddings, listWorkspaces, closeWorkspace, deleteWorkspace, DEFAULT_WORKSPACE, getActiveRagRequest, setActiveRagRequest, clearActiveRagRequest, } from "../../bare/rag-hyperdb/index.js";
|
|
54
|
+
import { getRequestRegistry, withRequestContext, } from "../../bare/runtime/index.js";
|
|
55
|
+
import { generateServerRequestId } from "../../bare/runtime/request-id.js";
|
|
56
|
+
import { getServerLogger } from "../../../logging/index.js";
|
|
2
57
|
import { profileReplyHandler, registerOperationMetrics, } from "../profiling/index.js";
|
|
3
58
|
registerOperationMetrics({
|
|
4
59
|
op: "rag",
|
|
@@ -20,8 +75,7 @@ registerOperationMetrics({
|
|
|
20
75
|
return Object.keys(gauges).length > 0 ? gauges : undefined;
|
|
21
76
|
},
|
|
22
77
|
});
|
|
23
|
-
function createHandlerOptions(operation, workspace, onProgress) {
|
|
24
|
-
const signal = registerRagOperation(workspace, operation);
|
|
78
|
+
function createHandlerOptions(operation, workspace, signal, onProgress) {
|
|
25
79
|
const options = { signal };
|
|
26
80
|
if (onProgress) {
|
|
27
81
|
options.onProgress = (stage, current, total) => onProgress({
|
|
@@ -42,6 +96,37 @@ function omitOnProgress(obj) {
|
|
|
42
96
|
void withProgress;
|
|
43
97
|
return rest;
|
|
44
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Begin a registry-tracked RAG context with workspace-level pre-emption.
|
|
101
|
+
*
|
|
102
|
+
* Workspace-level admission lives in the dispatcher rather than as a
|
|
103
|
+
* registry policy primitive (it's a dispatch concern, not a registry
|
|
104
|
+
* `kind` admission rule). The sequence is **cancel-prior → begin-new**:
|
|
105
|
+
* if another RAG operation is already running on the same workspace,
|
|
106
|
+
* cancel it first, then begin the new context. Reversing the order
|
|
107
|
+
* would cancel the just-installed context.
|
|
108
|
+
*
|
|
109
|
+
* The workspace → requestId map is updated after `begin(...)` succeeds
|
|
110
|
+
* and cleared on scope unwind via `scope.defer(...)`, with a
|
|
111
|
+
* "still mine?" guard so an older op's deferred cleanup cannot stomp
|
|
112
|
+
* a newer op's mapping.
|
|
113
|
+
*/
|
|
114
|
+
function beginRagContext(workspace, requestId) {
|
|
115
|
+
const registry = getRequestRegistry();
|
|
116
|
+
const prev = getActiveRagRequest(workspace);
|
|
117
|
+
if (prev !== undefined && prev !== requestId) {
|
|
118
|
+
registry.cancel({ requestId: prev, reason: "rag-workspace-preempt" });
|
|
119
|
+
}
|
|
120
|
+
const ctx = registry.begin({
|
|
121
|
+
requestId,
|
|
122
|
+
kind: "rag",
|
|
123
|
+
});
|
|
124
|
+
setActiveRagRequest(workspace, requestId);
|
|
125
|
+
ctx.scope.defer(() => {
|
|
126
|
+
clearActiveRagRequest(workspace, requestId);
|
|
127
|
+
});
|
|
128
|
+
return ctx;
|
|
129
|
+
}
|
|
45
130
|
export async function handleRag(request, onProgress) {
|
|
46
131
|
return profileReplyHandler({ op: "rag", request }, async () => handleRagInternal(request, onProgress));
|
|
47
132
|
}
|
|
@@ -57,10 +142,15 @@ async function handleRagInternal(request, onProgress) {
|
|
|
57
142
|
};
|
|
58
143
|
}
|
|
59
144
|
case "ingest": {
|
|
60
|
-
const
|
|
61
|
-
const handlerOptions = createHandlerOptions("ingest", workspace, onProgress);
|
|
62
|
-
const params = omitOnProgress(request);
|
|
145
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
63
146
|
try {
|
|
147
|
+
const workspace = request.workspace ?? DEFAULT_WORKSPACE;
|
|
148
|
+
const requestId = request.requestId ?? generateServerRequestId();
|
|
149
|
+
const ctx = __addDisposableResource(env_1, beginRagContext(workspace, requestId), true);
|
|
150
|
+
const log = withRequestContext(getServerLogger(), ctx);
|
|
151
|
+
log.debug("ingest start");
|
|
152
|
+
const handlerOptions = createHandlerOptions("ingest", workspace, ctx.signal, onProgress);
|
|
153
|
+
const params = omitOnProgress(request);
|
|
64
154
|
const result = await ingest(params, handlerOptions);
|
|
65
155
|
return {
|
|
66
156
|
type: "rag",
|
|
@@ -70,15 +160,26 @@ async function handleRagInternal(request, onProgress) {
|
|
|
70
160
|
droppedIndices: result.droppedIndices,
|
|
71
161
|
};
|
|
72
162
|
}
|
|
163
|
+
catch (e_1) {
|
|
164
|
+
env_1.error = e_1;
|
|
165
|
+
env_1.hasError = true;
|
|
166
|
+
}
|
|
73
167
|
finally {
|
|
74
|
-
|
|
168
|
+
const result_1 = __disposeResources(env_1);
|
|
169
|
+
if (result_1)
|
|
170
|
+
await result_1;
|
|
75
171
|
}
|
|
76
172
|
}
|
|
77
173
|
case "saveEmbeddings": {
|
|
78
|
-
const
|
|
79
|
-
const handlerOptions = createHandlerOptions("saveEmbeddings", workspace, onProgress);
|
|
80
|
-
const params = omitOnProgress(request);
|
|
174
|
+
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
81
175
|
try {
|
|
176
|
+
const workspace = request.workspace ?? DEFAULT_WORKSPACE;
|
|
177
|
+
const requestId = request.requestId ?? generateServerRequestId();
|
|
178
|
+
const ctx = __addDisposableResource(env_2, beginRagContext(workspace, requestId), true);
|
|
179
|
+
const log = withRequestContext(getServerLogger(), ctx);
|
|
180
|
+
log.debug("saveEmbeddings start");
|
|
181
|
+
const handlerOptions = createHandlerOptions("saveEmbeddings", workspace, ctx.signal, onProgress);
|
|
182
|
+
const params = omitOnProgress(request);
|
|
82
183
|
const processed = await saveEmbeddings(params, handlerOptions);
|
|
83
184
|
return {
|
|
84
185
|
type: "rag",
|
|
@@ -87,8 +188,14 @@ async function handleRagInternal(request, onProgress) {
|
|
|
87
188
|
processed,
|
|
88
189
|
};
|
|
89
190
|
}
|
|
191
|
+
catch (e_2) {
|
|
192
|
+
env_2.error = e_2;
|
|
193
|
+
env_2.hasError = true;
|
|
194
|
+
}
|
|
90
195
|
finally {
|
|
91
|
-
|
|
196
|
+
const result_2 = __disposeResources(env_2);
|
|
197
|
+
if (result_2)
|
|
198
|
+
await result_2;
|
|
92
199
|
}
|
|
93
200
|
}
|
|
94
201
|
case "search": {
|
|
@@ -109,10 +216,15 @@ async function handleRagInternal(request, onProgress) {
|
|
|
109
216
|
};
|
|
110
217
|
}
|
|
111
218
|
case "reindex": {
|
|
112
|
-
const
|
|
113
|
-
const handlerOptions = createHandlerOptions("reindex", workspace, onProgress);
|
|
114
|
-
const params = omitOnProgress(request);
|
|
219
|
+
const env_3 = { stack: [], error: void 0, hasError: false };
|
|
115
220
|
try {
|
|
221
|
+
const workspace = request.workspace ?? DEFAULT_WORKSPACE;
|
|
222
|
+
const requestId = request.requestId ?? generateServerRequestId();
|
|
223
|
+
const ctx = __addDisposableResource(env_3, beginRagContext(workspace, requestId), true);
|
|
224
|
+
const log = withRequestContext(getServerLogger(), ctx);
|
|
225
|
+
log.debug("reindex start");
|
|
226
|
+
const handlerOptions = createHandlerOptions("reindex", workspace, ctx.signal, onProgress);
|
|
227
|
+
const params = omitOnProgress(request);
|
|
116
228
|
const result = await reindex(params, handlerOptions);
|
|
117
229
|
return {
|
|
118
230
|
type: "rag",
|
|
@@ -121,8 +233,14 @@ async function handleRagInternal(request, onProgress) {
|
|
|
121
233
|
result,
|
|
122
234
|
};
|
|
123
235
|
}
|
|
236
|
+
catch (e_3) {
|
|
237
|
+
env_3.error = e_3;
|
|
238
|
+
env_3.hasError = true;
|
|
239
|
+
}
|
|
124
240
|
finally {
|
|
125
|
-
|
|
241
|
+
const result_3 = __disposeResources(env_3);
|
|
242
|
+
if (result_3)
|
|
243
|
+
await result_3;
|
|
126
244
|
}
|
|
127
245
|
}
|
|
128
246
|
case "listWorkspaces": {
|
|
@@ -242,6 +242,29 @@ registerOperationMetrics({
|
|
|
242
242
|
return Object.keys(gauges).length > 0 ? gauges : undefined;
|
|
243
243
|
},
|
|
244
244
|
});
|
|
245
|
+
registerOperationMetrics({
|
|
246
|
+
op: "videoStream",
|
|
247
|
+
kind: "handler",
|
|
248
|
+
getTags: (req) => (req.modelId ? { modelId: req.modelId } : {}),
|
|
249
|
+
fromFinalChunk: (res) => {
|
|
250
|
+
if (!res.stats)
|
|
251
|
+
return undefined;
|
|
252
|
+
const gauges = {};
|
|
253
|
+
if (res.stats.generationMs !== undefined)
|
|
254
|
+
gauges["generationMs"] = res.stats.generationMs;
|
|
255
|
+
if (res.stats.totalSteps !== undefined)
|
|
256
|
+
gauges["totalSteps"] = res.stats.totalSteps;
|
|
257
|
+
if (res.stats.totalVideos !== undefined)
|
|
258
|
+
gauges["totalVideos"] = res.stats.totalVideos;
|
|
259
|
+
if (res.stats.totalVideoFrames !== undefined)
|
|
260
|
+
gauges["totalVideoFrames"] = res.stats.totalVideoFrames;
|
|
261
|
+
if (res.stats.videoFrames !== undefined)
|
|
262
|
+
gauges["videoFrames"] = res.stats.videoFrames;
|
|
263
|
+
if (res.stats.fps !== undefined)
|
|
264
|
+
gauges["fps"] = res.stats.fps;
|
|
265
|
+
return Object.keys(gauges).length > 0 ? gauges : undefined;
|
|
266
|
+
},
|
|
267
|
+
});
|
|
245
268
|
registerOperationMetrics({
|
|
246
269
|
op: "pluginInvoke",
|
|
247
270
|
kind: "handler",
|
|
@@ -34,6 +34,14 @@ const DIALECT_SPECS = {
|
|
|
34
34
|
"<|return|>",
|
|
35
35
|
],
|
|
36
36
|
},
|
|
37
|
+
qwen35: {
|
|
38
|
+
// Same <tool_call>…</tool_call> framing as hermes; inner content is XML.
|
|
39
|
+
toolFrames: [{ open: "<tool_call>", close: "</tool_call>" }],
|
|
40
|
+
},
|
|
41
|
+
gemma4: {
|
|
42
|
+
toolFrames: [{ open: "<|tool_call>", close: "<tool_call|>" }],
|
|
43
|
+
thinkingFrames: [{ open: "<|channel>thought", close: "<channel|>" }],
|
|
44
|
+
},
|
|
37
45
|
};
|
|
38
46
|
// Capture-gated reasoning marker — the generic `<think>...</think>`
|
|
39
47
|
// convention used by reasoning-tuned models. When the gate is off the
|
|
@@ -14,7 +14,7 @@ export function transformConfigForReload(modelType, config) {
|
|
|
14
14
|
case ModelType.llamacppCompletion:
|
|
15
15
|
case ModelType.llamacppEmbedding:
|
|
16
16
|
case ModelType.nmtcppTranslation:
|
|
17
|
-
case ModelType.
|
|
17
|
+
case ModelType.ttsGgml:
|
|
18
18
|
// Return as-is for now
|
|
19
19
|
return config;
|
|
20
20
|
default:
|
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
export function detectToolDialectFromName(name, path) {
|
|
7
7
|
const basename = path.toLowerCase().split(/[/\\]/).pop() ?? "";
|
|
8
8
|
const tag = `${(name ?? "").toLowerCase()}|${basename}`;
|
|
9
|
+
if (/qwen3[._-]?[56](?![a-z0-9])/.test(tag))
|
|
10
|
+
return "qwen35";
|
|
11
|
+
if (/gemma[-_]?4(?=[^a-z0-9]|$)/.test(tag))
|
|
12
|
+
return "gemma4";
|
|
9
13
|
if (/gpt[_-]?oss/.test(tag))
|
|
10
14
|
return "harmony";
|
|
11
15
|
if (/lfm[_-]?\d/.test(tag))
|
|
@@ -3,6 +3,8 @@ import { parseGemmaFormat, parseGenericFormat, parseLlamacppFormat, } from "./pa
|
|
|
3
3
|
import { parseHermesFormat } from "./parsers/hermes.js";
|
|
4
4
|
import { parsePythonicFormat } from "./parsers/pythonic.js";
|
|
5
5
|
import { parseHarmonyFormat } from "./parsers/harmony.js";
|
|
6
|
+
import { parseQwen35Format } from "./parsers/qwen35.js";
|
|
7
|
+
import { parseGemma4NativeFormat } from "./parsers/gemma4native.js";
|
|
6
8
|
function pickFormatParsers(dialect) {
|
|
7
9
|
switch (dialect) {
|
|
8
10
|
case "pythonic":
|
|
@@ -15,13 +17,26 @@ function pickFormatParsers(dialect) {
|
|
|
15
17
|
return [parseGemmaFormat, parseLlamacppFormat];
|
|
16
18
|
case "harmony":
|
|
17
19
|
return [parseHarmonyFormat];
|
|
20
|
+
case "qwen35":
|
|
21
|
+
// Hermes fallback: Qwen3.5 templates sometimes emit OpenAI-style JSON
|
|
22
|
+
// when the native XML format fails; Hermes chain recovers those.
|
|
23
|
+
return [parseQwen35Format, parseHermesFormat];
|
|
24
|
+
case "gemma4":
|
|
25
|
+
// No JSON fallback: Gemma4 emits only its native channel-thought dialect
|
|
26
|
+
// and never falls back to JSON-envelope formats.
|
|
27
|
+
return [parseGemma4NativeFormat];
|
|
18
28
|
default:
|
|
19
|
-
//
|
|
29
|
+
// Gemma4 first: `<|tool_call>` is uniquely distinctive and can't
|
|
20
30
|
// false-match other dialects.
|
|
31
|
+
// Harmony next: `to=functions.` is also uniquely Harmony.
|
|
32
|
+
// Qwen35 before Hermes: defers to Hermes when JSON is inside <tool_call>,
|
|
33
|
+
// so the XML path is recovered without breaking Hermes-JSON payloads.
|
|
21
34
|
// Pythonic last: its bare `[name(...)]` form can match payloads that
|
|
22
35
|
// look like other dialects.
|
|
23
36
|
return [
|
|
37
|
+
parseGemma4NativeFormat,
|
|
24
38
|
parseHarmonyFormat,
|
|
39
|
+
parseQwen35Format,
|
|
25
40
|
parseHermesFormat,
|
|
26
41
|
parseGemmaFormat,
|
|
27
42
|
parseLlamacppFormat,
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { generateStableToolCallId, validateToolArguments, } from "../shared.js";
|
|
2
|
+
// Transliterates Gemma 4's JS-literal argument body to valid JSON so it can
|
|
3
|
+
// be parsed with JSON.parse. The body uses:
|
|
4
|
+
// - <|"|>...<|"|> instead of "..." for string values
|
|
5
|
+
// - bare (unquoted) object keys
|
|
6
|
+
// Strategy: split by <|"|> tokens so structural parts (even indices) and
|
|
7
|
+
// string value parts (odd indices) are processed separately, preventing
|
|
8
|
+
// the key-quoting regex from matching `, key:` patterns inside string values.
|
|
9
|
+
function gemmaArgsToJson(argsRaw) {
|
|
10
|
+
const parts = ("{" + argsRaw + "}").split(/<\|"\|>/);
|
|
11
|
+
return parts
|
|
12
|
+
.map((part, i) => i % 2 === 0
|
|
13
|
+
? part.replace(/([{,]\s*)([A-Za-z_][\w-]*)\s*:/g, '$1"$2":')
|
|
14
|
+
: '"' + part.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/[\x00-\x1f]/g, (c) => `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`) + '"')
|
|
15
|
+
.join("");
|
|
16
|
+
}
|
|
17
|
+
// Parses Gemma 4's native tool-call dialect:
|
|
18
|
+
// <|tool_call>call:NAME{key:<|"|>val<|"|>,key2:bareNum,...}<tool_call|>
|
|
19
|
+
// Keys are bare identifiers; string values are wrapped in <|"|>...<|"|>;
|
|
20
|
+
// numbers/booleans are bare literals; nested objects/arrays use JS-literal
|
|
21
|
+
// syntax throughout. Transliterates to JSON then parses.
|
|
22
|
+
export function parseGemma4NativeFormat(text, tools) {
|
|
23
|
+
const toolCalls = [];
|
|
24
|
+
const errors = [];
|
|
25
|
+
if (!text.includes("<|tool_call>")) {
|
|
26
|
+
return { matched: false, toolCalls, errors };
|
|
27
|
+
}
|
|
28
|
+
const callRegex = /<\|tool_call>call:([A-Za-z_][\w-]*)\{([\s\S]*?)\}<tool_call\|>/g;
|
|
29
|
+
const matches = Array.from(text.matchAll(callRegex));
|
|
30
|
+
if (matches.length === 0)
|
|
31
|
+
return { matched: false, toolCalls, errors };
|
|
32
|
+
for (const match of matches) {
|
|
33
|
+
const name = match[1];
|
|
34
|
+
const argsRaw = match[2];
|
|
35
|
+
let args;
|
|
36
|
+
try {
|
|
37
|
+
args = JSON.parse(gemmaArgsToJson(argsRaw));
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
errors.push({
|
|
41
|
+
code: "PARSE_ERROR",
|
|
42
|
+
message: `Failed to parse Gemma 4 tool call arguments: ${err instanceof Error ? err.message : String(err)}`,
|
|
43
|
+
raw: match[0],
|
|
44
|
+
});
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const validation = validateToolArguments(name, args, tools);
|
|
48
|
+
if (!validation.isValid && validation.error) {
|
|
49
|
+
errors.push({ ...validation.error, raw: match[0] });
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
toolCalls.push({
|
|
53
|
+
id: generateStableToolCallId(name, args),
|
|
54
|
+
name,
|
|
55
|
+
arguments: args,
|
|
56
|
+
raw: match[0],
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return { matched: true, toolCalls, errors };
|
|
60
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { generateStableToolCallId, validateToolArguments, } from "../shared.js";
|
|
2
|
+
// Coerce raw parameter text to the type declared in the tool's JSON schema.
|
|
3
|
+
// String values are raw (not JSON-quoted); arrays/objects are valid JSON.
|
|
4
|
+
function coerceParamValue(raw, schema) {
|
|
5
|
+
const trimmed = raw.trim();
|
|
6
|
+
if (!schema?.type)
|
|
7
|
+
return trimmed;
|
|
8
|
+
switch (schema.type) {
|
|
9
|
+
case "number": {
|
|
10
|
+
if (trimmed.length === 0)
|
|
11
|
+
throw new Error(`invalid numeric value: ""`);
|
|
12
|
+
const n = Number(trimmed);
|
|
13
|
+
if (Number.isNaN(n))
|
|
14
|
+
throw new Error(`invalid numeric value: "${trimmed}"`);
|
|
15
|
+
return n;
|
|
16
|
+
}
|
|
17
|
+
case "integer": {
|
|
18
|
+
if (trimmed.length === 0)
|
|
19
|
+
throw new Error(`invalid integer value: ""`);
|
|
20
|
+
const n = Number(trimmed);
|
|
21
|
+
if (Number.isNaN(n) || !Number.isInteger(n))
|
|
22
|
+
throw new Error(`invalid integer value: "${trimmed}"`);
|
|
23
|
+
return n;
|
|
24
|
+
}
|
|
25
|
+
case "boolean":
|
|
26
|
+
if (trimmed === "true")
|
|
27
|
+
return true;
|
|
28
|
+
if (trimmed === "false")
|
|
29
|
+
return false;
|
|
30
|
+
throw new Error(`invalid boolean value: "${trimmed}"`);
|
|
31
|
+
case "array":
|
|
32
|
+
case "object":
|
|
33
|
+
return JSON.parse(trimmed);
|
|
34
|
+
default:
|
|
35
|
+
return trimmed;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Parses Qwen3.5/3.6 Pythonic-XML tool-call format:
|
|
39
|
+
// <tool_call>
|
|
40
|
+
// <function=NAME>
|
|
41
|
+
// <parameter=KEY>VALUE</parameter>
|
|
42
|
+
// </function>
|
|
43
|
+
// </tool_call>
|
|
44
|
+
// String parameter values are raw text (not JSON-quoted); arrays/objects
|
|
45
|
+
// are JSON. Type coercion uses the tool schema; unknown params pass through.
|
|
46
|
+
export function parseQwen35Format(text, tools) {
|
|
47
|
+
const toolCalls = [];
|
|
48
|
+
const errors = [];
|
|
49
|
+
if (!text.includes("<tool_call>")) {
|
|
50
|
+
return { matched: false, toolCalls, errors };
|
|
51
|
+
}
|
|
52
|
+
const outerRegex = /<tool_call>([\s\S]*?)<\/tool_call>/g;
|
|
53
|
+
const outerMatches = Array.from(text.matchAll(outerRegex));
|
|
54
|
+
if (outerMatches.length === 0)
|
|
55
|
+
return { matched: false, toolCalls, errors };
|
|
56
|
+
// If no match contains XML function syntax, check if this is JSON format
|
|
57
|
+
// (defer to hermes) or just malformed content (surface as PARSE_ERROR).
|
|
58
|
+
if (!outerMatches.some((m) => m[1].includes("<function="))) {
|
|
59
|
+
const looksLikeJson = outerMatches.some((m) => {
|
|
60
|
+
const inner = m[1].trim();
|
|
61
|
+
return inner.startsWith("{") || inner.startsWith("[");
|
|
62
|
+
});
|
|
63
|
+
if (looksLikeJson)
|
|
64
|
+
return { matched: false, toolCalls, errors };
|
|
65
|
+
return {
|
|
66
|
+
matched: true,
|
|
67
|
+
toolCalls,
|
|
68
|
+
errors: outerMatches.map((m) => ({
|
|
69
|
+
code: "PARSE_ERROR",
|
|
70
|
+
message: "Qwen3.5 tool call missing <function=NAME>...</function>",
|
|
71
|
+
raw: m[1].trim(),
|
|
72
|
+
})),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
for (const outerMatch of outerMatches) {
|
|
76
|
+
const inner = outerMatch[1].trim();
|
|
77
|
+
const fnMatch = /<function=([^>\s]+)\s*>([\s\S]*?)<\/function>/i.exec(inner);
|
|
78
|
+
if (!fnMatch) {
|
|
79
|
+
errors.push({
|
|
80
|
+
code: "PARSE_ERROR",
|
|
81
|
+
message: "Qwen3.5 tool call missing <function=NAME>...</function>",
|
|
82
|
+
raw: inner,
|
|
83
|
+
});
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const name = fnMatch[1].trim();
|
|
87
|
+
const paramsBlock = fnMatch[2];
|
|
88
|
+
const tool = tools.find((t) => t.name === name);
|
|
89
|
+
const schemaProperties = tool?.parameters?.properties ?? {};
|
|
90
|
+
const args = {};
|
|
91
|
+
let parseError;
|
|
92
|
+
try {
|
|
93
|
+
const paramRegex = /<parameter=([^>\s]+)\s*>([\s\S]*?)<\/parameter>/gi;
|
|
94
|
+
let pm;
|
|
95
|
+
while ((pm = paramRegex.exec(paramsBlock)) !== null) {
|
|
96
|
+
const paramName = pm[1].trim();
|
|
97
|
+
args[paramName] = coerceParamValue(pm[2], schemaProperties[paramName]);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
parseError = err instanceof Error ? err.message : String(err);
|
|
102
|
+
}
|
|
103
|
+
if (parseError !== undefined) {
|
|
104
|
+
errors.push({ code: "PARSE_ERROR", message: parseError, raw: inner });
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const validation = validateToolArguments(name, args, tools);
|
|
108
|
+
if (!validation.isValid && validation.error) {
|
|
109
|
+
errors.push({ ...validation.error, raw: inner });
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
toolCalls.push({
|
|
113
|
+
id: generateStableToolCallId(name, args),
|
|
114
|
+
name,
|
|
115
|
+
arguments: args,
|
|
116
|
+
raw: inner,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return { matched: true, toolCalls, errors };
|
|
120
|
+
}
|