@qvac/sdk 0.10.2 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/NOTICE +92 -54
  2. package/dist/client/api/cancel.d.ts +24 -32
  3. package/dist/client/api/cancel.js +58 -31
  4. package/dist/client/api/client-request-id.d.ts +17 -0
  5. package/dist/client/api/client-request-id.js +27 -0
  6. package/dist/client/api/completion-stream.d.ts +1 -1
  7. package/dist/client/api/completion-stream.js +34 -3
  8. package/dist/client/api/diffusion.d.ts +46 -0
  9. package/dist/client/api/diffusion.js +50 -1
  10. package/dist/client/api/download-asset.d.ts +12 -2
  11. package/dist/client/api/download-asset.js +21 -3
  12. package/dist/client/api/embed.d.ts +8 -4
  13. package/dist/client/api/embed.js +14 -1
  14. package/dist/client/api/get-model-info.d.ts +1 -1
  15. package/dist/client/api/index.d.ts +1 -0
  16. package/dist/client/api/index.js +1 -0
  17. package/dist/client/api/load-model.d.ts +12 -4
  18. package/dist/client/api/load-model.js +25 -1
  19. package/dist/client/api/rag.d.ts +9 -3
  20. package/dist/client/api/rag.js +23 -3
  21. package/dist/client/api/transcribe.d.ts +20 -8
  22. package/dist/client/api/transcribe.js +58 -4
  23. package/dist/client/api/unload-model.d.ts +5 -2
  24. package/dist/client/api/unload-model.js +9 -4
  25. package/dist/client/api/upscale.d.ts +45 -0
  26. package/dist/client/api/upscale.js +99 -0
  27. package/dist/client/rpc/expo-rpc-client.js +2 -1
  28. package/dist/client/rpc/node-rpc-client.js +18 -7
  29. package/dist/client/rpc/rpc-client.d.ts +2 -2
  30. package/dist/client/rpc/rpc-client.js +10 -4
  31. package/dist/client/rpc/rpc-error.d.ts +9 -0
  32. package/dist/client/rpc/rpc-error.js +92 -0
  33. package/dist/examples/cancel-by-request-id.d.ts +38 -0
  34. package/dist/examples/cancel-by-request-id.js +103 -0
  35. package/dist/examples/diffusion-esrgan-upscale.d.ts +2 -0
  36. package/dist/examples/diffusion-esrgan-upscale.js +78 -0
  37. package/dist/examples/download-with-cancel.js +10 -10
  38. package/dist/examples/embed-multi-gpu.d.ts +2 -0
  39. package/dist/examples/embed-multi-gpu.js +46 -0
  40. package/dist/examples/llamacpp-multi-gpu.d.ts +2 -0
  41. package/dist/examples/llamacpp-multi-gpu.js +57 -0
  42. package/dist/examples/rag/rag-hyperdb/cancellation.js +20 -17
  43. package/dist/examples/tools/llamacpp-tools-gemma4.d.ts +2 -0
  44. package/dist/examples/tools/llamacpp-tools-gemma4.js +76 -0
  45. package/dist/examples/tools/llamacpp-tools-qwen35.d.ts +2 -0
  46. package/dist/examples/tools/llamacpp-tools-qwen35.js +70 -0
  47. package/dist/examples/transcription/whispercpp-microphone-conversation.d.ts +2 -0
  48. package/dist/examples/transcription/whispercpp-microphone-conversation.js +102 -0
  49. package/dist/examples/tts/supertonic.js +1 -1
  50. package/dist/expo/plugins/withMobileBundle.d.ts +20 -4
  51. package/dist/expo/plugins/withMobileBundle.js +44 -6
  52. package/dist/index.d.ts +5 -2
  53. package/dist/index.js +21 -1
  54. package/dist/models/registry/models.d.ts +186 -318
  55. package/dist/models/registry/models.js +1522 -1667
  56. package/dist/pear/pre.d.ts +3 -0
  57. package/dist/pear/pre.js +3 -0
  58. package/dist/schemas/cancel.d.ts +167 -28
  59. package/dist/schemas/cancel.js +119 -19
  60. package/dist/schemas/common.d.ts +427 -208
  61. package/dist/schemas/common.js +3 -1
  62. package/dist/schemas/completion-event.d.ts +14 -0
  63. package/dist/schemas/completion-event.js +11 -1
  64. package/dist/schemas/completion-stream.d.ts +15 -1
  65. package/dist/schemas/completion-stream.js +25 -7
  66. package/dist/schemas/download-asset.d.ts +15 -9
  67. package/dist/schemas/download-asset.js +17 -6
  68. package/dist/schemas/embed.d.ts +1 -0
  69. package/dist/schemas/embed.js +5 -0
  70. package/dist/schemas/error.d.ts +31 -0
  71. package/dist/schemas/error.js +29 -1
  72. package/dist/schemas/finetune.d.ts +2 -0
  73. package/dist/schemas/finetune.js +5 -0
  74. package/dist/schemas/get-model-info.d.ts +6 -6
  75. package/dist/schemas/llamacpp-config.d.ts +54 -8
  76. package/dist/schemas/llamacpp-config.js +12 -0
  77. package/dist/schemas/load-model.d.ts +1911 -1260
  78. package/dist/schemas/load-model.js +15 -0
  79. package/dist/schemas/model-src-utils.d.ts +14 -14
  80. package/dist/schemas/model-types.d.ts +10 -10
  81. package/dist/schemas/ocr.d.ts +3 -3
  82. package/dist/schemas/plugin.d.ts +40 -1
  83. package/dist/schemas/plugin.js +10 -1
  84. package/dist/schemas/rag.d.ts +9 -0
  85. package/dist/schemas/rag.js +17 -9
  86. package/dist/schemas/registry.d.ts +30 -30
  87. package/dist/schemas/reload-config.d.ts +14 -14
  88. package/dist/schemas/sdcpp-config.d.ts +131 -17
  89. package/dist/schemas/sdcpp-config.js +163 -1
  90. package/dist/schemas/sdk-config.d.ts +649 -271
  91. package/dist/schemas/sdk-errors-client.d.ts +1 -0
  92. package/dist/schemas/sdk-errors-client.js +5 -0
  93. package/dist/schemas/sdk-errors-server.d.ts +5 -0
  94. package/dist/schemas/sdk-errors-server.js +25 -0
  95. package/dist/schemas/text-to-speech.d.ts +78 -78
  96. package/dist/schemas/transcription-config.d.ts +24 -24
  97. package/dist/schemas/transcription.d.ts +56 -2
  98. package/dist/schemas/transcription.js +27 -0
  99. package/dist/schemas/translate.d.ts +2 -0
  100. package/dist/schemas/translate.js +13 -2
  101. package/dist/schemas/translation-config.d.ts +40 -40
  102. package/dist/schemas/unload-model.d.ts +2 -1
  103. package/dist/schemas/unload-model.js +4 -1
  104. package/dist/scripts/run-unit-tests.js +15 -2
  105. package/dist/server/bare/ops/cancel.d.ts +27 -1
  106. package/dist/server/bare/ops/cancel.js +36 -10
  107. package/dist/server/bare/ops/embed.d.ts +3 -3
  108. package/dist/server/bare/ops/embed.js +144 -28
  109. package/dist/server/bare/ops/kv-cache-utils.d.ts +0 -7
  110. package/dist/server/bare/ops/kv-cache-utils.js +8 -47
  111. package/dist/server/bare/ops/transcribe.d.ts +10 -5
  112. package/dist/server/bare/ops/transcribe.js +196 -41
  113. package/dist/server/bare/ops/translate.d.ts +1 -1
  114. package/dist/server/bare/ops/translate.js +197 -88
  115. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.d.ts +12 -3
  116. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +170 -172
  117. package/dist/server/bare/plugins/llamacpp-completion/ops/finetune.js +125 -21
  118. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-session.d.ts +154 -0
  119. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-session.js +448 -0
  120. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.d.ts +21 -73
  121. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.js +18 -101
  122. package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +30 -3
  123. package/dist/server/bare/plugins/llamacpp-completion/plugin.js +157 -85
  124. package/dist/server/bare/plugins/llamacpp-completion/transform.d.ts +10 -0
  125. package/dist/server/bare/plugins/llamacpp-completion/transform.js +34 -0
  126. package/dist/server/bare/plugins/llamacpp-embedding/plugin.d.ts +7 -0
  127. package/dist/server/bare/plugins/llamacpp-embedding/plugin.js +10 -1
  128. package/dist/server/bare/plugins/nmtcpp-translation/plugin.d.ts +17 -15
  129. package/dist/server/bare/plugins/nmtcpp-translation/plugin.js +5 -1
  130. package/dist/server/bare/plugins/onnx-ocr/plugin.d.ts +3 -3
  131. package/dist/server/bare/plugins/onnx-ocr/plugin.js +3 -0
  132. package/dist/server/bare/plugins/onnx-tts/plugin.d.ts +39 -39
  133. package/dist/server/bare/plugins/onnx-tts/plugin.js +6 -0
  134. package/dist/server/bare/plugins/parakeet-transcription/plugin.d.ts +29 -21
  135. package/dist/server/bare/plugins/parakeet-transcription/plugin.js +4 -1
  136. package/dist/server/bare/plugins/sdcpp-generation/ops/diffusion.js +8 -0
  137. package/dist/server/bare/plugins/sdcpp-generation/ops/upscale.d.ts +3 -0
  138. package/dist/server/bare/plugins/sdcpp-generation/ops/upscale.js +40 -0
  139. package/dist/server/bare/plugins/sdcpp-generation/plugin.d.ts +91 -16
  140. package/dist/server/bare/plugins/sdcpp-generation/plugin.js +97 -7
  141. package/dist/server/bare/plugins/whispercpp-transcription/plugin.d.ts +22 -3
  142. package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +50 -14
  143. package/dist/server/bare/rag-hyperdb/index.d.ts +1 -1
  144. package/dist/server/bare/rag-hyperdb/index.js +1 -1
  145. package/dist/server/bare/rag-hyperdb/rag-operation-manager.d.ts +26 -4
  146. package/dist/server/bare/rag-hyperdb/rag-operation-manager.js +65 -28
  147. package/dist/server/bare/runtime/disposable-scope.d.ts +36 -0
  148. package/dist/server/bare/runtime/disposable-scope.js +69 -0
  149. package/dist/server/bare/runtime/index.d.ts +8 -0
  150. package/dist/server/bare/runtime/index.js +3 -0
  151. package/dist/server/bare/runtime/request-context.d.ts +49 -0
  152. package/dist/server/bare/runtime/request-context.js +1 -0
  153. package/dist/server/bare/runtime/request-id.d.ts +12 -0
  154. package/dist/server/bare/runtime/request-id.js +14 -0
  155. package/dist/server/bare/runtime/request-registry-singleton.d.ts +4 -0
  156. package/dist/server/bare/runtime/request-registry-singleton.js +27 -0
  157. package/dist/server/bare/runtime/request-registry.d.ts +136 -0
  158. package/dist/server/bare/runtime/request-registry.js +297 -0
  159. package/dist/server/bare/runtime/with-request-context.d.ts +22 -0
  160. package/dist/server/bare/runtime/with-request-context.js +53 -0
  161. package/dist/server/bare/types/addon-responses.d.ts +11 -1
  162. package/dist/server/rpc/handler-registry.js +26 -7
  163. package/dist/server/rpc/handlers/cancel-delegated.js +28 -31
  164. package/dist/server/rpc/handlers/cancelHandler.d.ts +30 -1
  165. package/dist/server/rpc/handlers/cancelHandler.js +54 -22
  166. package/dist/server/rpc/handlers/delete-cache.d.ts +9 -0
  167. package/dist/server/rpc/handlers/delete-cache.js +13 -15
  168. package/dist/server/rpc/handlers/download-asset.js +133 -40
  169. package/dist/server/rpc/handlers/index.d.ts +2 -0
  170. package/dist/server/rpc/handlers/index.js +2 -0
  171. package/dist/server/rpc/handlers/load-model/download-manager.d.ts +60 -2
  172. package/dist/server/rpc/handlers/load-model/download-manager.js +141 -8
  173. package/dist/server/rpc/handlers/load-model/handler.js +213 -98
  174. package/dist/server/rpc/handlers/load-model/http.js +3 -3
  175. package/dist/server/rpc/handlers/load-model/hyperdrive.js +1 -1
  176. package/dist/server/rpc/handlers/load-model/registry.js +1 -1
  177. package/dist/server/rpc/handlers/load-model/resolve-session.d.ts +20 -1
  178. package/dist/server/rpc/handlers/load-model/resolve-session.js +6 -5
  179. package/dist/server/rpc/handlers/load-model/resolve.d.ts +3 -2
  180. package/dist/server/rpc/handlers/load-model/resolve.js +9 -6
  181. package/dist/server/rpc/handlers/load-model/types.d.ts +24 -0
  182. package/dist/server/rpc/handlers/rag.js +133 -15
  183. package/dist/server/rpc/handlers/upscale-stream.d.ts +3 -0
  184. package/dist/server/rpc/handlers/upscale-stream.js +4 -0
  185. package/dist/server/utils/completion-normalizer.js +8 -0
  186. package/dist/server/utils/tools/dialect.js +4 -0
  187. package/dist/server/utils/tools/parser.js +16 -1
  188. package/dist/server/utils/tools/parsers/gemma4native.d.ts +4 -0
  189. package/dist/server/utils/tools/parsers/gemma4native.js +60 -0
  190. package/dist/server/utils/tools/parsers/qwen35.d.ts +4 -0
  191. package/dist/server/utils/tools/parsers/qwen35.js +120 -0
  192. package/dist/utils/aggregate-events.d.ts +9 -0
  193. package/dist/utils/aggregate-events.js +18 -3
  194. package/dist/utils/decorate-promise.d.ts +34 -0
  195. package/dist/utils/decorate-promise.js +35 -0
  196. package/dist/utils/errors-client.d.ts +3 -0
  197. package/dist/utils/errors-client.js +5 -0
  198. package/dist/utils/errors-server.d.ts +85 -0
  199. package/dist/utils/errors-server.js +97 -0
  200. package/package.json +20 -15
@@ -76,6 +76,9 @@ export declare const whisperPlugin: {
76
76
  sha256Checksum: import("zod").ZodOptional<import("zod").ZodString>;
77
77
  addon: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodEnum<{
78
78
  embeddings: "embeddings";
79
+ diffusion: "diffusion";
80
+ tts: "tts";
81
+ ocr: "ocr";
79
82
  "llamacpp-completion": "llamacpp-completion";
80
83
  "whispercpp-transcription": "whispercpp-transcription";
81
84
  "llamacpp-embedding": "llamacpp-embedding";
@@ -88,9 +91,6 @@ export declare const whisperPlugin: {
88
91
  whisper: "whisper";
89
92
  nmt: "nmt";
90
93
  parakeet: "parakeet";
91
- tts: "tts";
92
- ocr: "ocr";
93
- diffusion: "diffusion";
94
94
  }>, import("zod").ZodLiteral<"vad">]>>;
95
95
  }, import("zod/v4/core").$strip>]>>;
96
96
  }, import("zod/v4/core").$strip>;
@@ -225,6 +225,7 @@ export declare const whisperPlugin: {
225
225
  value: import("zod").ZodString;
226
226
  }, import("zod/v4/core").$strip>], "type">;
227
227
  type: import("zod").ZodLiteral<"transcribe">;
228
+ requestId: import("zod").ZodOptional<import("zod").ZodString>;
228
229
  }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
229
230
  text: import("zod").ZodOptional<import("zod").ZodString>;
230
231
  done: import("zod").ZodOptional<import("zod").ZodBoolean>;
@@ -248,6 +249,13 @@ export declare const whisperPlugin: {
248
249
  append: import("zod").ZodBoolean;
249
250
  id: import("zod").ZodNumber;
250
251
  }, import("zod/v4/core").$strip>>;
252
+ vad: import("zod").ZodOptional<import("zod").ZodObject<{
253
+ speaking: import("zod").ZodBoolean;
254
+ probability: import("zod").ZodNumber;
255
+ }, import("zod/v4/core").$strip>>;
256
+ endOfTurn: import("zod").ZodOptional<import("zod").ZodObject<{
257
+ silenceDurationMs: import("zod").ZodNumber;
258
+ }, import("zod/v4/core").$strip>>;
251
259
  type: import("zod").ZodLiteral<"transcribe">;
252
260
  }, import("zod/v4/core").$strip>>;
253
261
  transcribeStream: import("../../../../schemas/index").PluginHandlerDefinition<import("zod").ZodObject<{
@@ -255,6 +263,10 @@ export declare const whisperPlugin: {
255
263
  prompt: import("zod").ZodOptional<import("zod").ZodString>;
256
264
  metadata: import("zod").ZodOptional<import("zod").ZodBoolean>;
257
265
  type: import("zod").ZodLiteral<"transcribeStream">;
266
+ emitVadEvents: import("zod").ZodOptional<import("zod").ZodBoolean>;
267
+ endOfTurnSilenceMs: import("zod").ZodOptional<import("zod").ZodNumber>;
268
+ vadRunIntervalMs: import("zod").ZodOptional<import("zod").ZodNumber>;
269
+ requestId: import("zod").ZodOptional<import("zod").ZodString>;
258
270
  }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
259
271
  text: import("zod").ZodOptional<import("zod").ZodString>;
260
272
  done: import("zod").ZodOptional<import("zod").ZodBoolean>;
@@ -278,6 +290,13 @@ export declare const whisperPlugin: {
278
290
  append: import("zod").ZodBoolean;
279
291
  id: import("zod").ZodNumber;
280
292
  }, import("zod/v4/core").$strip>>;
293
+ vad: import("zod").ZodOptional<import("zod").ZodObject<{
294
+ speaking: import("zod").ZodBoolean;
295
+ probability: import("zod").ZodNumber;
296
+ }, import("zod/v4/core").$strip>>;
297
+ endOfTurn: import("zod").ZodOptional<import("zod").ZodObject<{
298
+ silenceDurationMs: import("zod").ZodNumber;
299
+ }, import("zod/v4/core").$strip>>;
281
300
  type: import("zod").ZodLiteral<"transcribeStream">;
282
301
  }, import("zod/v4/core").$strip>>;
283
302
  };
@@ -52,6 +52,9 @@ export const whisperPlugin = definePlugin({
52
52
  requestSchema: transcribeRequestSchema,
53
53
  responseSchema: transcribeResponseSchema,
54
54
  streaming: true,
55
+ // whisper.cpp addon exposes a model-wide hard cancel — compute
56
+ // is interrupted on the currently-running transcription.
57
+ cancel: { scope: "model", hard: true },
55
58
  handler: async function* (request) {
56
59
  const metadata = request.metadata === true;
57
60
  const stream = metadata
@@ -60,12 +63,12 @@ export const whisperPlugin = definePlugin({
60
63
  audioChunk: request.audioChunk,
61
64
  prompt: request.prompt,
62
65
  metadata: true,
63
- })
66
+ }, request.requestId)
64
67
  : transcribe({
65
68
  modelId: request.modelId,
66
69
  audioChunk: request.audioChunk,
67
70
  prompt: request.prompt,
68
- });
71
+ }, request.requestId);
69
72
  try {
70
73
  let result = await stream.next();
71
74
  while (!result.done) {
@@ -98,22 +101,55 @@ export const whisperPlugin = definePlugin({
98
101
  responseSchema: transcribeStreamResponseSchema,
99
102
  streaming: true,
100
103
  duplex: true,
104
+ // Same model-wide hard cancel surface as `transcribe` — both
105
+ // route through the whisper.cpp addon.
106
+ cancel: { scope: "model", hard: true },
101
107
  handler: async function* (request, inputStream) {
102
- if (request.metadata === true) {
103
- for await (const segment of transcribeStream(request.modelId, inputStream, request.prompt, true)) {
104
- yield {
105
- type: "transcribeStream",
106
- segment,
107
- };
108
+ const streamOpts = {
109
+ ...(request.emitVadEvents !== undefined && {
110
+ emitVadEvents: request.emitVadEvents,
111
+ }),
112
+ ...(request.endOfTurnSilenceMs !== undefined && {
113
+ endOfTurnSilenceMs: request.endOfTurnSilenceMs,
114
+ }),
115
+ ...(request.vadRunIntervalMs !== undefined && {
116
+ vadRunIntervalMs: request.vadRunIntervalMs,
117
+ }),
118
+ };
119
+ const metadata = request.metadata === true;
120
+ const iterator = metadata
121
+ ? transcribeStream(request.modelId, inputStream, request.prompt, true, streamOpts, request.requestId)
122
+ : transcribeStream(request.modelId, inputStream, request.prompt, false, streamOpts, request.requestId);
123
+ for await (const value of iterator) {
124
+ if (typeof value === "object" && value !== null && "type" in value) {
125
+ if (value.type === "vad") {
126
+ yield {
127
+ type: "transcribeStream",
128
+ vad: {
129
+ speaking: value.speaking,
130
+ probability: value.probability,
131
+ },
132
+ };
133
+ continue;
134
+ }
135
+ if (value.type === "endOfTurn") {
136
+ yield {
137
+ type: "transcribeStream",
138
+ endOfTurn: { silenceDurationMs: value.silenceDurationMs },
139
+ };
140
+ continue;
141
+ }
142
+ continue;
108
143
  }
109
- }
110
- else {
111
- for await (const text of transcribeStream(request.modelId, inputStream, request.prompt)) {
112
- yield {
144
+ yield metadata
145
+ ? {
113
146
  type: "transcribeStream",
114
- text,
147
+ segment: value,
148
+ }
149
+ : {
150
+ type: "transcribeStream",
151
+ text: value,
115
152
  };
116
- }
117
153
  }
118
154
  yield {
119
155
  type: "transcribeStream",
@@ -8,5 +8,5 @@ export { listWorkspaces } from "./handlers/list-workspaces";
8
8
  export { closeWorkspace } from "./handlers/close-workspace";
9
9
  export { deleteWorkspace } from "./handlers/delete-workspace";
10
10
  export { closeAllRagInstances, DEFAULT_WORKSPACE, type RagWorkspaceInfo, } from "./rag-workspace-manager";
11
- export { registerRagOperation, unregisterRagOperation, cancelRagOperation, } from "./rag-operation-manager";
11
+ export { getActiveRagRequest, setActiveRagRequest, clearActiveRagRequest, getWorkspaceKey, } from "./rag-operation-manager";
12
12
  //# sourceMappingURL=index.d.ts.map
@@ -8,4 +8,4 @@ export { listWorkspaces } from "./handlers/list-workspaces.js";
8
8
  export { closeWorkspace } from "./handlers/close-workspace.js";
9
9
  export { deleteWorkspace } from "./handlers/delete-workspace.js";
10
10
  export { closeAllRagInstances, DEFAULT_WORKSPACE, } from "./rag-workspace-manager.js";
11
- export { registerRagOperation, unregisterRagOperation, cancelRagOperation, } from "./rag-operation-manager.js";
11
+ export { getActiveRagRequest, setActiveRagRequest, clearActiveRagRequest, getWorkspaceKey, } from "./rag-operation-manager.js";
@@ -1,7 +1,29 @@
1
- import { type AbortSignal } from "bare-abort-controller";
2
1
  export declare function getWorkspaceKey(workspace?: string): string;
3
- export declare function registerRagOperation(workspace: string | undefined, operation: string): AbortSignal;
4
- export declare function unregisterRagOperation(workspace?: string): void;
5
- export declare function cancelRagOperation(workspace?: string): boolean;
2
+ /**
3
+ * Returns the `requestId` of any in-flight RAG operation on the workspace
4
+ * (or `undefined` if none). The dispatcher uses this to decide whether to
5
+ * pre-empt before calling `registry.begin(...)`.
6
+ */
7
+ export declare function getActiveRagRequest(workspace?: string): string | undefined;
8
+ /**
9
+ * Records the `requestId` of a freshly-begun RAG operation. Called by the
10
+ * dispatcher in `rag.ts` after `registry.begin(...)` succeeds; paired with
11
+ * `clearActiveRagRequest` via the request scope's deferred cleanup so the
12
+ * map never outlives the request.
13
+ */
14
+ export declare function setActiveRagRequest(workspace: string | undefined, requestId: string): void;
15
+ /**
16
+ * Clears the workspace's mapping iff it still belongs to `requestId`. The
17
+ * conditional guard handles the natural race between two ingest calls on
18
+ * the same workspace: the older context's scope unwind must not stomp the
19
+ * newer context's mapping installed by the pre-emption sequence.
20
+ */
21
+ export declare function clearActiveRagRequest(workspace: string | undefined, requestId: string): void;
22
+ /**
23
+ * Shutdown / workspace-close sweep. Cancels every tracked RAG request via
24
+ * the registry and clears the workspace map. Idempotent — callers that
25
+ * re-invoke during a teardown (workspace-close fired twice, shutdown
26
+ * racing with `close-all`) get a no-op on the second pass.
27
+ */
6
28
  export declare function cancelAllRagOperations(): void;
7
29
  //# sourceMappingURL=rag-operation-manager.d.ts.map
@@ -1,39 +1,76 @@
1
- import { AbortController } from "bare-abort-controller";
2
- import { DEFAULT_WORKSPACE } from "./rag-workspace-manager.js";
3
- // Map of workspace -> active operation
4
- const activeOperations = new Map();
1
+ import { getRequestRegistry } from "../runtime/index.js";
2
+ // Sentinel for "no workspace specified". Mirrors the value re-exported
3
+ // from `rag-workspace-manager.ts`; redeclared locally so this module is
4
+ // safely importable in environments that don't have the Bare runtime
5
+ // (unit tests, doc generators) — `rag-workspace-manager` pulls in
6
+ // `bare-fs` / `bare-path` at module load.
7
+ const DEFAULT_WORKSPACE = "default";
8
+ /**
9
+ * RAG operation tracking — workspace-level admission bookkeeping.
10
+ *
11
+ * In 0.11.0 the cancel surface for in-flight RAG operations consolidates
12
+ * onto the request registry (`getRequestRegistry().cancel({ requestId })`).
13
+ * The historical workspace-level pre-emption rule — "starting a new
14
+ * `ingest` / `reindex` / `saveEmbeddings` on a workspace cancels any prior
15
+ * op on the same workspace" — is preserved by the dispatcher in
16
+ * `server/rpc/handlers/rag.ts`: the dispatcher cancels the workspace's
17
+ * prior `requestId` (if any) and then begins a new registry context.
18
+ * Workspace-level admission lives in the dispatcher rather than as a
19
+ * registry policy primitive — it's a dispatch concern, not part of the
20
+ * registry's per-`kind` admission rules.
21
+ *
22
+ * This module owns the small workspace → requestId map that makes that
23
+ * pre-emption decision routable from the dispatcher. The map is module-
24
+ * scoped (one per Bare worker) so the dispatcher, the shutdown sweep
25
+ * (`cancelAllRagOperations`), and the workspace-close sweep (which
26
+ * delegates to it via `rag-workspace-manager.ts`) all see the same state.
27
+ */
28
+ // workspace key → requestId of the in-flight RAG operation on that workspace.
29
+ const activeRagRequestByWorkspace = new Map();
5
30
  export function getWorkspaceKey(workspace) {
6
31
  return workspace ?? DEFAULT_WORKSPACE;
7
32
  }
8
- export function registerRagOperation(workspace, operation) {
9
- const key = getWorkspaceKey(workspace);
10
- // Cancel any existing operation on this workspace
11
- cancelRagOperation(workspace);
12
- const abortController = new AbortController();
13
- activeOperations.set(key, {
14
- abortController,
15
- operation,
16
- startTime: Date.now(),
17
- });
18
- return abortController.signal;
33
+ /**
34
+ * Returns the `requestId` of any in-flight RAG operation on the workspace
35
+ * (or `undefined` if none). The dispatcher uses this to decide whether to
36
+ * pre-empt before calling `registry.begin(...)`.
37
+ */
38
+ export function getActiveRagRequest(workspace) {
39
+ return activeRagRequestByWorkspace.get(getWorkspaceKey(workspace));
19
40
  }
20
- export function unregisterRagOperation(workspace) {
21
- const key = getWorkspaceKey(workspace);
22
- activeOperations.delete(key);
41
+ /**
42
+ * Records the `requestId` of a freshly-begun RAG operation. Called by the
43
+ * dispatcher in `rag.ts` after `registry.begin(...)` succeeds; paired with
44
+ * `clearActiveRagRequest` via the request scope's deferred cleanup so the
45
+ * map never outlives the request.
46
+ */
47
+ export function setActiveRagRequest(workspace, requestId) {
48
+ activeRagRequestByWorkspace.set(getWorkspaceKey(workspace), requestId);
23
49
  }
24
- export function cancelRagOperation(workspace) {
50
+ /**
51
+ * Clears the workspace's mapping iff it still belongs to `requestId`. The
52
+ * conditional guard handles the natural race between two ingest calls on
53
+ * the same workspace: the older context's scope unwind must not stomp the
54
+ * newer context's mapping installed by the pre-emption sequence.
55
+ */
56
+ export function clearActiveRagRequest(workspace, requestId) {
25
57
  const key = getWorkspaceKey(workspace);
26
- const entry = activeOperations.get(key);
27
- if (!entry) {
28
- return false;
58
+ if (activeRagRequestByWorkspace.get(key) === requestId) {
59
+ activeRagRequestByWorkspace.delete(key);
29
60
  }
30
- entry.abortController.abort();
31
- activeOperations.delete(key);
32
- return true;
33
61
  }
62
+ /**
63
+ * Shutdown / workspace-close sweep. Cancels every tracked RAG request via
64
+ * the registry and clears the workspace map. Idempotent — callers that
65
+ * re-invoke during a teardown (workspace-close fired twice, shutdown
66
+ * racing with `close-all`) get a no-op on the second pass.
67
+ */
34
68
  export function cancelAllRagOperations() {
35
- for (const [key, entry] of activeOperations.entries()) {
36
- entry.abortController.abort();
37
- activeOperations.delete(key);
69
+ if (activeRagRequestByWorkspace.size === 0)
70
+ return;
71
+ const registry = getRequestRegistry();
72
+ for (const [key, requestId] of activeRagRequestByWorkspace) {
73
+ registry.cancel({ requestId, reason: "rag-shutdown" });
74
+ activeRagRequestByWorkspace.delete(key);
38
75
  }
39
76
  }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Bounded-lifetime cleanup scope for an in-flight request.
3
+ *
4
+ * Callers register cleanup callbacks via `defer(...)` while a handler runs.
5
+ * On `[Symbol.asyncDispose]()` (used implicitly by `await using` or
6
+ * explicitly) every registered callback is awaited in **LIFO** order — the
7
+ * mirror of how `try/finally` blocks would unwind in a sequential write-up
8
+ * of the same handler.
9
+ *
10
+ * Guarantees:
11
+ *
12
+ * - **Idempotent.** A scope can be disposed once. Subsequent disposes are
13
+ * no-ops; subsequent `defer` calls run the cleanup eagerly so callers
14
+ * never silently leak a deferred resource if they hand a deferred
15
+ * callback to an already-disposed scope.
16
+ * - **Error aggregation.** Every deferred cleanup runs even when an
17
+ * earlier one throws. If a single cleanup throws, that error is
18
+ * rethrown verbatim. If two or more throw, an `AggregateError` is
19
+ * rethrown carrying every failure in the order it occurred. The
20
+ * handler unwinding the scope can therefore see _all_ cleanup
21
+ * failures, not just the first one.
22
+ */
23
+ export interface DisposableScope {
24
+ /**
25
+ * Register a cleanup callback. Cleanups run on dispose in LIFO order.
26
+ * Calling `defer` after the scope has been disposed runs the cleanup
27
+ * eagerly so resources never leak silently.
28
+ */
29
+ defer(cleanup: () => Promise<void> | void): void;
30
+ /** Run all registered cleanups. Idempotent. */
31
+ [Symbol.asyncDispose](): Promise<void>;
32
+ /** True after the first dispose has been initiated. */
33
+ readonly disposed: boolean;
34
+ }
35
+ export declare function createDisposableScope(): DisposableScope;
36
+ //# sourceMappingURL=disposable-scope.d.ts.map
@@ -0,0 +1,69 @@
1
+ import { AsyncDisposeUnavailableError } from "../../../utils/errors-server.js";
2
+ /**
3
+ * Module-load guard. The whole request-lifecycle primitive stack (scopes,
4
+ * the registry's `ManagedRequestContext`, `await using ctx = ...`) is
5
+ * built on `Symbol.asyncDispose`, which is an ES2024 feature. If the host
6
+ * runtime doesn't expose it (older Bare/Expo build, missing polyfill),
7
+ * the `[Symbol.asyncDispose]:` property key in this file's `dispose`
8
+ * function would coerce to the string `"undefined"` and silently produce
9
+ * objects that look async-disposable but are not — handlers would leak
10
+ * registry entries forever. Better to fail loudly at import time with a
11
+ * clear error than to debug a slow registry leak in production.
12
+ */
13
+ if (typeof Symbol.asyncDispose !== "symbol") {
14
+ throw new AsyncDisposeUnavailableError();
15
+ }
16
+ export function createDisposableScope() {
17
+ const cleanups = [];
18
+ let disposed = false;
19
+ let disposing = false;
20
+ function defer(cleanup) {
21
+ if (disposed || disposing) {
22
+ void runEagerly(cleanup);
23
+ return;
24
+ }
25
+ cleanups.push(cleanup);
26
+ }
27
+ async function runEagerly(cleanup) {
28
+ try {
29
+ await cleanup();
30
+ }
31
+ catch {
32
+ // Late-deferred cleanups have no caller waiting on them; the
33
+ // unwinding path that disposed the scope already returned its own
34
+ // errors. Swallowing here matches the user's intent of registering
35
+ // a fire-and-forget cleanup.
36
+ }
37
+ }
38
+ async function dispose() {
39
+ if (disposed || disposing)
40
+ return;
41
+ disposing = true;
42
+ const errors = [];
43
+ while (cleanups.length > 0) {
44
+ const cleanup = cleanups.pop();
45
+ if (!cleanup)
46
+ continue;
47
+ try {
48
+ await cleanup();
49
+ }
50
+ catch (err) {
51
+ errors.push(err);
52
+ }
53
+ }
54
+ disposed = true;
55
+ disposing = false;
56
+ if (errors.length === 1)
57
+ throw errors[0];
58
+ if (errors.length > 1) {
59
+ throw new AggregateError(errors, `DisposableScope: ${errors.length} cleanups failed`);
60
+ }
61
+ }
62
+ return {
63
+ defer,
64
+ [Symbol.asyncDispose]: dispose,
65
+ get disposed() {
66
+ return disposed;
67
+ },
68
+ };
69
+ }
@@ -0,0 +1,8 @@
1
+ export { createDisposableScope } from "./disposable-scope";
2
+ export type { DisposableScope } from "./disposable-scope";
3
+ export type { RequestContext, RequestKind, RequestState, } from "./request-context";
4
+ export { createRequestRegistry, getRequestRegistry, } from "./request-registry-singleton";
5
+ export type { BeginOpts, CancelByModelId, CancelByRequestId, CancelTarget, ConcurrencyPolicy, ManagedRequestContext, RequestOutcome, RequestRegistry, } from "./request-registry";
6
+ export { withRequestContext } from "./with-request-context";
7
+ export type { RequestLogContext } from "./with-request-context";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,3 @@
1
+ export { createDisposableScope } from "./disposable-scope.js";
2
+ export { createRequestRegistry, getRequestRegistry, } from "./request-registry-singleton.js";
3
+ export { withRequestContext } from "./with-request-context.js";
@@ -0,0 +1,49 @@
1
+ import type { AbortSignal } from "bare-abort-controller";
2
+ import type { DisposableScope } from "./disposable-scope";
3
+ /**
4
+ * Coarse classification of a long-running request. Used by
5
+ * `RequestRegistry.cancel({ modelId, kind })` so a broad cancel can target
6
+ * just one operation kind on a given model (e.g. cancel an in-flight
7
+ * completion without touching a finetune running on the same model).
8
+ *
9
+ * The set is intentionally open-coded — adding a new kind is a one-line
10
+ * change and the union surfaces in editor autocomplete at every call site.
11
+ */
12
+ export type RequestKind = "completion" | "embeddings" | "transcribe" | "translate" | "diffusion" | "tts" | "ocr" | "finetune" | "loadModel" | "downloadAsset" | "rag";
13
+ /**
14
+ * Lifecycle states a request transitions through. A new context starts in
15
+ * `"running"`. `cancel(...)` flips it to `"cancelling"` and aborts the
16
+ * signal; `end({ outcome: "completed" | "failed" | "cancelled" })` flips
17
+ * it to a terminal state and removes it from the registry.
18
+ *
19
+ * Kept as a string union (not a state machine) on purpose — handlers read
20
+ * `state` defensively at most a couple of points and a flat enum is easier
21
+ * to log/assert than a transition table.
22
+ */
23
+ export type RequestState = "running" | "cancelling" | "completed" | "failed" | "cancelled";
24
+ /**
25
+ * Per-request lifecycle handle. Created by `RequestRegistry.begin(...)`
26
+ * and consumed by long-running handlers as the single owner of:
27
+ *
28
+ * - `requestId` — stable identity; visible to the client so it can
29
+ * target this exact request with `cancel({ requestId })`.
30
+ * - `signal` — `AbortSignal` that fires when the request is cancelled.
31
+ * Composes with addon-level cancellation through a single
32
+ * `signal.addEventListener("abort", ...)` hook installed by the
33
+ * handler.
34
+ * - `scope` — `DisposableScope` for `await using` / `Symbol.asyncDispose`
35
+ * cleanup. The scope unwinds whether the handler returns, throws, or
36
+ * is cancelled — there is no manual cleanup path for handlers to
37
+ * forget on the cancel branch.
38
+ * - `state` — current lifecycle state. Treat as read-mostly; the
39
+ * registry mutates it.
40
+ */
41
+ export interface RequestContext {
42
+ readonly requestId: string;
43
+ readonly kind: RequestKind;
44
+ readonly modelId: string | undefined;
45
+ readonly signal: AbortSignal;
46
+ readonly scope: DisposableScope;
47
+ state: RequestState;
48
+ }
49
+ //# sourceMappingURL=request-context.d.ts.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Server-side fallback for `requestId`. The new wire contract is that
3
+ * the client generates the id (UUIDv4) at call time so it's surfaced
4
+ * synchronously on the `CompletionRun` for use with `cancel({ requestId })`.
5
+ * To keep older clients working, the request schema marks `requestId`
6
+ * optional and the server fills it in here when it's missing.
7
+ *
8
+ * `bare-crypto.randomUUID()` mirrors Node's `crypto.randomUUID()` and is
9
+ * Bare-runtime safe. Returns a v4 UUID.
10
+ */
11
+ export declare function generateServerRequestId(): string;
12
+ //# sourceMappingURL=request-id.d.ts.map
@@ -0,0 +1,14 @@
1
+ import { randomUUID } from "bare-crypto";
2
+ /**
3
+ * Server-side fallback for `requestId`. The new wire contract is that
4
+ * the client generates the id (UUIDv4) at call time so it's surfaced
5
+ * synchronously on the `CompletionRun` for use with `cancel({ requestId })`.
6
+ * To keep older clients working, the request schema marks `requestId`
7
+ * optional and the server fills it in here when it's missing.
8
+ *
9
+ * `bare-crypto.randomUUID()` mirrors Node's `crypto.randomUUID()` and is
10
+ * Bare-runtime safe. Returns a v4 UUID.
11
+ */
12
+ export function generateServerRequestId() {
13
+ return randomUUID();
14
+ }
@@ -0,0 +1,4 @@
1
+ import { createRequestRegistry as createRegistry, type RequestRegistry } from "./request-registry";
2
+ export declare function getRequestRegistry(): RequestRegistry;
3
+ export { createRegistry as createRequestRegistry };
4
+ //# sourceMappingURL=request-registry-singleton.d.ts.map
@@ -0,0 +1,27 @@
1
+ import { createRequestRegistry as createRegistry, } from "./request-registry.js";
2
+ /**
3
+ * Worker-process singleton. Every long-running request in this Bare
4
+ * worker registers under this registry, so a `cancel({ requestId })` RPC
5
+ * can find its target without the caller needing to know which plugin /
6
+ * handler owns the request.
7
+ *
8
+ * Exposed alongside `createRequestRegistry()` rather than replacing it so
9
+ * unit tests can spin up isolated registries without contaminating the
10
+ * shared instance. On first use the singleton registers the SDK's
11
+ * baseline concurrency policies.
12
+ */
13
+ let registry = null;
14
+ function installDefaultPolicies(r) {
15
+ // The llama.cpp addon owns one KV-cache + one decode loop per model,
16
+ // so two concurrent `completionStream` requests on the same model
17
+ // would interleave their token streams on the same logical session.
18
+ r.policy({ kind: "completion", oneAtATimePerModel: true });
19
+ }
20
+ export function getRequestRegistry() {
21
+ if (!registry) {
22
+ registry = createRegistry();
23
+ installDefaultPolicies(registry);
24
+ }
25
+ return registry;
26
+ }
27
+ export { createRegistry as createRequestRegistry };