@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,8 +1,9 @@
|
|
|
1
1
|
import { TOOLS_MODE } from "../../../../../schemas/tools.js";
|
|
2
|
-
import { logCacheDisabled, logCacheInit, logCacheSave,
|
|
3
|
-
import {
|
|
2
|
+
import { logCacheDisabled, logCacheInit, logCacheSave, logMessagesToAddon, } from "./cache-logger.js";
|
|
3
|
+
import { extractSystemPrompt, getCurrentCacheInfo, } from "../../../ops/kv-cache-utils.js";
|
|
4
4
|
import { getModel, getModelConfig, } from "../../../registry/model-registry.js";
|
|
5
|
-
import {
|
|
5
|
+
import { decideCachedHistorySlice } from "./kv-cache-state.js";
|
|
6
|
+
import { createKvCacheSession, generateConfigHash, } from "./kv-cache-session.js";
|
|
6
7
|
import { appendToolsToHistory, detectToolDialect, prependToolsToHistory, } from "../../../../utils/tool-integration.js";
|
|
7
8
|
import { parseToolCalls } from "../../../../utils/tools/index.js";
|
|
8
9
|
import { getResponseFormatJsonSchema } from "../../../../utils/response-format.js";
|
|
@@ -11,37 +12,23 @@ import { getServerLogger } from "../../../../../logging/index.js";
|
|
|
11
12
|
import { AttachmentNotFoundError } from "../../../../../utils/errors-server.js";
|
|
12
13
|
import { nowMs } from "../../../../../profiling/index.js";
|
|
13
14
|
import { buildStreamResult, hasDefinedValues, } from "../../../../../profiling/model-execution.js";
|
|
14
|
-
import fs
|
|
15
|
-
import path from "bare-path";
|
|
15
|
+
import fs from "bare-fs";
|
|
16
16
|
const logger = getServerLogger();
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
// drop the `access()` probe and wrap the `model.run()` call in a real
|
|
33
|
-
// try/catch that forwards the error to `logCacheSaveError`.
|
|
34
|
-
async function recordCacheSaveCount(cachePath, messageCount) {
|
|
35
|
-
try {
|
|
36
|
-
await fsPromises.access(cachePath);
|
|
37
|
-
cachedMessageCounts.set(cachePath, messageCount);
|
|
38
|
-
return true;
|
|
39
|
-
}
|
|
40
|
-
catch (err) {
|
|
41
|
-
cachedMessageCounts.delete(cachePath);
|
|
42
|
-
logCacheSaveError(cachePath, err);
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
17
|
+
/**
|
|
18
|
+
* Decide whether a completed turn earned the right to record its kv-cache
|
|
19
|
+
* boundary. A `savedCount` is only safe to write when the turn ran to
|
|
20
|
+
* completion AND produced at least one token — anything else (cancelled
|
|
21
|
+
* mid-decode, zero-token reply, early EOS) leaves the on-disk cache file
|
|
22
|
+
* in an unknown state relative to `history.length + 1`, and a stale entry
|
|
23
|
+
* would slice the next turn's history down to an empty payload.
|
|
24
|
+
*
|
|
25
|
+
* Replaces the pre-0.11.0 `shouldRecordSavedCount(wasCancelled, ...)` with
|
|
26
|
+
* a signal-driven check that reads directly from the request's
|
|
27
|
+
* `AbortSignal`. The local helper keeps the call sites in
|
|
28
|
+
* `completion-stream.ts` honest without importing the registry every time.
|
|
29
|
+
*/
|
|
30
|
+
function shouldCommitTurn(signal, producedTokens) {
|
|
31
|
+
return !signal.aborted && producedTokens;
|
|
45
32
|
}
|
|
46
33
|
function transformMessage(message) {
|
|
47
34
|
const transformed = [];
|
|
@@ -100,9 +87,7 @@ async function initSystemPromptCache(model, cachePathToUse, systemPromptToUse, c
|
|
|
100
87
|
const primeResponse = await runModel(model, primeMessages, {
|
|
101
88
|
cacheKey: cachePathToUse,
|
|
102
89
|
saveCacheToDisk: true,
|
|
103
|
-
|
|
104
|
-
primeResponse.once("output", () => {
|
|
105
|
-
void primeResponse.cancel();
|
|
90
|
+
prefill: true,
|
|
106
91
|
});
|
|
107
92
|
await primeResponse.await();
|
|
108
93
|
}
|
|
@@ -117,7 +102,8 @@ async function initSystemPromptCache(model, cachePathToUse, systemPromptToUse, c
|
|
|
117
102
|
* consumer pushing both an assistant transcript and a follow-up user
|
|
118
103
|
* message between completions) all reaches the model.
|
|
119
104
|
* - Cache hit with a stale/missing `savedCount`: fall back to the full
|
|
120
|
-
* non-system history.
|
|
105
|
+
* non-system history. The session is told (`dropStaleSavedCount`) so
|
|
106
|
+
* the bad boundary doesn't propagate into the next turn.
|
|
121
107
|
*
|
|
122
108
|
* Dynamic mode (`tools` argument set):
|
|
123
109
|
* - The addon anchors the tool block after the last user message and
|
|
@@ -133,7 +119,7 @@ async function initSystemPromptCache(model, cachePathToUse, systemPromptToUse, c
|
|
|
133
119
|
* the new prompt, then re-anchor the tool block.
|
|
134
120
|
* * otherwise: send just the last message + tool block.
|
|
135
121
|
*/
|
|
136
|
-
function prepareMessagesForCache(
|
|
122
|
+
function prepareMessagesForCache(session, turn, cacheExists, history, tools) {
|
|
137
123
|
const addTools = tools?.length ? transformMessages(tools) : [];
|
|
138
124
|
const dynamic = addTools.length > 0;
|
|
139
125
|
if (!(cacheExists && history.length > 0)) {
|
|
@@ -141,16 +127,18 @@ function prepareMessagesForCache(cachePathToUse, cacheExists, history, tools) {
|
|
|
141
127
|
return [...transformMessages(historyWithoutSystem), ...addTools];
|
|
142
128
|
}
|
|
143
129
|
if (!dynamic) {
|
|
144
|
-
// Static path — slice from the
|
|
130
|
+
// Static path — slice from the turn's `savedCount` so callers can
|
|
145
131
|
// stage multiple messages between completions. `decideCachedHistorySlice`
|
|
146
132
|
// also guards against the QVAC-17780 stale-count regression: if the
|
|
147
133
|
// saved boundary would slice the history down to an empty payload
|
|
148
134
|
// (e.g. after a cancelled mid-decode), it falls back to the full
|
|
149
135
|
// non-system history and signals the caller to drop the bad entry.
|
|
150
|
-
|
|
151
|
-
|
|
136
|
+
// The session owns the entry; `dropStaleSavedCount` clears it
|
|
137
|
+
// without touching the on-disk file (the file is still trustworthy
|
|
138
|
+
// — only the boundary count is wrong).
|
|
139
|
+
const { messages, clearStaleCount } = decideCachedHistorySlice(turn.savedCount, cacheExists, history);
|
|
152
140
|
if (clearStaleCount) {
|
|
153
|
-
|
|
141
|
+
session.dropStaleSavedCount(turn);
|
|
154
142
|
}
|
|
155
143
|
return transformMessages(messages);
|
|
156
144
|
}
|
|
@@ -217,6 +205,9 @@ async function* processModelResponse(model, messagesToSend, tools, generationPar
|
|
|
217
205
|
...(responseWithStats.stats?.CacheTokens !== undefined && {
|
|
218
206
|
cacheTokens: responseWithStats.stats.CacheTokens,
|
|
219
207
|
}),
|
|
208
|
+
...(responseWithStats.stats?.promptTokens !== undefined && {
|
|
209
|
+
promptTokens: responseWithStats.stats.promptTokens,
|
|
210
|
+
}),
|
|
220
211
|
...(responseWithStats.stats?.generatedTokens !== undefined && {
|
|
221
212
|
generatedTokens: responseWithStats.stats.generatedTokens,
|
|
222
213
|
}),
|
|
@@ -231,8 +222,10 @@ async function* processModelResponse(model, messagesToSend, tools, generationPar
|
|
|
231
222
|
producedTokens,
|
|
232
223
|
};
|
|
233
224
|
}
|
|
234
|
-
export async function* completion(params) {
|
|
225
|
+
export async function* completion(params, opts) {
|
|
235
226
|
const { history, modelId, kvCache, tools, generationParams, responseFormat } = params;
|
|
227
|
+
const { signal, scope } = opts;
|
|
228
|
+
const requestLogger = opts.logger ?? logger;
|
|
236
229
|
const modelConfig = getModelConfig(modelId);
|
|
237
230
|
const toolsEnabled = modelConfig.tools === true;
|
|
238
231
|
const toolsMode = modelConfig.toolsMode;
|
|
@@ -259,136 +252,45 @@ export async function* completion(params) {
|
|
|
259
252
|
}
|
|
260
253
|
}
|
|
261
254
|
const model = getModel(modelId);
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
// to a per-turn anchor and must not enter the system cache.
|
|
281
|
-
staticTools ? tools : undefined);
|
|
282
|
-
markCacheInitialized(modelId, configHash, kvCache);
|
|
283
|
-
cacheExists = true;
|
|
284
|
-
}
|
|
285
|
-
const messagesToSend = prepareMessagesForCache(cachePathToUse, cacheExists, history, dynamicTools ? tools : undefined);
|
|
286
|
-
logMessagesToAddon(messagesToSend, "PROMPT_SEND");
|
|
287
|
-
const cancelCountBefore = snapshotCancelCount(modelId);
|
|
288
|
-
const result = yield* processModelResponse(model, messagesToSend, tools, mergedGenerationParams, { cacheKey: cachePathToUse, saveCacheToDisk: true }, dialect);
|
|
289
|
-
const wasCancelled = snapshotCancelCount(modelId) > cancelCountBefore;
|
|
290
|
-
if (shouldRecordSavedCount(wasCancelled, result.producedTokens)) {
|
|
291
|
-
// Turn ran to completion and produced content — record the new
|
|
292
|
-
// boundary so the next turn can slice its history.
|
|
293
|
-
await recordCacheSaveCount(cachePathToUse, history.length + 1);
|
|
294
|
-
}
|
|
295
|
-
else {
|
|
296
|
-
// The addon writes the cache file unconditionally on
|
|
297
|
-
// `saveCacheToDisk` turns, including cancellations and zero-token
|
|
298
|
-
// exits, so what's left on disk holds partial decode state that
|
|
299
|
-
// does not correspond to a clean turn boundary. Mirror the
|
|
300
|
-
// auto-key handling: drop the file, clear the in-memory init
|
|
301
|
-
// flag (otherwise `customCacheExists` would still report true),
|
|
302
|
-
// and forget the saved count. Next turn re-primes the system
|
|
303
|
-
// prompt cleanly — a one-turn perf hit, but no risk of the
|
|
304
|
-
// addon loading the stale KV state.
|
|
305
|
-
try {
|
|
306
|
-
await fsPromises.unlink(cachePathToUse);
|
|
307
|
-
}
|
|
308
|
-
catch (unlinkError) {
|
|
309
|
-
logger.warn(`[kv-cache] Failed to remove cache file after cancelled or empty custom-key turn; next turn may load stale KV state. path=${cachePathToUse} error=${unlinkError instanceof Error ? unlinkError.message : String(unlinkError)}`);
|
|
310
|
-
}
|
|
311
|
-
clearCacheRegistry({ cacheKey: kvCache, modelId });
|
|
312
|
-
cachedMessageCounts.delete(cachePathToUse);
|
|
313
|
-
}
|
|
314
|
-
return result;
|
|
315
|
-
}
|
|
316
|
-
else {
|
|
317
|
-
// Auto-generate cache key based on conversation history
|
|
318
|
-
const cacheMessages = history.map((msg) => ({
|
|
319
|
-
role: msg.role,
|
|
320
|
-
content: msg.content,
|
|
321
|
-
attachments: msg.attachments ?? undefined,
|
|
322
|
-
}));
|
|
323
|
-
const existingCache = await findMatchingCache(modelId, configHash, cacheMessages);
|
|
324
|
-
const preResponseCacheInfo = await getCurrentCacheInfo(modelId, configHash, cacheMessages);
|
|
325
|
-
cachePathToUse =
|
|
326
|
-
existingCache !== null
|
|
327
|
-
? existingCache.cachePath
|
|
328
|
-
: preResponseCacheInfo.cachePath;
|
|
329
|
-
let cacheExists = existingCache !== null;
|
|
330
|
-
logCacheStatus("auto", cacheExists);
|
|
331
|
-
if (!cacheExists) {
|
|
332
|
-
await initSystemPromptCache(model, cachePathToUse, systemPromptToUse, "auto", staticTools ? tools : undefined);
|
|
333
|
-
markCacheInitialized(modelId, configHash, preResponseCacheInfo.cacheKey);
|
|
334
|
-
cacheExists = true;
|
|
335
|
-
}
|
|
336
|
-
const messagesToSend = prepareMessagesForCache(cachePathToUse, cacheExists, history, dynamicTools ? tools : undefined);
|
|
337
|
-
logMessagesToAddon(messagesToSend, "PROMPT_SEND");
|
|
338
|
-
const cancelCountBefore = snapshotCancelCount(modelId);
|
|
339
|
-
const result = yield* processModelResponse(model, messagesToSend, tools, mergedGenerationParams, { cacheKey: cachePathToUse, saveCacheToDisk: true }, dialect);
|
|
340
|
-
const wasCancelled = snapshotCancelCount(modelId) > cancelCountBefore;
|
|
341
|
-
// TODO: support auto-cache for tool-call turns by keying off the
|
|
342
|
-
// structured assistant/tool messages callers push into history,
|
|
343
|
-
// not result.responseText (which is raw tool-call markup here).
|
|
344
|
-
// Until then, remove any cache file the addon wrote so it doesn't
|
|
345
|
-
// leak on disk (the next turn would compute a different key and
|
|
346
|
-
// never reach it).
|
|
347
|
-
if (result.toolCalls.length > 0) {
|
|
348
|
-
logger.warn(`[kv-cache] Auto cache tool-call turn; removing orphaned cache to avoid disk leak. path=${cachePathToUse}`);
|
|
349
|
-
try {
|
|
350
|
-
await fsPromises.unlink(cachePathToUse);
|
|
351
|
-
}
|
|
352
|
-
catch (unlinkError) {
|
|
353
|
-
logger.warn(`[kv-cache] Failed to remove orphaned tool-turn cache file; disk leak likely. path=${cachePathToUse} error=${unlinkError instanceof Error ? unlinkError.message : String(unlinkError)}`);
|
|
354
|
-
}
|
|
355
|
-
cachedMessageCounts.delete(cachePathToUse);
|
|
356
|
-
return result;
|
|
357
|
-
}
|
|
358
|
-
// A cancelled or zero-token turn cannot be promoted to a post-response
|
|
359
|
-
// cache: the post-response key is derived from `result.responseText`,
|
|
360
|
-
// which is empty/partial in those cases, and the on-disk cache the
|
|
361
|
-
// addon wrote is not aligned with the current-history hash. Treat it
|
|
362
|
-
// like the tool-call branch — drop the cache file and clear the count.
|
|
363
|
-
if (!shouldRecordSavedCount(wasCancelled, result.producedTokens)) {
|
|
364
|
-
try {
|
|
365
|
-
await fsPromises.unlink(cachePathToUse);
|
|
366
|
-
}
|
|
367
|
-
catch (unlinkError) {
|
|
368
|
-
logger.warn(`[kv-cache] Failed to remove cache file after cancelled or empty turn; disk leak possible. path=${cachePathToUse} error=${unlinkError instanceof Error ? unlinkError.message : String(unlinkError)}`);
|
|
369
|
-
}
|
|
370
|
-
cachedMessageCounts.delete(cachePathToUse);
|
|
371
|
-
return result;
|
|
372
|
-
}
|
|
373
|
-
const savedHistory = buildAutoCacheSaveHistory(cacheMessages, result.responseText);
|
|
374
|
-
const postResponseCacheInfo = await getCurrentCacheInfo(modelId, configHash, savedHistory);
|
|
375
|
-
if (!(await renameCacheFile(cachePathToUse, postResponseCacheInfo.cachePath))) {
|
|
376
|
-
logger.warn(`[kv-cache] Auto cache rename failed; removing stale cache to avoid disk leak. from=${cachePathToUse} to=${postResponseCacheInfo.cachePath}`);
|
|
377
|
-
try {
|
|
378
|
-
await fsPromises.unlink(cachePathToUse);
|
|
379
|
-
}
|
|
380
|
-
catch (unlinkError) {
|
|
381
|
-
logger.warn(`[kv-cache] Failed to remove stale cache file; disk leak likely. path=${cachePathToUse} error=${unlinkError instanceof Error ? unlinkError.message : String(unlinkError)}`);
|
|
382
|
-
}
|
|
383
|
-
cachedMessageCounts.delete(cachePathToUse);
|
|
384
|
-
return result;
|
|
385
|
-
}
|
|
386
|
-
cachedMessageCounts.delete(cachePathToUse);
|
|
387
|
-
await recordCacheSaveCount(postResponseCacheInfo.cachePath, savedHistory.length);
|
|
388
|
-
return result;
|
|
255
|
+
// Hard-cancel wiring: when the registry aborts the request's signal,
|
|
256
|
+
// forward to the addon so the C++ work stops as soon as it can. The
|
|
257
|
+
// SDK still treats `signal.aborted` as the truth for cancel detection
|
|
258
|
+
// (post-completion bookkeeping below) — this listener only shortens
|
|
259
|
+
// the latency between "user clicked stop" and "addon stops decoding".
|
|
260
|
+
//
|
|
261
|
+
// Fire-and-forget by construction (event listeners can't `await`), but
|
|
262
|
+
// `addon.cancel()` returns a Promise — if it ever rejects the bare
|
|
263
|
+
// `void` would leak it as an unhandledRejection. Attach `.catch(...)`
|
|
264
|
+
// so a rejection is logged and the process stays clean; the iterator
|
|
265
|
+
// below still sees EOF/empty tokens via the addon's normal cancel path
|
|
266
|
+
// so callers aren't affected.
|
|
267
|
+
const onAbort = () => {
|
|
268
|
+
const addon = model.addon;
|
|
269
|
+
if (addon?.cancel) {
|
|
270
|
+
addon.cancel.call(addon).catch((err) => {
|
|
271
|
+
requestLogger.warn(`[cancel] addon.cancel() rejected during abort for modelId=${modelId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
272
|
+
});
|
|
389
273
|
}
|
|
390
|
-
}
|
|
391
|
-
|
|
274
|
+
};
|
|
275
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
276
|
+
// `addEventListener("abort", ..., { once: true })` does *not* fire if
|
|
277
|
+
// the signal is already aborted at register time — but the registry
|
|
278
|
+
// synchronously aborts a fresh controller when `parentSignal` was
|
|
279
|
+
// already aborted at `begin(...)`. Without this fall-through, the
|
|
280
|
+
// addon would keep decoding until the post-loop check notices.
|
|
281
|
+
// Re-using `onAbort` here keeps the listener body as the single
|
|
282
|
+
// source of truth for "what cancel does."
|
|
283
|
+
if (signal.aborted)
|
|
284
|
+
onAbort();
|
|
285
|
+
// Detach the abort listener on every exit path (happy, throw, generator
|
|
286
|
+
// `return()` from upstream). `{ once: true }` already removes the
|
|
287
|
+
// listener if the signal fires, so the `removeEventListener` here is
|
|
288
|
+
// the cleanup hook for the signal-never-fired path.
|
|
289
|
+
scope.defer(() => {
|
|
290
|
+
signal.removeEventListener("abort", onAbort);
|
|
291
|
+
});
|
|
292
|
+
if (!kvCache) {
|
|
293
|
+
// KV-cache disabled — straight passthrough, no session involvement.
|
|
392
294
|
let historyWithTools = history;
|
|
393
295
|
if (staticTools && tools) {
|
|
394
296
|
historyWithTools = prependToolsToHistory(history, tools);
|
|
@@ -401,4 +303,103 @@ export async function* completion(params) {
|
|
|
401
303
|
logMessagesToAddon(transformedHistory, "NO_CACHE");
|
|
402
304
|
return yield* processModelResponse(model, transformedHistory, tools, mergedGenerationParams, undefined, dialect);
|
|
403
305
|
}
|
|
306
|
+
// ---- KV-cache path. The session owns all three bookkeeping layers
|
|
307
|
+
// (on-disk `.bin`, `initializedCaches`, `cachedMessageCounts`). The
|
|
308
|
+
// handler asks for a turn, registers rollback on the scope, and on
|
|
309
|
+
// the happy path calls `commitTurn` which short-circuits the deferred
|
|
310
|
+
// rollback. Cancellations / zero-token replies / rename failures all
|
|
311
|
+
// unwind through the same `scope.defer` hook. ----
|
|
312
|
+
const session = createKvCacheSession(modelId, { logger: requestLogger });
|
|
313
|
+
const systemPromptFromHistory = extractSystemPrompt(history);
|
|
314
|
+
// Dynamic mode lets each turn carry its own tool set, so the cache
|
|
315
|
+
// hash must not depend on the tool list — otherwise a tool change
|
|
316
|
+
// would force a fresh cache file and defeat the whole optimisation.
|
|
317
|
+
const configHash = generateConfigHash(systemPromptFromHistory, dynamicTools ? undefined : tools);
|
|
318
|
+
const systemPromptToUse = systemPromptFromHistory ||
|
|
319
|
+
modelConfig.system_prompt ||
|
|
320
|
+
"You are a helpful assistant.";
|
|
321
|
+
const primeIfMissing = async (cachePath) => {
|
|
322
|
+
await initSystemPromptCache(model, cachePath, systemPromptToUse, typeof kvCache === "string" ? kvCache : "auto",
|
|
323
|
+
// Static-mode tools are baked into the system-prompt cache so
|
|
324
|
+
// they're shared across the session. Dynamic-mode tools belong
|
|
325
|
+
// to a per-turn anchor and must not enter the system cache.
|
|
326
|
+
staticTools ? tools : undefined);
|
|
327
|
+
};
|
|
328
|
+
let turn;
|
|
329
|
+
if (typeof kvCache === "string") {
|
|
330
|
+
turn = await session.beginTurn({
|
|
331
|
+
kind: "custom",
|
|
332
|
+
customKey: kvCache,
|
|
333
|
+
configHash,
|
|
334
|
+
primeIfMissing,
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
const cacheMessages = history.map((msg) => ({
|
|
339
|
+
role: msg.role,
|
|
340
|
+
content: msg.content,
|
|
341
|
+
attachments: msg.attachments ?? undefined,
|
|
342
|
+
}));
|
|
343
|
+
turn = await session.beginTurn({
|
|
344
|
+
kind: "auto",
|
|
345
|
+
configHash,
|
|
346
|
+
history: cacheMessages,
|
|
347
|
+
primeIfMissing,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
// Single cleanup hook for every non-success exit path. `commitTurn`
|
|
351
|
+
// flips the turn's internal `committed` flag so this becomes a no-op
|
|
352
|
+
// on the happy path. Scope unwinding is LIFO — registered after the
|
|
353
|
+
// `removeEventListener` defer above so rollback runs before the
|
|
354
|
+
// listener detach.
|
|
355
|
+
scope.defer(() => session.rollback(turn));
|
|
356
|
+
// `cacheExists` is implied by `beginTurn` — the session either found
|
|
357
|
+
// an existing cache or just primed one. Pass `true` to the message
|
|
358
|
+
// selector so the slicing branches engage.
|
|
359
|
+
const messagesToSend = prepareMessagesForCache(session, turn,
|
|
360
|
+
/* cacheExists */ true, history, dynamicTools ? tools : undefined);
|
|
361
|
+
logMessagesToAddon(messagesToSend, "PROMPT_SEND");
|
|
362
|
+
const result = yield* processModelResponse(model, messagesToSend, tools, mergedGenerationParams, { cacheKey: turn.cachePath, saveCacheToDisk: true }, dialect);
|
|
363
|
+
if (typeof kvCache === "string") {
|
|
364
|
+
// Custom-key path: the addon wrote the new cache state inline at
|
|
365
|
+
// the same path. Either commit (records the boundary, suppresses
|
|
366
|
+
// rollback) or fall through to the deferred rollback.
|
|
367
|
+
if (shouldCommitTurn(signal, result.producedTokens)) {
|
|
368
|
+
await session.commitTurn(turn, {
|
|
369
|
+
kind: "static",
|
|
370
|
+
messageCount: history.length + 1,
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
return result;
|
|
374
|
+
}
|
|
375
|
+
// Auto-cache path.
|
|
376
|
+
//
|
|
377
|
+
// Tool-call turns: the auto-cache key is derived from
|
|
378
|
+
// `result.responseText`, which here is raw tool-call markup rather
|
|
379
|
+
// than a clean assistant message. There's no safe post-response key
|
|
380
|
+
// to rename to, so we let the deferred rollback drop the file. Once
|
|
381
|
+
// the SDK supports auto-cache for structured assistant/tool turns,
|
|
382
|
+
// this becomes a normal commit path.
|
|
383
|
+
if (result.toolCalls.length > 0) {
|
|
384
|
+
logger.warn(`[kv-cache] Auto cache tool-call turn; rolling back to avoid disk leak. path=${turn.cachePath}`);
|
|
385
|
+
return result;
|
|
386
|
+
}
|
|
387
|
+
if (!shouldCommitTurn(signal, result.producedTokens)) {
|
|
388
|
+
// Cancelled or zero-token turn — the addon wrote the file but its
|
|
389
|
+
// contents don't correspond to a clean turn boundary. Let the
|
|
390
|
+
// deferred rollback unlink it.
|
|
391
|
+
return result;
|
|
392
|
+
}
|
|
393
|
+
const savedHistory = buildAutoCacheSaveHistory(history.map((msg) => ({
|
|
394
|
+
role: msg.role,
|
|
395
|
+
content: msg.content,
|
|
396
|
+
attachments: msg.attachments ?? undefined,
|
|
397
|
+
})), result.responseText);
|
|
398
|
+
const postResponseCacheInfo = await getCurrentCacheInfo(modelId, configHash, savedHistory);
|
|
399
|
+
await session.commitTurn(turn, {
|
|
400
|
+
kind: "autoRename",
|
|
401
|
+
targetCachePath: postResponseCacheInfo.cachePath,
|
|
402
|
+
messageCount: savedHistory.length,
|
|
403
|
+
});
|
|
404
|
+
return result;
|
|
404
405
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helpers for detecting and parsing the llama.cpp addon's
|
|
3
|
+
* `ContextOverflow` status error (`LlmErrors.hpp::ContextOverflow = 14`).
|
|
4
|
+
*
|
|
5
|
+
* The addon's JS-facing throw goes through `js_throw_error(env, code,
|
|
6
|
+
* msg)` (see `JsUtils.hpp::JSCATCH`) where `code` comes from
|
|
7
|
+
* `qvac_errors::StatusError::codeString()` and formats as
|
|
8
|
+
* `"[ <addonId> :: ContextOverflow ]"`. The message carries the
|
|
9
|
+
* C++-formatted detail (which may include the prompt/ctx sizes).
|
|
10
|
+
*
|
|
11
|
+
* These helpers let the plugin handler convert that addon error into a
|
|
12
|
+
* typed `ContextOverflowError` and let unit tests assert the detection
|
|
13
|
+
* + extraction logic without a real model load.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isAddonContextOverflowError(err: unknown): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Best-effort extraction of `promptTokens` / `ctxSize` from the addon
|
|
18
|
+
* error message. The C++ paths in `TextLlmContext.cpp` and
|
|
19
|
+
* `MtmdLlmContext.cpp` format both numbers into the message; the
|
|
20
|
+
* `LlamaModel::processPromptImpl` fallback path emits a bare
|
|
21
|
+
* `"<func>: context overflow\n"` with neither number. Returning
|
|
22
|
+
* `undefined` for either field is fine — `ContextOverflowError` holds
|
|
23
|
+
* them as optional and the message factory degrades gracefully.
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseContextOverflowMessage(message: string): {
|
|
26
|
+
promptTokens?: number;
|
|
27
|
+
ctxSize?: number;
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=context-overflow.d.ts.map
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helpers for detecting and parsing the llama.cpp addon's
|
|
3
|
+
* `ContextOverflow` status error (`LlmErrors.hpp::ContextOverflow = 14`).
|
|
4
|
+
*
|
|
5
|
+
* The addon's JS-facing throw goes through `js_throw_error(env, code,
|
|
6
|
+
* msg)` (see `JsUtils.hpp::JSCATCH`) where `code` comes from
|
|
7
|
+
* `qvac_errors::StatusError::codeString()` and formats as
|
|
8
|
+
* `"[ <addonId> :: ContextOverflow ]"`. The message carries the
|
|
9
|
+
* C++-formatted detail (which may include the prompt/ctx sizes).
|
|
10
|
+
*
|
|
11
|
+
* These helpers let the plugin handler convert that addon error into a
|
|
12
|
+
* typed `ContextOverflowError` and let unit tests assert the detection
|
|
13
|
+
* + extraction logic without a real model load.
|
|
14
|
+
*/
|
|
15
|
+
export function isAddonContextOverflowError(err) {
|
|
16
|
+
if (typeof err !== "object" || err === null)
|
|
17
|
+
return false;
|
|
18
|
+
const code = err.code;
|
|
19
|
+
// Anchor to the codeString tail (`[ <addonId> :: ContextOverflow ]`)
|
|
20
|
+
// so we don't false-positive on a hypothetical sibling like
|
|
21
|
+
// `ContextOverflowRecovered` or `PostContextOverflow` after an
|
|
22
|
+
// addon-side rename.
|
|
23
|
+
if (typeof code === "string" && /::\s*ContextOverflow\s*\]/.test(code)) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
// Message-substring fallback for the bare `LlamaModel::processPromptImpl`
|
|
27
|
+
// path, which doesn't go through `StatusError::codeString()`. Match the
|
|
28
|
+
// two known C++-emitted formats only — broader substring would catch
|
|
29
|
+
// wrapper / cause-chain text that mentions overflow without being one.
|
|
30
|
+
const message = err.message;
|
|
31
|
+
return (typeof message === "string" &&
|
|
32
|
+
/(?:context overflow at prefill step|processPromptImpl: context overflow)/i.test(message));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Best-effort extraction of `promptTokens` / `ctxSize` from the addon
|
|
36
|
+
* error message. The C++ paths in `TextLlmContext.cpp` and
|
|
37
|
+
* `MtmdLlmContext.cpp` format both numbers into the message; the
|
|
38
|
+
* `LlamaModel::processPromptImpl` fallback path emits a bare
|
|
39
|
+
* `"<func>: context overflow\n"` with neither number. Returning
|
|
40
|
+
* `undefined` for either field is fine — `ContextOverflowError` holds
|
|
41
|
+
* them as optional and the message factory degrades gracefully.
|
|
42
|
+
*/
|
|
43
|
+
export function parseContextOverflowMessage(message) {
|
|
44
|
+
// "[TextLlm] context overflow at prefill step: prompt tokens N, max context tokens M\n"
|
|
45
|
+
// Same-clause separator (no `[^]*?` cross-newline walk) so a future
|
|
46
|
+
// wrapper that pastes overflow text alongside unrelated numbers can't
|
|
47
|
+
// produce a mismatched pair.
|
|
48
|
+
const longForm = message.match(/prompt tokens (\d+)[,\s]+max context tokens (\d+)/i);
|
|
49
|
+
if (longForm?.[1] && longForm[2]) {
|
|
50
|
+
return {
|
|
51
|
+
promptTokens: Number(longForm[1]),
|
|
52
|
+
ctxSize: Number(longForm[2]),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
// "[TextLlm] context overflow at prefill step (N tokens, max M)\n"
|
|
56
|
+
// "[MtmdLlm] context overflow at prefill step (N tokens, max M)\n"
|
|
57
|
+
const shortForm = message.match(/\((\d+)\s+tokens,\s*max\s+(\d+)\)/i);
|
|
58
|
+
if (shortForm?.[1] && shortForm[2]) {
|
|
59
|
+
return {
|
|
60
|
+
promptTokens: Number(shortForm[1]),
|
|
61
|
+
ctxSize: Number(shortForm[2]),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return {};
|
|
65
|
+
}
|