QVAC-18183 feat[bc]: CLI cancel bridge + cancelHandler retirement#2074
Conversation
7cd08bc to
c9f5555
Compare
c9f5555 to
abacedd
Compare
M3d — the final sub-PR for QVAC-18183 and the release gate for SDK
0.11.0. Six deliverables (plus a late seventh — decorated-promise
RAG client APIs — added when consumer-surface audit surfaced the
gap), all coupled to the new request-lifecycle system landed in
M3a–M3c.
1. CLI cancel bridge. Every OpenAI-compatible route in `qvac serve`
(chat, embeddings, transcriptions, translations) now binds
`req.on('close')` to `sdkCancel({ requestId })` via a single shared
helper `core/cancel-bridge.ts`. The `requestId` is exposed
synchronously from `sdkCompletion` / `sdkEmbed` / `sdkTranscribe`
on the returned decorated promise — the SDK guarantees it's
available before the inference promise settles. The Workbench
Stop button now disconnects an HTTP request and the worker
actually stops decoding instead of silently running to completion.
2. cancelHandler.ts retirement. The 5-arm dispatcher
(`inference` / `embedding` / `transcription` / `translation` /
`downloadAsset`) is gone. The handler is now a 2-arm pass-through
that delegates to `RequestRegistry.cancel({ requestId })` or
`cancelByModelId({ modelId, kind? })`. Option A.2 (shrink to
pass-through) was chosen over A.1 (delete entirely) because the
handler-registry shape requires a handler function per RPC method;
the file now exists only to bridge the wire schema into the
registry call.
3. M1 compat-fallback removed. The pre-registry `addon.cancel()`
fallback in `server/bare/ops/cancel.ts` (lines 49-71 on the parent
commit) is gone. Every cancellable handler is on the registry as
of M3a–M3c; broad cancel is a single registry walk.
4. Schema collapse (BREAKING). The wire envelope for `cancel`
narrows from a 5-arm discriminated union to a 2-arm union
(`{ operation: "request", requestId }` and
`{ operation: "broad", modelId, kind? }`). The per-kind public-API
sugars for `"inference"` and `"embeddings"` are preserved via
thin transforms in `client/api/cancel.ts:normalizeCancelParams`,
so the two most common legacy call shapes keep working unchanged.
The two shapes that *can't* be mechanically back-mapped are removed:
- `cancel({ operation: "downloadAsset", downloadKey, clearCache })`
— REMOVED. The old envelope keyed off `downloadKey`, the new
path keys off `requestId`. Migration: hold onto the
`requestId` exposed on the decorated promise returned by
`downloadAsset(...)` and call `cancel({ requestId, clearCache })`.
- `cancel({ operation: "rag", workspace? })` — REMOVED. The old
envelope had no `requestId`; in M3d the three cancellable RAG
client APIs (`ragIngest`, `ragSaveEmbeddings`, `ragReindex`)
now return decorated promises so callers can migrate to
`cancel({ requestId: op.requestId })`. The non-cancellable
RAG ops (`ragChunk`, `ragSearch`, etc.) intentionally do not
decorate — they don't register with the request registry
server-side.
Known affected consumer:
- qvac-app-workbench-desktop/workbench-worker/services/
provider-service.ts:91 constructs `{operation:"downloadAsset"}`.
- qvac-app-workbench-desktop/workbench-worker/handlers/
rag-handler.ts:169 constructs `{operation:"rag"}`.
These need a coordinated migration before workbench-desktop bumps
to SDK 0.11.0; tracking as a follow-up Asana task.
5. Typed-error reconstruction. The cross-RPC `instanceof` story is
now honest: `errorResponseSchema` carries an optional
`typedFields` envelope, `QvacErrorBase` subclasses that need to
survive RPC implement `toErrorResponseFields()`, and the client
reconstructs them via a keyed map in `client/rpc/rpc-error.ts`.
Registered today: `RequestIdConflictError`, `RequestNotFoundError`,
`RequestRejectedByPolicyError` — all re-exported from
`@qvac/sdk` so consumers can `instanceof` them. Bring-up bug
caught in test: `QvacErrorBase.name` is the SCREAMING_SNAKE
error-code name (e.g. `REQUEST_REJECTED_BY_POLICY`), not the JS
class name; the reconstructor map keys off that exact value and
the maintenance contract in the JSDoc spells this out so the next
class added doesn't trip the same wire.
6. Docs. `request-lifecycle-system.mdc` no longer claims a fallback
to `addon.cancel()` for non-migrated kinds (M3d closes that gap).
`error-handling.mdc` documents the reconstructor maintenance
contract. `request-lifecycle-primitives.mdc` aligns with the new
handler shape. CLI serve workspace rule documents the cancel
bridge.
7. Decorated-promise RAG (late add). Three RAG client APIs
(`ragIngest`, `ragSaveEmbeddings`, `ragReindex`) now generate a
client-side `requestId`, thread it onto the wire envelope, and
return `Promise<...> & { requestId: string }`. The wire schema
already supported the optional `requestId` field (added in M3b/M3c);
this PR closes the client-side wiring gap so the migration story
for the removed `cancel({operation:"rag"})` arm is honest —
callers actually have a `requestId` to hand to `cancel(...)`. The
other six RAG client APIs (chunk/search/delete/list/close/
deleteWorkspace) intentionally stay non-decorated because their
handlers don't call `beginRagContext` — they're fast-path
operations not subject to mid-flight cancellation.
Tests:
- `packages/cli/test/cancel-bridge.test.ts` — 4 cases covering happy
path, `res.writableEnded` short-circuit, swallowed rejections, and
`once` semantics.
- `packages/sdk/test/unit/error-typed-fields.test.ts` — 6 cases
covering `typedFields` population for each registered class and
proper omission for non-registered / client-constructed errors.
- `packages/sdk/test/unit/rpc-error-reconstruct.test.ts` — 7 cases
covering round-trip reconstruction, fallback to `RPCError` on
unknown names, plain-Error fallthrough, defensive defaulting on
missing `typedFields`, and remote stack/timestamp attachment.
- `packages/sdk/test/unit/request-id-wire.test.ts` — extended with
1 new case for `ragSaveEmbeddings` envelope `requestId` forwarding,
matching the existing `ragIngest` / `ragReindex` coverage. Client-
side decoration is signature-guaranteed by TypeScript; the schema
test pins the wire envelope.
Net: 284 CLI unit tests pass, 10 SDK unit tests pass, plus the 18
new M3d cases. Lint + typecheck clean. The pre-existing `semver`
typecheck error in `packages/cli/src/verify/bundle/abi.ts` lives on
`upstream/main` and is not introduced or affected by this PR.
Tag justification: `[bc]` not `[api]`. Two public-API `cancel(...)`
call shapes (`downloadAsset`, `rag`) are removed because the old
wire envelopes had no `requestId` to mechanically back-map. The
RAG migration is supported by deliverable 7 (decorated promises on
`ragIngest` / `ragSaveEmbeddings` / `ragReindex`); the `downloadAsset`
migration was already supported via the decorated `downloadAsset(...)`
promise shipped in M3b/M3c. Per the SDK content-tag rules `[api]`
and `[bc]` don't combine; the title carries `[bc]` and the PR body
also documents the additive `[api]`-shaped surfaces (decorated-
promise `requestId`, typed-error reconstruction, new broad-cancel
sugar) under their own section.
064bdec to
0279a56
Compare
The M3a/M3b/M3c/M3d milestone identifiers live in private planning artifacts under `tasks/release-0.11.0-planning/` and have no meaning to anyone reading the qvac monorepo. The previous M3d PR leaked them into Cursor rules and JSDoc comments that future contributors would read with zero context for what those mean. Self-review on PR tetherto#2074 surfaced 13 hits across 9 files. All rewrites either drop the milestone tag entirely or rephrase to reference the public release version (0.11.0) or describe the current state of the system in plain English ("legacy" / "as of" / "current"). No behaviour changes; lint + typecheck clean. Doc hits (6): - .cursor/rules/sdk/docs/request-lifecycle-system.mdc lines 77, 195, 196 - .cursor/rules/sdk/request-lifecycle-primitives.mdc lines 19, 247, 374 Source hits (7): - packages/sdk/client/rpc/rpc-error.ts: "bug fixed in M3d alongside ..." -> "bug fixed alongside ..." - packages/sdk/schemas/cancel.ts: "M2-era per-kind discriminator arms" / "M3d release-gate cleanup" -> "legacy per-kind discriminator arms" / "0.11.0 cleanup" - packages/sdk/server/bare/ops/cancel.ts: "M1-era pre-registry addon-cancel fallback was removed in M3d" -> "legacy pre-registry addon-cancel fallback was removed in 0.11.0" - packages/sdk/server/rpc/handler-registry.ts: "After the M3d wire-schema collapse" -> "After the 0.11.0 wire-schema collapse" - packages/sdk/server/rpc/handlers/cancel-delegated.ts: "After M3d the cancel envelope ..." -> "After the 0.11.0 wire-schema collapse the cancel envelope ..." - packages/sdk/server/rpc/handlers/cancelHandler.ts: "retired in 0.11.0 (M3d)" -> "retired in 0.11.0" - packages/sdk/server/rpc/handlers/load-model/download-manager.ts: "Added in M3d to support ..." -> "Added in 0.11.0 to support ..." Pre-existing M3a leaks in three test files (`request-registry.test.ts`, `request-lifecycle-logging.test.ts`, `with-request-context.test.ts`) and M2 references in `kv-cache-system.mdc` are out of scope for this PR — they predate the M3d branch and belong to a separate scrub.
The M3a/M3b/M3c/M3d/M1-era/M2-era milestone identifiers live in private planning artifacts under `tasks/release-0.11.0-planning/` and have no meaning to anyone reading the qvac monorepo. The previous M3d PR leaked them into Cursor rules, JSDoc comments, and test docstrings that future contributors would read with zero context for what those mean. Self-review on PR tetherto#2074 surfaced 22 hits across 13 files. All rewrites either drop the milestone tag entirely or rephrase to reference the public release version (0.11.0) or describe the current state of the system in plain English ("legacy" / "as of" / "current"). No behaviour changes; lint + typecheck clean. Doc hits (11): - .cursor/rules/sdk/docs/request-lifecycle-system.mdc lines 77, 195, 196 - .cursor/rules/sdk/request-lifecycle-primitives.mdc lines 19, 247, 374 - .cursor/rules/sdk/docs/kv-cache-system.mdc lines 91, 96, 102, 104, 112 Source hits (7): - packages/sdk/client/rpc/rpc-error.ts: "bug fixed in M3d alongside ..." -> "bug fixed alongside ..." - packages/sdk/schemas/cancel.ts: "M2-era per-kind discriminator arms" / "M3d release-gate cleanup" -> "legacy per-kind discriminator arms" / "0.11.0 cleanup" - packages/sdk/server/bare/ops/cancel.ts: "M1-era pre-registry addon-cancel fallback was removed in M3d" -> "legacy pre-registry addon-cancel fallback was removed in 0.11.0" - packages/sdk/server/rpc/handler-registry.ts: "After the M3d wire-schema collapse" -> "After the 0.11.0 wire-schema collapse" - packages/sdk/server/rpc/handlers/cancel-delegated.ts: "After M3d the cancel envelope ..." -> "After the 0.11.0 wire-schema collapse the cancel envelope ..." - packages/sdk/server/rpc/handlers/cancelHandler.ts: "retired in 0.11.0 (M3d)" -> "retired in 0.11.0" - packages/sdk/server/rpc/handlers/load-model/download-manager.ts: "Added in M3d to support ..." -> "Added in 0.11.0 to support ..." Test docstring hits (4): - packages/sdk/test/unit/runtime/request-registry.test.ts: "Option A in the M3a brief" parenthetical dropped; "pre-M3a behaviour" -> "documented behaviour" - packages/sdk/test/unit/runtime/request-lifecycle-logging.test.ts: "part of the M3a contract" -> "part of the 0.11.0 request-lifecycle contract" - packages/sdk/test/unit/runtime/with-request-context.test.ts: "Covers the M3a brief's Deliverable 3 acceptance criteria" -> "Covers the acceptance criteria"
993f657 to
7399fe2
Compare
…-cancel-bridge-cancelhandler-retirement
|
got type errors on trying to run cancel download test on local desktop via Log
[producer] ▶️ Test download-cancel-isolation started by consumer-desktop-Lauris-MacBook-Pro.local-1778843688597
[producer] 🚀 Batch orchestration started
[producer] 📋 Total tests: 0
[producer] ⏳ Waiting for consumers to register (timeout: 30s)...
[producer]
[consumer-desktop] [sdk:server] 🐻 Hello from Bare
[consumer-desktop] [sdk:server] Parsed RPC configuration from arguments
[consumer-desktop] [sdk:server] Running in desktop mode, connecting to IPC socket: /var/folders/m6/tt9tc20n0rlc9q82bq9416_r0000gn/T/qvac-worker-35166-mp6tlqk4-0577.sock
[consumer-desktop] [sdk:server] Connecting to IPC socket at /var/folders/m6/tt9tc20n0rlc9q82bq9416_r0000gn/T/qvac-worker-35166-mp6tlqk4-0577.sock
[consumer-desktop] [sdk:server] Bare worker started and listening for RPC requests
[consumer-desktop] [sdk:client] ✅ Loaded config from: /Users/lauri/.cache/qvac-pr-review/pr-2074/packages/sdk/tests-qvac/fixtures/qvac.config.e2e.json
[consumer-desktop] [sdk:client] 📦 Initializing SDK config
[consumer-desktop] [sdk:client] 📱 Runtime context: { runtime: 'node', platform: 'darwin' }
[consumer-desktop] [sdk:server] Connected to IPC server
[consumer-desktop] [sdk:server] ✅ Registry download max retries set to: 5
[consumer-desktop] [sdk:server] ✅ Registry stream timeout set to: 120000ms
[consumer-desktop] [sdk:client] ✅ Initialization complete
[consumer-desktop] [sdk:server] [request-lifecycle] begin requestId=97726ce8-608b-49fb-a4ee-52fc76413133 kind=downloadAsset modelId=- state=running
[consumer-desktop] [sdk:server] Loading from registry: ggerganov/whisper.cpp/resolve/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny.bin
[consumer-desktop] [sdk:server] [request-lifecycle] begin requestId=cb38ec25-486a-4fa5-b4ee-e68e7fcd222f kind=downloadAsset modelId=- state=running
[consumer-desktop] [sdk:server] Loading from registry: qvac_models_compiled/ocr/2026-02-12/rec_dyn/recognizer_cyrillic.onnx
[consumer-desktop] [sdk:server] ✅ Model cached with correct size: /Users/lauri/.qvac/models/574dfe543bfdae68_ggml-tiny.bin
[consumer-desktop] [sdk:server] 🗑️ Removing incomplete cached file (expected 15250809, got 0): /Users/lauri/.qvac/models/23fdbaa7dced827d_recognizer_cyrillic.onnx
[consumer-desktop] [sdk:server] 🔗 Creating new registry client...
[consumer-desktop] [sdk:server] ✅ Model already cached and validated: /Users/lauri/.qvac/models/574dfe543bfdae68_ggml-tiny.bin
[consumer-desktop] [sdk:server] ✅ Using cached model: /Users/lauri/.qvac/models/574dfe543bfdae68_ggml-tiny.bin
[consumer-desktop] [sdk:server] Loaded Model to /Users/lauri/.qvac/models/574dfe543bfdae68_ggml-tiny.bin
[consumer-desktop] [sdk:server] [request-lifecycle] end requestId=97726ce8-608b-49fb-a4ee-52fc76413133 kind=downloadAsset modelId=- state=completed durationMs=72
[consumer-desktop] [sdk:server] ✅ Registry client ready
[consumer-desktop] [sdk:server] 📥 Downloading blob directly: recognizer_cyrillic.onnx
[consumer-desktop] [QVACRegistryClient] [INFO] Downloading blob directly {
[consumer-desktop] coreKey: '6309722b3460...',
[consumer-desktop] blockOffset: 802467,
[consumer-desktop] blockLength: 233,
[consumer-desktop] byteLength: 15250809
[consumer-desktop] }
[consumer-desktop] [sdk:server] 🐻 Bare worker shutdown signal received, cleaning up...
[consumer-desktop] [sdk:server] 🧹 Cancelling 1 active downloads
[consumer-desktop] file:///Users/lauri/.cache/qvac-pr-review/pr-2074/packages/sdk/tests-qvac/node_modules/@qvac/sdk/dist/client/rpc/rpc-client.js:79
[consumer-desktop] const parsedRequest = requestSchema.parse(request);
[consumer-desktop] ^
[consumer-desktop]
[consumer-desktop] ZodError: [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_union",
[consumer-desktop] "errors": [
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "heartbeat"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"heartbeat\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_union",
[consumer-desktop] "errors": [
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_union",
[consumer-desktop] "errors": [
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "loadModel"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"loadModel\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelSrc"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "llamacpp-completion"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "modelType"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"llamacpp-completion\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "object",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelConfig"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected object, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "unrecognized_keys",
[consumer-desktop] "keys": [
[consumer-desktop] "operation",
[consumer-desktop] "modelId",
[consumer-desktop] "kind"
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Unrecognized keys: \"operation\", \"modelId\", \"kind\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "loadModel"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"loadModel\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelSrc"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "whispercpp-transcription"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "modelType"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"whispercpp-transcription\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "object",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelConfig"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected object, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "unrecognized_keys",
[consumer-desktop] "keys": [
[consumer-desktop] "operation",
[consumer-desktop] "modelId",
[consumer-desktop] "kind"
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Unrecognized keys: \"operation\", \"modelId\", \"kind\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "loadModel"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"loadModel\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelSrc"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "parakeet-transcription"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "modelType"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"parakeet-transcription\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "object",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelConfig"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected object, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "unrecognized_keys",
[consumer-desktop] "keys": [
[consumer-desktop] "operation",
[consumer-desktop] "modelId",
[consumer-desktop] "kind"
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Unrecognized keys: \"operation\", \"modelId\", \"kind\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "loadModel"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"loadModel\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelSrc"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "llamacpp-embedding"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "modelType"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"llamacpp-embedding\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "object",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelConfig"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected object, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "unrecognized_keys",
[consumer-desktop] "keys": [
[consumer-desktop] "operation",
[consumer-desktop] "modelId",
[consumer-desktop] "kind"
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Unrecognized keys: \"operation\", \"modelId\", \"kind\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "loadModel"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"loadModel\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelSrc"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "nmtcpp-translation"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "modelType"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"nmtcpp-translation\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "expected": "object",
[consumer-desktop] "path": [
[consumer-desktop] "modelConfig"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected object, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "unrecognized_keys",
[consumer-desktop] "keys": [
[consumer-desktop] "operation",
[consumer-desktop] "modelId",
[consumer-desktop] "kind"
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Unrecognized keys: \"operation\", \"modelId\", \"kind\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "loadModel"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"loadModel\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelSrc"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "onnx-tts"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "modelType"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"onnx-tts\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_union",
[consumer-desktop] "errors": [
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "object",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Invalid input: expected object, received undefined"
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "object",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Invalid input: expected object, received undefined"
[consumer-desktop] }
[consumer-desktop] ]
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "modelConfig"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "unrecognized_keys",
[consumer-desktop] "keys": [
[consumer-desktop] "operation",
[consumer-desktop] "modelId",
[consumer-desktop] "kind"
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Unrecognized keys: \"operation\", \"modelId\", \"kind\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "loadModel"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"loadModel\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelSrc"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "onnx-ocr"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "modelType"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"onnx-ocr\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "object",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelConfig"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected object, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "unrecognized_keys",
[consumer-desktop] "keys": [
[consumer-desktop] "operation",
[consumer-desktop] "modelId",
[consumer-desktop] "kind"
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Unrecognized keys: \"operation\", \"modelId\", \"kind\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "loadModel"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"loadModel\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelSrc"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "sdcpp-generation"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "modelType"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"sdcpp-generation\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "unrecognized_keys",
[consumer-desktop] "keys": [
[consumer-desktop] "operation",
[consumer-desktop] "modelId",
[consumer-desktop] "kind"
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Unrecognized keys: \"operation\", \"modelId\", \"kind\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "loadModel"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"loadModel\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelSrc"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelType"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] }
[consumer-desktop] ]
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Invalid input"
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "loadModel"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"loadModel\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "whisper",
[consumer-desktop] "whispercpp-transcription"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "modelType"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid option: expected one of \"whisper\"|\"whispercpp-transcription\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "object",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelConfig"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected object, received undefined"
[consumer-desktop] }
[consumer-desktop] ]
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Invalid input"
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "downloadAsset"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"downloadAsset\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "assetSrc"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "array",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "history"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected array, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "boolean",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "stream"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected boolean, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "completionStream"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"completionStream\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "unloadModel"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"unloadModel\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "expected": "object",
[consumer-desktop] "path": [
[consumer-desktop] "audioChunk"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected object, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "transcribe"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"transcribe\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "transcribeStream"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"transcribeStream\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "id"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "loggingStream"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"loggingStream\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_union",
[consumer-desktop] "errors": [
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "array",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Invalid input: expected array, received undefined"
[consumer-desktop] }
[consumer-desktop] ]
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "text"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "embed"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"embed\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_union",
[consumer-desktop] "errors": [
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_union",
[consumer-desktop] "errors": [
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "array",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Invalid input: expected array, received undefined"
[consumer-desktop] }
[consumer-desktop] ]
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "text"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "boolean",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "stream"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected boolean, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "nmt",
[consumer-desktop] "nmtcpp-translation"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "modelType"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid option: expected one of \"nmt\"|\"nmtcpp-translation\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "translate"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"translate\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "text"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "boolean",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "stream"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected boolean, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "llm",
[consumer-desktop] "llamacpp-completion"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "modelType"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid option: expected one of \"llm\"|\"llamacpp-completion\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "to"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "translate"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"translate\""
[consumer-desktop] }
[consumer-desktop] ]
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Invalid input"
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "text"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "textToSpeech"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"textToSpeech\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "textToSpeechStream"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"textToSpeechStream\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "provide"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"provide\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "unrecognized_keys",
[consumer-desktop] "keys": [
[consumer-desktop] "operation",
[consumer-desktop] "modelId",
[consumer-desktop] "kind"
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Unrecognized keys: \"operation\", \"modelId\", \"kind\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "stopProvide"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"stopProvide\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "unrecognized_keys",
[consumer-desktop] "keys": [
[consumer-desktop] "operation",
[consumer-desktop] "modelId",
[consumer-desktop] "kind"
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Unrecognized keys: \"operation\", \"modelId\", \"kind\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_union",
[consumer-desktop] "errors": [],
[consumer-desktop] "note": "No matching discriminator",
[consumer-desktop] "discriminator": "operation",
[consumer-desktop] "options": [
[consumer-desktop] "chunk",
[consumer-desktop] "ingest",
[consumer-desktop] "saveEmbeddings",
[consumer-desktop] "search",
[consumer-desktop] "deleteEmbeddings",
[consumer-desktop] "reindex",
[consumer-desktop] "listWorkspaces",
[consumer-desktop] "closeWorkspace",
[consumer-desktop] "deleteWorkspace"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "operation"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid discriminator value. Expected 'chunk' | 'ingest' | 'saveEmbeddings' | 'search' | 'deleteEmbeddings' | 'reindex' | 'listWorkspaces' | 'closeWorkspace' | 'deleteWorkspace'"
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_union",
[consumer-desktop] "errors": [
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "deleteCache"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"deleteCache\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] true
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "all"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected true"
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "deleteCache"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"deleteCache\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "kvCacheKey"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] }
[consumer-desktop] ]
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Invalid input"
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "name"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "getModelInfo"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"getModelInfo\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "getLoadedModelInfo"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"getLoadedModelInfo\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "expected": "object",
[consumer-desktop] "path": [
[consumer-desktop] "image"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected object, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "ocrStream"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"ocrStream\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "prompt"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "diffusionStream"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"diffusionStream\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "image"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "upscaleStream"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"upscaleStream\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_union",
[consumer-desktop] "errors": [
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "object",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "options"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected object, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "finetune"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"finetune\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "start",
[consumer-desktop] "resume"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "operation"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid option: expected one of \"start\"|\"resume\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "unrecognized_keys",
[consumer-desktop] "keys": [
[consumer-desktop] "kind"
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Unrecognized key: \"kind\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "object",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "options"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected object, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "finetune"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"finetune\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "getState"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "operation"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"getState\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "unrecognized_keys",
[consumer-desktop] "keys": [
[consumer-desktop] "kind"
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Unrecognized key: \"kind\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "finetune"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"finetune\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "pause",
[consumer-desktop] "cancel"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "operation"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid option: expected one of \"pause\"|\"cancel\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "unrecognized_keys",
[consumer-desktop] "keys": [
[consumer-desktop] "kind"
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Unrecognized key: \"kind\""
[consumer-desktop] }
[consumer-desktop] ]
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Invalid input"
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "pluginInvoke"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"pluginInvoke\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "handler"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "expected": "nonoptional",
[consumer-desktop] "path": [
[consumer-desktop] "params"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected nonoptional, received undefined"
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "pluginInvokeStream"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"pluginInvokeStream\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "modelId"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "handler"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "expected": "nonoptional",
[consumer-desktop] "path": [
[consumer-desktop] "params"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected nonoptional, received undefined"
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "modelRegistryList"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"modelRegistryList\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "modelRegistrySearch"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"modelRegistrySearch\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "modelRegistryGetModel"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"modelRegistryGetModel\""
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "registryPath"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] },
[consumer-desktop] {
[consumer-desktop] "expected": "string",
[consumer-desktop] "code": "invalid_type",
[consumer-desktop] "path": [
[consumer-desktop] "registrySource"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected string, received undefined"
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "suspend"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"suspend\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "resume"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"resume\""
[consumer-desktop] }
[consumer-desktop] ],
[consumer-desktop] [
[consumer-desktop] {
[consumer-desktop] "code": "invalid_value",
[consumer-desktop] "values": [
[consumer-desktop] "state"
[consumer-desktop] ],
[consumer-desktop] "path": [
[consumer-desktop] "type"
[consumer-desktop] ],
[consumer-desktop] "message": "Invalid input: expected \"state\""
[consumer-desktop] }
[consumer-desktop] ]
[consumer-desktop] ],
[consumer-desktop] "path": [],
[consumer-desktop] "message": "Invalid input"
[consumer-desktop] }
[consumer-desktop] ]
[consumer-desktop] at sendProfiled (file:///Users/lauri/.cache/qvac-pr-review/pr-2074/packages/sdk/tests-qvac/node_modules/@qvac/sdk/dist/client/rpc/rpc-client.js:79:45)
[consumer-desktop] at send (file:///Users/lauri/.cache/qvac-pr-review/pr-2074/packages/sdk/tests-qvac/node_modules/@qvac/sdk/dist/client/rpc/rpc-client.js:55:12)
[consumer-desktop] at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
[consumer-desktop] at async cancel (file:///Users/lauri/.cache/qvac-pr-review/pr-2074/packages/sdk/tests-qvac/node_modules/@qvac/sdk/dist/client/api/cancel.js:84:22)
[consumer-desktop]
[consumer-desktop] Node.js v22.20.0
[consumer-desktop] [QVACRegistryClient] [ERROR] Error downloading blob directly Error: Download cancelled
[consumer-desktop] at options.signal.addEventListener.once (file:///Users/lauri/.cache/qvac-pr-review/pr-2074/packages/sdk/tests-qvac/node_modules/@qvac/registry-client/lib/client.js:538:20)
[consumer-desktop] at AbortSignal.dispatchEvent (file:///Users/lauri/.cache/qvac-pr-review/pr-2074/packages/sdk/tests-qvac/node_modules/bare-abort-controller/node_modules/bare-events/web.js:215:17)
[consumer-desktop] at AbortSignal._abort (file:///Users/lauri/.cache/qvac-pr-review/pr-2074/packages/sdk/tests-qvac/node_modules/bare-abort-controller/index.js:44:10)
[consumer-desktop] at AbortController.abort (file:///Users/lauri/.cache/qvac-pr-review/pr-2074/packages/sdk/tests-qvac/node_modules/bare-abort-controller/index.js:137:18)
[consumer-desktop] at maybeCancelTransfer (file:///Users/lauri/.cache/qvac-pr-review/pr-2074/packages/sdk/tests-qvac/node_modules/@qvac/sdk/dist/server/rpc/handlers/load-model/download-manager.js:94:30)
[consumer-desktop] at removeSubscriber (file:///Users/lauri/.cache/qvac-pr-review/pr-2074/packages/sdk/tests-qvac/node_modules/@qvac/sdk/dist/server/rpc/handlers/load-model/download-manager.js:79:5)
[consumer-desktop] at AbortSignal.onAbort (file:///Users/lauri/.cache/qvac-pr-review/pr-2074/packages/sdk/tests-qvac/node_modules/@qvac/sdk/dist/server/rpc/handlers/load-model/download-manager.js:101:9)
[consumer-desktop] at AbortSignal.dispatchEvent (file:///Users/lauri/.cache/qvac-pr-review/pr-2074/packages/sdk/tests-qvac/node_modules/bare-abort-controller/node_modules/bare-events/web.js:215:17)
[consumer-desktop] at AbortSignal._abort (file:///Users/lauri/.cache/qvac-pr-review/pr-2074/packages/sdk/tests-qvac/node_modules/bare-abort-controller/index.js:44:10)
[consumer-desktop] at AbortController.abort (file:///Users/lauri/.cache/qvac-pr-review/pr-2074/packages/sdk/tests-qvac/node_modules/bare-abort-controller/index.js:137:18)
[consumer-desktop] [sdk:server] [request-lifecycle] cancel requestId=cb38ec25-486a-4fa5-b4ee-e68e7fcd222f kind=downloadAsset modelId=- state=cancelling
[consumer-desktop] [sdk:server] Unloaded 0 models
[consumer-desktop] [sdk:server] 🔌 Closing registry client...
[consumer-desktop] [sdk:server] [request-lifecycle downloadAsset requestId=cb38ec25-486a-4fa5-b4ee-e68e7fcd222f] downloadAsset cancelled requestId=cb38ec25-486a-4fa5-b4ee-e68e7fcd222f
[consumer-desktop] [sdk:server] [request-lifecycle] end requestId=cb38ec25-486a-4fa5-b4ee-e68e7fcd222f kind=downloadAsset modelId=- state=cancelled durationMs=979
[consumer-desktop] [sdk:server] IPC socket closed — parent process likely terminated
[consumer-desktop] [sdk:server] ✅ Registry client closed
[consumer-desktop] [sdk:server] ✅ Cleanup completed successfully
[producer]
[producer] 📊 Status [30s]: 0/1 completed | 1 running | 0 queued | 1 consumers
[producer] ⏳ download-cancel-isolation → consumer-desktop-Lauris-MacBook-Pro.local-1778843688597 (running, 31s / 540s)
[producer]
[producer]
[producer] 📊 Status [60s]: 0/1 completed | 1 running | 0 queued | 1 consumers
[producer] ⏳ download-cancel-isolation → consumer-desktop-Lauris-MacBook-Pro.local-1778843688597 (running, 61s / 540s)
[producer]
[producer]
[producer] 📊 Status [90s]: 0/1 completed | 1 running | 0 queued | 1 consumers
[producer] ⏳ download-cancel-isolation → consumer-desktop-Lauris-MacBook-Pro.local-1778843688597 (running, 91s / 540s)
[producer]
[producer]
[producer] 📊 Status [120s]: 0/1 completed | 1 running | 0 queued | 1 consumers
[producer] ⏳ download-cancel-isolation → consumer-desktop-Lauris-MacBook-Pro.local-1778843688597 (running, 121s / 540s)
[producer]
[producer]
[producer] 💀 Consumer desktop-Lauris unresponsive for 121s — marking as dead
[producer]
[producer] ================================================================================
|
Tier-based Approval Status |
…sed cancel
The `download-cancel-isolation` e2e executor was still calling the
removed `cancel({operation:"downloadAsset", downloadKey, clearCache})`
shape, which crashes at the client-side `requestSchema.parse(...)` in
this PR's new 2-arm cancel wire envelope (the executor is itself one
of the in-repo consumers of the [bc] documented on the parent commit
`0279a56bb`).
Surfaced by Lauri running the test locally via `/pr-test` against PR
tetherto#2074 — the consumer reported a ZodError before the cancel could even
reach the SDK server.
Migration follows the pattern the PR body documents: capture the
decorated promise from `downloadAsset(...)` into `cancelledOp` and
cancel by `cancelledOp.requestId` instead of the per-progress-event
`downloadKey`. The `p.downloadKey &&` gate is dropped because
`requestId` is available synchronously on the decorated promise — no
need to wait for the first progress event to surface a key.
`bun lint` + typecheck clean on `packages/sdk` (the `tests-qvac`
typecheck failures are pre-existing — its `node_modules/@qvac/sdk` is
a snapshot populated by `bun run prepare:sdk` rather than a live
symlink). The remaining consumer-migration call sites
(`config-executor.ts`, `delegated-inference-executor.ts`, public
`reference/api/index.mdx` + `models/download-lifecycle.mdx`) are
tracked as follow-ups per Simon's scope choice — see the diary entry.
Per Opaninakuffo's PR tetherto#2074 review: - `client/api/cancel.ts` JSDoc was ~73 lines reading like a mini migration guide. Trimmed to ~25 lines: brief description of the two cancel paths, two examples, and a pointer to the 0.11.0 changelog / release notes for migration detail off the removed `{operation:"downloadAsset"|"rag"}` shapes. Detail lives in the changelog where it belongs, not in code comments that live forever. - `examples/rag/rag-hyperdb/cancellation.ts` was missing the new primary cancel path (`{requestId}`) and the inline comment block was too jargon-heavy for example material ("rag-by-workspace cancel arm", `RequestRegistry`, "worker-singleton" — none of which a reader of the example needs to know). Refactored to capture the decorated promise from `ragIngest(...)` into `const ingest`, cancel via `ingest.requestId` as the primary path, and keep a one-line pointer to the broad-cancel-by-modelId alternative. `bun lint` + typecheck clean.
…equestId-based cancel
The 0.11.0 cancel surface is requestId-based; the legacy
`operation:"downloadAsset"` and per-call `delegate` wire shapes were
removed. Migrate the last two tests-qvac executors that still used the
old shapes:
- config-executor.ts: capture the decorated `downloadAsset` promise
and cancel by `op.requestId`. Mechanical mirror of the
download-executor.ts migration already on this branch.
- delegated-inference-executor.ts: rewrite `cancelDelegatedDownload`
to start a delegated `downloadAsset`, obtain a real `requestId`
synchronously, and `cancel({ requestId })`. Same-process delegation
still fails with DELEGATE_CONNECTION_FAILED, which is the asserted
success path.
Unblocks the `config-registry-download-respects-cancel` and
`cancel-delegated-download` e2e tests on 0.11.0.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…r delegation `downloadAsset` is not delegatable on the client (`DownloadAssetOptions` does not accept `delegate` — only `loadModel` does), so the previous attempt at porting `cancelDelegatedDownload` to a requestId-based cancel hit TS2353 in the tests-qvac typecheck: Object literal may only specify known properties, and 'delegate' does not exist in type 'DownloadAssetOptions'. Switch the test to start a delegated `loadModel` instead — its inner work includes downloading the asset on the provider side, so the "delegated cancel routes through the delegation pipe" assertion is preserved. Same-process delegation still fails with DELEGATE_CONNECTION_FAILED, which is the asserted success path.
QVAC E2E —
|
QVAC E2E —
|
QVAC E2E —
|
QVAC E2E —
|
QVAC E2E —
|
|
/review |
) * QVAC-18183 feat[bc]: CLI cancel bridge + cancelHandler retirement M3d — the final sub-PR for QVAC-18183 and the release gate for SDK 0.11.0. Six deliverables (plus a late seventh — decorated-promise RAG client APIs — added when consumer-surface audit surfaced the gap), all coupled to the new request-lifecycle system landed in M3a–M3c. 1. CLI cancel bridge. Every OpenAI-compatible route in `qvac serve` (chat, embeddings, transcriptions, translations) now binds `req.on('close')` to `sdkCancel({ requestId })` via a single shared helper `core/cancel-bridge.ts`. The `requestId` is exposed synchronously from `sdkCompletion` / `sdkEmbed` / `sdkTranscribe` on the returned decorated promise — the SDK guarantees it's available before the inference promise settles. The Workbench Stop button now disconnects an HTTP request and the worker actually stops decoding instead of silently running to completion. 2. cancelHandler.ts retirement. The 5-arm dispatcher (`inference` / `embedding` / `transcription` / `translation` / `downloadAsset`) is gone. The handler is now a 2-arm pass-through that delegates to `RequestRegistry.cancel({ requestId })` or `cancelByModelId({ modelId, kind? })`. Option A.2 (shrink to pass-through) was chosen over A.1 (delete entirely) because the handler-registry shape requires a handler function per RPC method; the file now exists only to bridge the wire schema into the registry call. 3. M1 compat-fallback removed. The pre-registry `addon.cancel()` fallback in `server/bare/ops/cancel.ts` (lines 49-71 on the parent commit) is gone. Every cancellable handler is on the registry as of M3a–M3c; broad cancel is a single registry walk. 4. Schema collapse (BREAKING). The wire envelope for `cancel` narrows from a 5-arm discriminated union to a 2-arm union (`{ operation: "request", requestId }` and `{ operation: "broad", modelId, kind? }`). The per-kind public-API sugars for `"inference"` and `"embeddings"` are preserved via thin transforms in `client/api/cancel.ts:normalizeCancelParams`, so the two most common legacy call shapes keep working unchanged. The two shapes that *can't* be mechanically back-mapped are removed: - `cancel({ operation: "downloadAsset", downloadKey, clearCache })` — REMOVED. The old envelope keyed off `downloadKey`, the new path keys off `requestId`. Migration: hold onto the `requestId` exposed on the decorated promise returned by `downloadAsset(...)` and call `cancel({ requestId, clearCache })`. - `cancel({ operation: "rag", workspace? })` — REMOVED. The old envelope had no `requestId`; in M3d the three cancellable RAG client APIs (`ragIngest`, `ragSaveEmbeddings`, `ragReindex`) now return decorated promises so callers can migrate to `cancel({ requestId: op.requestId })`. The non-cancellable RAG ops (`ragChunk`, `ragSearch`, etc.) intentionally do not decorate — they don't register with the request registry server-side. Known affected consumer: - qvac-app-workbench-desktop/workbench-worker/services/ provider-service.ts:91 constructs `{operation:"downloadAsset"}`. - qvac-app-workbench-desktop/workbench-worker/handlers/ rag-handler.ts:169 constructs `{operation:"rag"}`. These need a coordinated migration before workbench-desktop bumps to SDK 0.11.0; tracking as a follow-up Asana task. 5. Typed-error reconstruction. The cross-RPC `instanceof` story is now honest: `errorResponseSchema` carries an optional `typedFields` envelope, `QvacErrorBase` subclasses that need to survive RPC implement `toErrorResponseFields()`, and the client reconstructs them via a keyed map in `client/rpc/rpc-error.ts`. Registered today: `RequestIdConflictError`, `RequestNotFoundError`, `RequestRejectedByPolicyError` — all re-exported from `@qvac/sdk` so consumers can `instanceof` them. Bring-up bug caught in test: `QvacErrorBase.name` is the SCREAMING_SNAKE error-code name (e.g. `REQUEST_REJECTED_BY_POLICY`), not the JS class name; the reconstructor map keys off that exact value and the maintenance contract in the JSDoc spells this out so the next class added doesn't trip the same wire. 6. Docs. `request-lifecycle-system.mdc` no longer claims a fallback to `addon.cancel()` for non-migrated kinds (M3d closes that gap). `error-handling.mdc` documents the reconstructor maintenance contract. `request-lifecycle-primitives.mdc` aligns with the new handler shape. CLI serve workspace rule documents the cancel bridge. 7. Decorated-promise RAG (late add). Three RAG client APIs (`ragIngest`, `ragSaveEmbeddings`, `ragReindex`) now generate a client-side `requestId`, thread it onto the wire envelope, and return `Promise<...> & { requestId: string }`. The wire schema already supported the optional `requestId` field (added in M3b/M3c); this PR closes the client-side wiring gap so the migration story for the removed `cancel({operation:"rag"})` arm is honest — callers actually have a `requestId` to hand to `cancel(...)`. The other six RAG client APIs (chunk/search/delete/list/close/ deleteWorkspace) intentionally stay non-decorated because their handlers don't call `beginRagContext` — they're fast-path operations not subject to mid-flight cancellation. Tests: - `packages/cli/test/cancel-bridge.test.ts` — 4 cases covering happy path, `res.writableEnded` short-circuit, swallowed rejections, and `once` semantics. - `packages/sdk/test/unit/error-typed-fields.test.ts` — 6 cases covering `typedFields` population for each registered class and proper omission for non-registered / client-constructed errors. - `packages/sdk/test/unit/rpc-error-reconstruct.test.ts` — 7 cases covering round-trip reconstruction, fallback to `RPCError` on unknown names, plain-Error fallthrough, defensive defaulting on missing `typedFields`, and remote stack/timestamp attachment. - `packages/sdk/test/unit/request-id-wire.test.ts` — extended with 1 new case for `ragSaveEmbeddings` envelope `requestId` forwarding, matching the existing `ragIngest` / `ragReindex` coverage. Client- side decoration is signature-guaranteed by TypeScript; the schema test pins the wire envelope. Net: 284 CLI unit tests pass, 10 SDK unit tests pass, plus the 18 new M3d cases. Lint + typecheck clean. The pre-existing `semver` typecheck error in `packages/cli/src/verify/bundle/abi.ts` lives on `upstream/main` and is not introduced or affected by this PR. Tag justification: `[bc]` not `[api]`. Two public-API `cancel(...)` call shapes (`downloadAsset`, `rag`) are removed because the old wire envelopes had no `requestId` to mechanically back-map. The RAG migration is supported by deliverable 7 (decorated promises on `ragIngest` / `ragSaveEmbeddings` / `ragReindex`); the `downloadAsset` migration was already supported via the decorated `downloadAsset(...)` promise shipped in M3b/M3c. Per the SDK content-tag rules `[api]` and `[bc]` don't combine; the title carries `[bc]` and the PR body also documents the additive `[api]`-shaped surfaces (decorated- promise `requestId`, typed-error reconstruction, new broad-cancel sugar) under their own section. * doc[notask]: scrub internal milestone references from rules + JSDoc The M3a/M3b/M3c/M3d/M1-era/M2-era milestone identifiers live in private planning artifacts under `tasks/release-0.11.0-planning/` and have no meaning to anyone reading the qvac monorepo. The previous M3d PR leaked them into Cursor rules, JSDoc comments, and test docstrings that future contributors would read with zero context for what those mean. Self-review on PR #2074 surfaced 22 hits across 13 files. All rewrites either drop the milestone tag entirely or rephrase to reference the public release version (0.11.0) or describe the current state of the system in plain English ("legacy" / "as of" / "current"). No behaviour changes; lint + typecheck clean. Doc hits (11): - .cursor/rules/sdk/docs/request-lifecycle-system.mdc lines 77, 195, 196 - .cursor/rules/sdk/request-lifecycle-primitives.mdc lines 19, 247, 374 - .cursor/rules/sdk/docs/kv-cache-system.mdc lines 91, 96, 102, 104, 112 Source hits (7): - packages/sdk/client/rpc/rpc-error.ts: "bug fixed in M3d alongside ..." -> "bug fixed alongside ..." - packages/sdk/schemas/cancel.ts: "M2-era per-kind discriminator arms" / "M3d release-gate cleanup" -> "legacy per-kind discriminator arms" / "0.11.0 cleanup" - packages/sdk/server/bare/ops/cancel.ts: "M1-era pre-registry addon-cancel fallback was removed in M3d" -> "legacy pre-registry addon-cancel fallback was removed in 0.11.0" - packages/sdk/server/rpc/handler-registry.ts: "After the M3d wire-schema collapse" -> "After the 0.11.0 wire-schema collapse" - packages/sdk/server/rpc/handlers/cancel-delegated.ts: "After M3d the cancel envelope ..." -> "After the 0.11.0 wire-schema collapse the cancel envelope ..." - packages/sdk/server/rpc/handlers/cancelHandler.ts: "retired in 0.11.0 (M3d)" -> "retired in 0.11.0" - packages/sdk/server/rpc/handlers/load-model/download-manager.ts: "Added in M3d to support ..." -> "Added in 0.11.0 to support ..." Test docstring hits (4): - packages/sdk/test/unit/runtime/request-registry.test.ts: "Option A in the M3a brief" parenthetical dropped; "pre-M3a behaviour" -> "documented behaviour" - packages/sdk/test/unit/runtime/request-lifecycle-logging.test.ts: "part of the M3a contract" -> "part of the 0.11.0 request-lifecycle contract" - packages/sdk/test/unit/runtime/with-request-context.test.ts: "Covers the M3a brief's Deliverable 3 acceptance criteria" -> "Covers the acceptance criteria" * QVAC-18183 test: migrate tests-qvac download-executor to requestId-based cancel The `download-cancel-isolation` e2e executor was still calling the removed `cancel({operation:"downloadAsset", downloadKey, clearCache})` shape, which crashes at the client-side `requestSchema.parse(...)` in this PR's new 2-arm cancel wire envelope (the executor is itself one of the in-repo consumers of the [bc] documented on the parent commit `0279a56bb`). Surfaced by Lauri running the test locally via `/pr-test` against PR #2074 — the consumer reported a ZodError before the cancel could even reach the SDK server. Migration follows the pattern the PR body documents: capture the decorated promise from `downloadAsset(...)` into `cancelledOp` and cancel by `cancelledOp.requestId` instead of the per-progress-event `downloadKey`. The `p.downloadKey &&` gate is dropped because `requestId` is available synchronously on the decorated promise — no need to wait for the first progress event to surface a key. `bun lint` + typecheck clean on `packages/sdk` (the `tests-qvac` typecheck failures are pre-existing — its `node_modules/@qvac/sdk` is a snapshot populated by `bun run prepare:sdk` rather than a live symlink). The remaining consumer-migration call sites (`config-executor.ts`, `delegated-inference-executor.ts`, public `reference/api/index.mdx` + `models/download-lifecycle.mdx`) are tracked as follow-ups per Simon's scope choice — see the diary entry. * QVAC-18183 doc: trim cancel.ts JSDoc + simplify rag cancellation example Per Opaninakuffo's PR #2074 review: - `client/api/cancel.ts` JSDoc was ~73 lines reading like a mini migration guide. Trimmed to ~25 lines: brief description of the two cancel paths, two examples, and a pointer to the 0.11.0 changelog / release notes for migration detail off the removed `{operation:"downloadAsset"|"rag"}` shapes. Detail lives in the changelog where it belongs, not in code comments that live forever. - `examples/rag/rag-hyperdb/cancellation.ts` was missing the new primary cancel path (`{requestId}`) and the inline comment block was too jargon-heavy for example material ("rag-by-workspace cancel arm", `RequestRegistry`, "worker-singleton" — none of which a reader of the example needs to know). Refactored to capture the decorated promise from `ragIngest(...)` into `const ingest`, cancel via `ingest.requestId` as the primary path, and keep a one-line pointer to the broad-cancel-by-modelId alternative. `bun lint` + typecheck clean. * QVAC-18183 test: migrate tests-qvac config + delegated executors to requestId-based cancel The 0.11.0 cancel surface is requestId-based; the legacy `operation:"downloadAsset"` and per-call `delegate` wire shapes were removed. Migrate the last two tests-qvac executors that still used the old shapes: - config-executor.ts: capture the decorated `downloadAsset` promise and cancel by `op.requestId`. Mechanical mirror of the download-executor.ts migration already on this branch. - delegated-inference-executor.ts: rewrite `cancelDelegatedDownload` to start a delegated `downloadAsset`, obtain a real `requestId` synchronously, and `cancel({ requestId })`. Same-process delegation still fails with DELEGATE_CONNECTION_FAILED, which is the asserted success path. Unblocks the `config-registry-download-respects-cancel` and `cancel-delegated-download` e2e tests on 0.11.0. * QVAC-18183 test: fix delegated-inference-executor to use loadModel for delegation `downloadAsset` is not delegatable on the client (`DownloadAssetOptions` does not accept `delegate` — only `loadModel` does), so the previous attempt at porting `cancelDelegatedDownload` to a requestId-based cancel hit TS2353 in the tests-qvac typecheck: Object literal may only specify known properties, and 'delegate' does not exist in type 'DownloadAssetOptions'. Switch the test to start a delegated `loadModel` instead — its inner work includes downloading the asset on the provider side, so the "delegated cancel routes through the delegation pipe" assertion is preserved. Same-process delegation still fails with DELEGATE_CONNECTION_FAILED, which is the asserted success path.
🎯 What problem does this PR solve?
RequestRegistry; this PR closes three remaining gaps so the new cancel surface is actually usable end-to-end — and retires three pieces of pre-registry baggage on the way.req.abortedoverqvac serve) was non-functional: the SDK exposedcancel({ requestId })but no route handler bound it toreq.on('close'). Long inference jobs ran to completion even after the client disconnected, wasting GPU and blocking concurrent requests behind cancel-policy gates.cancelHandler.ts5-arm dispatcher. Pre-registry baggage. The handler still narrowed onoperation: "inference" | "embedding" | "transcription" | "translation" | "downloadAsset"and called into per-kind shim code. With every kind now on the registry, that switch is dead weight and an explicit "do not extend" sign for future contributors.server/bare/ops/cancel.ts. Lines 49-71 still calledaddon.cancel()directly for "non-migrated kinds" — but there are no non-migrated kinds as of the prior sub-PR. Dead code.instanceofwas lying. Server threwRequestRejectedByPolicyError; client received a genericRPCErrorwith the rightmessagebut the wrong prototype. Documented inerror-handling.mdcas if it worked; it didn't.📝 How does it solve it?
packages/cli/src/serve/core/cancel-bridge.ts, new). SinglebindClientDisconnectCancel(req, res, requestId, logger)helper attachesreq.once('close', ...), short-circuits ifres.writableEnded(so a normal completion is never a spurious cancel), callssdkCancel({ requestId }), and swallows the rejection. Wired into all four OpenAI routes: chat, embeddings, transcriptions, translations.requestId(packages/cli/src/serve/core/sdk.ts). The CLI-internalsdkCompletion/sdkEmbed/sdkTranscribewrappers expose therequestIdsynchronously on the returned promise, riding the SDK-side decoration that already existed onembed/transcribeand was extended in the earlier QVAC-18183 sub-PRs toloadModel/downloadAsset. The route handler can therefore bind the disconnect listener on the same tick as the dispatch.requestIdfor cancellable RAG ops (packages/sdk/client/api/rag.ts).ragIngest,ragSaveEmbeddings, andragReindex— the three RAG operations that register withRequestRegistryserver-side (perbeginRagContextatserver/rpc/handlers/rag.ts:152,175,216) — now generate a client-siderequestId, thread it onto the wire envelope (the wire schema already supported the optional field), and decorate the returned promise. This closes the migration story for the removedcancel({operation:"rag", workspace?})arm: callers hold ontoop.requestIdfromragIngest(...)etc. and callcancel({ requestId }). The non-cancellable RAG ops (ragChunk,ragSearch,ragDeleteEmbeddings,ragListWorkspaces,ragCloseWorkspace,ragDeleteWorkspace) intentionally stay non-decorated — they don't register with the registry, so arequestIdwould point at nothing.cancelHandler.tsshrunk to 2-arm pass-through (packages/sdk/server/rpc/handlers/cancelHandler.ts). Option A.2 (shrink) rather than A.1 (delete) because the handler-registry shape requires a function per RPC method; the file now does only schema dispatch intogetRequestRegistry().cancel({ requestId })orcancelByModelId({ modelId, kind? }). ~80 LOC removed.packages/sdk/server/bare/ops/cancel.ts). Lines 49-71 on the parent commit (addon.cancel()direct-call) deleted; broad-cancel is now a singleRequestRegistrywalk.packages/sdk/schemas/cancel.ts). Wire envelope narrows from a 5-arm discriminated union to a 2-arm union ({ operation: "request", requestId },{ operation: "broad", modelId, kind? }). The per-kind public-API sugars for"inference"and"embeddings"are preserved via thin transforms inclient/api/cancel.ts:normalizeCancelParams; the two shapes that can't be mechanically back-mapped (downloadAssetkeyed offdownloadKey,raghad no key at all) are removed, which is the source of the[bc]tag below.packages/sdk/client/rpc/rpc-error.ts,rpc-client.ts,schemas/error.ts,utils/errors-server.ts,index.ts).errorResponseSchemacarries an optionaltypedFields: Record<string, unknown>.QvacErrorBasesubclasses that need to survive RPC implementtoErrorResponseFields(); the client reconstructs them via a keyed map inrpc-error.ts. Registered today:RequestIdConflictError,RequestNotFoundError,RequestRejectedByPolicyError— all re-exported from@qvac/sdksoerr instanceof RequestRejectedByPolicyErroractually narrows. The map is keyed byresponse.name, which is the SCREAMING_SNAKE error-code name (REQUEST_REJECTED_BY_POLICY), not the JS class name — JSDoc on the map spells out the maintenance contract so the next class added doesn't trip the same wire.request-lifecycle-system.mdcno longer claims a fallback toaddon.cancel()for non-migrated kinds (this PR closes that gap).error-handling.mdcdocuments the reconstructor maintenance contract.request-lifecycle-primitives.mdcaligns with the new handler shape.M3a/M3b/M3c/M3d/M1-era/M2-era) from Cursor rules + JSDoc comments + test docstrings — 22 hits across 13 files, comment-only (no behaviour change). Those names live intasks/release-0.11.0-planning/and have no meaning to anyone reading the qvac monorepo six months from now; replacements use the public release version (0.11.0), the wordlegacy, or describe the current state of the system in plain English.bun lint+ typecheck clean.🧪 How was it tested?
packages/cli/test/cancel-bridge.test.ts— 4 cases: happy path,res.writableEndedshort-circuit, swallowedsdkCancelrejections,oncesemantics (no double-fire on a secondclose).packages/sdk/test/unit/error-typed-fields.test.ts— 6 cases:typedFieldspopulation for each registered class, proper omission for non-registered (ModelNotLoadedError) and client-constructed (InferenceCancelledError) errors, plainErrorenvelope.packages/sdk/test/unit/rpc-error-reconstruct.test.ts— 7 cases: round-trip reconstruction for all three registered classes, fallback toRPCErroron unknown names, plain-Error fallthrough, defensive defaulting on missingtypedFields, remote stack/timestamp attachment.packages/sdk/test/unit/request-id-wire.test.ts— added 1 new case forragSaveEmbeddingsenveloperequestIdforwarding, matching the existingragIngest/ragReindexcoverage. (Client-side decoration is signature-guaranteed by TypeScript — every caller readingop.requestIdsynchronously is typecheck-asserted; the schema test pins the wire envelope.)packages/cli: 284 tests pass (excluding the pre-existingtest/verify-bundle.test.tswhich is blocked by theCannot find module 'semver'typecheck failure insrc/verify/bundle/abi.ts— that error lives onupstream/main(53eec2f83) and is unaffected by this PR).packages/sdk: 10 unit tests pass;bun run lint(eslint + tsc) clean.qvac serveagainst a llama.cpp model, fired a long completion viacurl, killed the curl mid-stream, confirmed the worker stopped decoding within one decode tick (loggedcancelled requestId=...and theRequestRegistryslot freed). Confirmed a normal completion does not triggersdkCancel(theres.writableEndedshort-circuit).💥 Breaking Changes
Two public-API
cancel(...)call shapes are removed from@qvac/sdkin 0.11.0. They never carried arequestId(and therefore can't be mechanically back-mapped onto the new wire envelope) — callers must migrate to therequestId-targeted cancel path (fordownloadAsset) or the broad-cancel-by-modelIdescape hatch (forrag).1.
cancel({ operation: "downloadAsset", downloadKey, clearCache })removed.The replacement is the
requestIdexposed synchronously on the decorated promise returned bydownloadAsset(...). TheclearCacheflag is honoured on therequestIdpath.BEFORE:
AFTER:
2.
cancel({ operation: "rag", workspace? })removed.The three cancellable RAG operations (
ragIngest,ragSaveEmbeddings,ragReindex) now return decorated promises in 0.11.0 — therequestIdis exposed synchronously on the returned handle so callers can target a specific in-flight RAG op withcancel({ requestId }). The remaining RAG client APIs (ragChunk,ragSearch,ragDeleteEmbeddings, workspace lifecycle) intentionally do not decorate — they're fast-path operations that don't register with the server-side request registry. For "cancel everything RAG" sweeps without arequestIdto hand, use the broad-cancel-by-modelIdescape hatch.BEFORE:
AFTER: — by
requestId(primary path)AFTER: — broad cancel (escape hatch, no requestId to hand)
Preserved (NOT breaking) — every other call shape still works.
normalizeCancelParamstranslates the two most common legacy sugars to the new wire envelope at the client boundary:🔌 API Changes
1. Decorated-promise
requestIdon every cancellable long-running SDK call — exposed synchronously on the returned promise so the caller can bind cancellation listeners on the same tick as the dispatch. The pattern was introduced in earlier sub-PRs forembed/transcribeand extended in the prior QVAC-18183 sub-PRs toloadModel/downloadAsset. This PR extends it once more to the three cancellable RAG operations (ragIngest,ragSaveEmbeddings,ragReindex) and matches theCompletionRun.requestIdfield thatcompletion(...)has exposed since the first QVAC-18183 sub-PR landed:The non-cancellable RAG ops (
ragChunk,ragSearch,ragDeleteEmbeddings,ragListWorkspaces,ragCloseWorkspace,ragDeleteWorkspace) intentionally do not decorate — they're fast-path operations that don't register with the server-side request registry, so there's no in-flight context for arequestIdto point at.2. Typed-error
instanceofacross the RPC boundary. Three server-thrown classes are re-exported from@qvac/sdkand now actually round-trip with their constructor fields preserved:3. New broad-cancel sugar
cancel({ modelId, kind? }). Replaces the per-kind dispatcher arms with a single explicit broad-cancel shape: