@qvac/sdk 0.15.0 → 0.16.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 (102) hide show
  1. package/NOTICE +31 -45
  2. package/dist/client/api/ocr.d.ts +9 -0
  3. package/dist/client/api/ocr.js +9 -0
  4. package/dist/client/api/translate.js +6 -17
  5. package/dist/client/api/video.d.ts +7 -4
  6. package/dist/client/api/video.js +7 -4
  7. package/dist/client/api/vla.d.ts +14 -10
  8. package/dist/client/api/vla.js +14 -10
  9. package/dist/client/rpc/rpc-error.js +7 -1
  10. package/dist/examples/diffusion-ideogram.d.ts +2 -0
  11. package/dist/examples/diffusion-ideogram.js +108 -0
  12. package/dist/examples/diffusion-img2vid-ltx.d.ts +2 -0
  13. package/dist/examples/diffusion-img2vid-ltx.js +98 -0
  14. package/dist/examples/diffusion-txt2vid-ltx.d.ts +2 -0
  15. package/dist/examples/diffusion-txt2vid-ltx.js +92 -0
  16. package/dist/examples/logging-streaming.js +5 -1
  17. package/dist/examples/transcription/parakeet-tdt-filesystem-chunked.d.ts +2 -0
  18. package/dist/examples/transcription/parakeet-tdt-filesystem-chunked.js +203 -0
  19. package/dist/examples/vla-groot.d.ts +2 -0
  20. package/dist/examples/vla-groot.js +118 -0
  21. package/dist/models/registry/models.d.ts +5711 -9637
  22. package/dist/models/registry/models.js +2747 -6886
  23. package/dist/models/update-models/naming.js +5 -1
  24. package/dist/schemas/batch-completion-stream.d.ts +4 -4
  25. package/dist/schemas/common.d.ts +385 -4
  26. package/dist/schemas/common.js +3 -1
  27. package/dist/schemas/completion-stream.d.ts +186 -2
  28. package/dist/schemas/completion-stream.js +67 -0
  29. package/dist/schemas/constants-registry.d.ts +67 -0
  30. package/dist/schemas/constants-registry.js +51 -0
  31. package/dist/schemas/delete-cache.js +7 -3
  32. package/dist/schemas/engine-addon-map.d.ts +1 -0
  33. package/dist/schemas/engine-addon-map.js +1 -1
  34. package/dist/schemas/finetune.js +6 -3
  35. package/dist/schemas/get-loaded-model-info.d.ts +16 -0
  36. package/dist/schemas/get-loaded-model-info.js +14 -6
  37. package/dist/schemas/llamacpp-config.d.ts +24 -4
  38. package/dist/schemas/llamacpp-config.js +1 -6
  39. package/dist/schemas/load-model.d.ts +1380 -60
  40. package/dist/schemas/load-model.js +6 -3
  41. package/dist/schemas/plugin.d.ts +4 -4
  42. package/dist/schemas/plugin.js +4 -4
  43. package/dist/schemas/reload-config.js +3 -1
  44. package/dist/schemas/sdcpp-config.d.ts +239 -0
  45. package/dist/schemas/sdcpp-config.js +116 -10
  46. package/dist/schemas/sdk-config.d.ts +790 -40
  47. package/dist/schemas/sdk-errors-server.js +3 -1
  48. package/dist/schemas/text-to-speech.d.ts +14 -0
  49. package/dist/schemas/text-to-speech.js +10 -4
  50. package/dist/schemas/tools.d.ts +1 -1
  51. package/dist/schemas/tools.js +2 -1
  52. package/dist/schemas/translate.js +12 -6
  53. package/dist/schemas/vla.d.ts +10 -0
  54. package/dist/schemas/vla.js +31 -11
  55. package/dist/scripts/contract/build-contract.d.ts +38 -0
  56. package/dist/scripts/contract/build-contract.js +620 -0
  57. package/dist/scripts/contract/build-error-codes.d.ts +17 -0
  58. package/dist/scripts/contract/build-error-codes.js +17 -0
  59. package/dist/scripts/contract/build-model-type-maps.d.ts +22 -0
  60. package/dist/scripts/contract/build-model-type-maps.js +16 -0
  61. package/dist/scripts/contract/build-models-registry.d.ts +17 -0
  62. package/dist/scripts/contract/build-models-registry.js +31 -0
  63. package/dist/scripts/contract/plugin-contract.d.ts +23 -0
  64. package/dist/scripts/contract/plugin-contract.js +28 -0
  65. package/dist/scripts/export-contract.d.ts +2 -0
  66. package/dist/scripts/export-contract.js +27 -0
  67. package/dist/scripts/export-plugin-contract.d.ts +2 -0
  68. package/dist/scripts/export-plugin-contract.js +18 -0
  69. package/dist/server/bare/ops/translate.js +16 -3
  70. package/dist/server/bare/plugins/bci-whispercpp-transcription/plugin.d.ts +2 -1
  71. package/dist/server/bare/plugins/ggml-ocr/plugin.js +2 -23
  72. package/dist/server/bare/plugins/ggml-ocr/resolve-config.d.ts +6 -0
  73. package/dist/server/bare/plugins/ggml-ocr/resolve-config.js +73 -0
  74. package/dist/server/bare/plugins/ggml-vla/plugin.d.ts +5 -0
  75. package/dist/server/bare/plugins/ggml-vla/plugin.js +1 -1
  76. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +11 -22
  77. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.d.ts +8 -0
  78. package/dist/server/bare/plugins/llamacpp-completion/ops/kv-cache-state.js +8 -0
  79. package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +8 -3
  80. package/dist/server/bare/plugins/llamacpp-embedding/plugin.d.ts +6 -1
  81. package/dist/server/bare/plugins/sdcpp-generation/ops/video.d.ts +3 -1
  82. package/dist/server/bare/plugins/sdcpp-generation/ops/video.js +31 -2
  83. package/dist/server/bare/plugins/sdcpp-generation/plugin.d.ts +129 -1
  84. package/dist/server/bare/plugins/sdcpp-generation/plugin.js +94 -22
  85. package/dist/server/bare/plugins/tts-ggml/ops/text-to-speech.js +2 -16
  86. package/dist/server/bare/plugins/tts-ggml/plugin.d.ts +6 -0
  87. package/dist/server/bare/plugins/tts-ggml/plugin.js +3 -1
  88. package/dist/server/bare/types/addon-responses.d.ts +2 -0
  89. package/dist/server/bare/utils/tts-stats.d.ts +8 -4
  90. package/dist/server/bare/utils/tts-stats.js +6 -0
  91. package/dist/server/rpc/create-server.js +23 -1
  92. package/dist/server/rpc/handler-registry.js +5 -0
  93. package/dist/server/rpc/handlers/completion-orchestrate.d.ts +42 -0
  94. package/dist/server/rpc/handlers/completion-orchestrate.js +190 -0
  95. package/dist/server/rpc/handlers/get-loaded-model-info.js +8 -2
  96. package/dist/server/rpc/handlers/index.d.ts +2 -0
  97. package/dist/server/rpc/handlers/index.js +2 -0
  98. package/dist/server/rpc/method-shapes.d.ts +51 -0
  99. package/dist/server/rpc/method-shapes.js +48 -0
  100. package/dist/server/rpc/profiling/operation-metrics.js +20 -0
  101. package/dist/server/utils/cache/auto-history.js +13 -9
  102. package/package.json +16 -13
@@ -0,0 +1,190 @@
1
+ import { toolCallbackResultSchema } from '../../../schemas/completion-stream.js';
2
+ import { aggregateEvents } from '../../../utils/aggregate-events.js';
3
+ import { CompletionFailedError } from '../../../utils/errors-server.js';
4
+ import { dispatchPluginStream } from './plugin-dispatch.js';
5
+ const DEFAULT_MAX_TOOL_TURNS = 8;
6
+ // Generous ceiling on one client-side tool execution: long enough for a slow
7
+ // MCP round trip, short enough that a client that stopped reading can't pin a
8
+ // model slot forever.
9
+ const TOOL_RESULT_TIMEOUT_MS = 5 * 60 * 1000;
10
+ // A single tool result is small JSON; anything past this without a newline is a
11
+ // malformed/hostile client trying to grow the buffer without bound. Fail loudly
12
+ // instead of accumulating forever.
13
+ const MAX_TOOL_RESULT_LINE_BYTES = 16 * 1024 * 1024;
14
+ /**
15
+ * Reads newline-delimited JSON tool results off the duplex request stream
16
+ * and resolves per-callId waiters. Chunk boundaries don't align with lines,
17
+ * so a partial tail is buffered until its newline arrives.
18
+ *
19
+ * The pump is torn down by `close()` (called from a `finally` when
20
+ * orchestration ends, however it ends) so the upstream iterator is returned
21
+ * and the reader stops holding the request stream open.
22
+ */
23
+ export class ToolResultReader {
24
+ buffer = '';
25
+ results = new Map();
26
+ waiters = new Map();
27
+ failed;
28
+ closed = false;
29
+ iterator;
30
+ constructor(inputStream) {
31
+ this.iterator = inputStream[Symbol.asyncIterator]();
32
+ void this.pump();
33
+ }
34
+ async pump() {
35
+ try {
36
+ while (!this.closed) {
37
+ const next = await this.iterator.next();
38
+ if (next.done)
39
+ break;
40
+ this.buffer += next.value.toString();
41
+ let nl;
42
+ while ((nl = this.buffer.indexOf('\n')) !== -1) {
43
+ const line = this.buffer.slice(0, nl);
44
+ this.buffer = this.buffer.slice(nl + 1);
45
+ if (line.trim())
46
+ this.accept(line);
47
+ }
48
+ if (this.buffer.length > MAX_TOOL_RESULT_LINE_BYTES) {
49
+ throw new CompletionFailedError('tool result frame exceeds the maximum size');
50
+ }
51
+ }
52
+ if (!this.closed && this.buffer.trim())
53
+ this.accept(this.buffer);
54
+ }
55
+ catch (error) {
56
+ this.failWaiters(error instanceof Error ? error : new Error(String(error)));
57
+ }
58
+ }
59
+ failWaiters(error) {
60
+ this.failed = error;
61
+ // Wake every waiter; each rethrows via waitFor's failure check.
62
+ for (const [callId, resolve] of this.waiters) {
63
+ this.waiters.delete(callId);
64
+ resolve({ callId, error: error.message });
65
+ }
66
+ }
67
+ accept(line) {
68
+ const parsed = toolCallbackResultSchema.parse(JSON.parse(line));
69
+ const waiter = this.waiters.get(parsed.callId);
70
+ if (waiter) {
71
+ this.waiters.delete(parsed.callId);
72
+ waiter(parsed);
73
+ }
74
+ else {
75
+ this.results.set(parsed.callId, parsed);
76
+ }
77
+ }
78
+ async waitFor(callId, timeoutMs = TOOL_RESULT_TIMEOUT_MS) {
79
+ const buffered = this.results.get(callId);
80
+ if (buffered) {
81
+ this.results.delete(callId);
82
+ return buffered;
83
+ }
84
+ if (this.failed)
85
+ throw this.failed;
86
+ return await new Promise((resolve, reject) => {
87
+ const timer = setTimeout(() => {
88
+ this.waiters.delete(callId);
89
+ reject(new CompletionFailedError(`tool callback ${callId} timed out`));
90
+ }, timeoutMs);
91
+ this.waiters.set(callId, (result) => {
92
+ clearTimeout(timer);
93
+ resolve(result);
94
+ });
95
+ });
96
+ }
97
+ /**
98
+ * Stop the pump and release the upstream iterator. Idempotent. Pending
99
+ * waiters are failed so a caller blocked in `waitFor` can't hang after the
100
+ * stream is torn down.
101
+ */
102
+ close() {
103
+ if (this.closed)
104
+ return;
105
+ this.closed = true;
106
+ this.buffer = '';
107
+ this.results.clear();
108
+ if (!this.failed)
109
+ this.failWaiters(new CompletionFailedError('tool result stream closed'));
110
+ void this.iterator.return?.();
111
+ }
112
+ }
113
+ /**
114
+ * The orchestration core, pure over its collaborators so it unit-tests
115
+ * without the plugin registry: runs completion turns, forwards their events
116
+ * downstream, and when a turn requests tool calls, emits `toolCallback`
117
+ * frames and blocks on the client's results before starting the next turn
118
+ * with the extended history.
119
+ */
120
+ export async function* orchestrateCompletion(request, runTurn, reader) {
121
+ // Pull the loop bound out of the per-turn base; everything else (including
122
+ // `requestId`) flows into each inner completionStream turn. Threading the
123
+ // orchestrate `requestId` down is what makes `cancel({ requestId })` reach
124
+ // the turn that's currently generating — the expensive part a Stop button
125
+ // targets. Turns run strictly sequentially: turn N's request-registry entry
126
+ // is disposed (on the `for await` break below) before turn N+1 calls
127
+ // `begin(...)`, so reusing the id can't collide in `entries`. A cancel that
128
+ // lands between turns (during a tool-result wait) is caught by the
129
+ // registry's cancel-before-begin tripwire and aborts the next turn's
130
+ // `begin(...)`. Each turn's `history` and `type` are set below.
131
+ const { maxToolTurns, ...turnBase } = request;
132
+ const maxTurns = maxToolTurns ?? DEFAULT_MAX_TOOL_TURNS;
133
+ let history = [...request.history];
134
+ for (let turn = 0; turn < maxTurns; turn++) {
135
+ const turnEvents = [];
136
+ const innerRequest = {
137
+ ...turnBase,
138
+ history,
139
+ type: 'completionStream'
140
+ };
141
+ for await (const response of runTurn(innerRequest)) {
142
+ turnEvents.push(...response.events);
143
+ yield { type: 'completionOrchestrate', turn, events: response.events };
144
+ if (response.done)
145
+ break;
146
+ }
147
+ const { toolCalls, rawFullText, contentText, error, cancelled } = aggregateEvents(turnEvents);
148
+ // Terminal turn: the model answered (or failed/was cancelled) without
149
+ // requesting tools — the client folds the forwarded events itself.
150
+ if (error || cancelled || toolCalls.length === 0) {
151
+ yield { type: 'completionOrchestrate', done: true };
152
+ return;
153
+ }
154
+ // The assistant's tool-call turn goes back verbatim so the model sees
155
+ // its own call syntax; each result follows as a `tool` message.
156
+ history = [...history, { role: 'assistant', content: rawFullText ?? contentText }];
157
+ for (const call of toolCalls) {
158
+ yield {
159
+ type: 'completionOrchestrate',
160
+ turn,
161
+ toolCallback: { callId: call.id, name: call.name, arguments: call.arguments }
162
+ };
163
+ const result = await reader.waitFor(call.id);
164
+ const content = result.error !== undefined
165
+ ? JSON.stringify({ error: result.error })
166
+ : JSON.stringify(result.result ?? null);
167
+ history = [...history, { role: 'tool', content }];
168
+ }
169
+ }
170
+ // Turn cap reached without a natural end. Emit a terminal done frame with a
171
+ // stopReason so the client can tell this was truncated (the model still
172
+ // wanted a tool) rather than a natural finish; the last turn's events carry
173
+ // whatever the model produced.
174
+ yield { type: 'completionOrchestrate', done: true, stopReason: 'maxToolTurns' };
175
+ }
176
+ export async function* handleCompletionOrchestrate(request, inputStream) {
177
+ const reader = new ToolResultReader(inputStream);
178
+ const runTurn = async function* (innerRequest) {
179
+ yield* dispatchPluginStream(innerRequest.modelId, 'completionStream', innerRequest);
180
+ };
181
+ try {
182
+ yield* orchestrateCompletion(request, runTurn, reader);
183
+ }
184
+ finally {
185
+ // Tear the reader down however orchestration ends -- natural finish, turn
186
+ // cap, error, or the client abandoning the stream -- so the pump stops and
187
+ // the request stream isn't held open.
188
+ reader.close();
189
+ }
190
+ }
@@ -1,5 +1,6 @@
1
1
  import { getModelEntry } from '../../bare/registry/model-registry.js';
2
2
  import { getPlugin } from '../../plugins/registry.js';
3
+ import { detectToolDialectFromName } from '../../utils/tools/index.js';
3
4
  import { ModelNotFoundError } from '../../../utils/errors-server.js';
4
5
  import { getServerLogger } from '../../../logging/index.js';
5
6
  const logger = getServerLogger();
@@ -24,16 +25,21 @@ export function handleGetLoadedModelInfo(request) {
24
25
  if (!plugin) {
25
26
  logger.warn(`getLoadedModelInfo: no plugin registered for modelType "${entry.local.modelType}" on loaded model "${modelId}"`);
26
27
  }
28
+ const handlers = plugin ? Object.keys(plugin.handlers) : [];
27
29
  const info = {
28
30
  modelId: entry.id,
29
31
  isDelegated: false,
30
32
  modelType: entry.local.modelType,
31
- handlers: plugin ? Object.keys(plugin.handlers) : [],
33
+ handlers,
32
34
  loadedAt: entry.local.loadedAt,
33
35
  ...(plugin && { displayName: plugin.displayName }),
34
36
  ...(plugin && { addonPackage: plugin.addonPackage }),
35
37
  ...(entry.local.name && { name: entry.local.name }),
36
- ...(entry.local.path && { path: entry.local.path })
38
+ ...(entry.local.path && { path: entry.local.path }),
39
+ // Same detection the completion normalizer uses, so callers see the dialect it parses.
40
+ ...(handlers.includes('completionStream') && {
41
+ toolDialect: detectToolDialectFromName(entry.local.name, entry.local.path)
42
+ })
37
43
  };
38
44
  return { type: 'getLoadedModelInfo', info };
39
45
  }
@@ -1,4 +1,5 @@
1
1
  import { handleBatchCompletionStream } from './batch-completion-stream';
2
+ import { handleCompletionOrchestrate } from './completion-orchestrate';
2
3
  import { handleCompletionStream } from './completion-stream';
3
4
  import { handleDownloadAsset } from './download-asset';
4
5
  import { handleLoadModel } from './load-model/index';
@@ -34,6 +35,7 @@ export declare const handlers: {
34
35
  heartbeat: typeof handleHeartbeat;
35
36
  batchCompletionStream: typeof handleBatchCompletionStream;
36
37
  completionStream: typeof handleCompletionStream;
38
+ completionOrchestrate: typeof handleCompletionOrchestrate;
37
39
  downloadAsset: typeof handleDownloadAsset;
38
40
  deleteCache: typeof handleDeleteCache;
39
41
  loadModel: typeof handleLoadModel;
@@ -1,4 +1,5 @@
1
1
  import { handleBatchCompletionStream } from './batch-completion-stream.js';
2
+ import { handleCompletionOrchestrate } from './completion-orchestrate.js';
2
3
  import { handleCompletionStream } from './completion-stream.js';
3
4
  import { handleDownloadAsset } from './download-asset.js';
4
5
  import { handleLoadModel } from './load-model/index.js';
@@ -34,6 +35,7 @@ export const handlers = {
34
35
  heartbeat: handleHeartbeat,
35
36
  batchCompletionStream: handleBatchCompletionStream,
36
37
  completionStream: handleCompletionStream,
38
+ completionOrchestrate: handleCompletionOrchestrate,
37
39
  downloadAsset: handleDownloadAsset,
38
40
  deleteCache: handleDeleteCache,
39
41
  loadModel: handleLoadModel,
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Call shape of every RPC method, keyed by the request `type` literal.
3
+ *
4
+ * This module must stay free of handler imports: the contract export
5
+ * (`scripts/export-contract.ts`) loads it under Node, where the handler
6
+ * graph's native bare-* modules cannot be required. `handler-registry.ts`
7
+ * is type-bound to this map, so a registry entry whose key or `type`
8
+ * diverges from it fails to compile.
9
+ */
10
+ export declare const methodShapes: {
11
+ readonly batchCompletionStream: "stream";
12
+ readonly bciTranscribe: "stream";
13
+ readonly bciTranscribeStream: "duplex";
14
+ readonly cancel: "reply";
15
+ readonly classify: "stream";
16
+ readonly completionOrchestrate: "duplex";
17
+ readonly completionStream: "stream";
18
+ readonly deleteCache: "reply";
19
+ readonly diffusionStream: "stream";
20
+ readonly downloadAsset: "reply";
21
+ readonly embed: "reply";
22
+ readonly finetune: "reply";
23
+ readonly getLoadedModelInfo: "reply";
24
+ readonly getModelInfo: "reply";
25
+ readonly heartbeat: "reply";
26
+ readonly loadModel: "reply";
27
+ readonly loggingStream: "stream";
28
+ readonly modelRegistryGetModel: "reply";
29
+ readonly modelRegistryList: "reply";
30
+ readonly modelRegistrySearch: "reply";
31
+ readonly ocrStream: "stream";
32
+ readonly pluginInvoke: "reply";
33
+ readonly pluginInvokeStream: "stream";
34
+ readonly provide: "reply";
35
+ readonly rag: "reply";
36
+ readonly resume: "reply";
37
+ readonly state: "reply";
38
+ readonly stopProvide: "reply";
39
+ readonly suspend: "reply";
40
+ readonly textToSpeech: "stream";
41
+ readonly textToSpeechStream: "duplex";
42
+ readonly transcribe: "stream";
43
+ readonly transcribeStream: "duplex";
44
+ readonly translate: "stream";
45
+ readonly unloadModel: "reply";
46
+ readonly upscaleStream: "stream";
47
+ readonly videoStream: "stream";
48
+ };
49
+ export type MethodName = keyof typeof methodShapes;
50
+ export type MethodCallShape = (typeof methodShapes)[MethodName];
51
+ //# sourceMappingURL=method-shapes.d.ts.map
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Call shape of every RPC method, keyed by the request `type` literal.
3
+ *
4
+ * This module must stay free of handler imports: the contract export
5
+ * (`scripts/export-contract.ts`) loads it under Node, where the handler
6
+ * graph's native bare-* modules cannot be required. `handler-registry.ts`
7
+ * is type-bound to this map, so a registry entry whose key or `type`
8
+ * diverges from it fails to compile.
9
+ */
10
+ export const methodShapes = {
11
+ batchCompletionStream: 'stream',
12
+ bciTranscribe: 'stream',
13
+ bciTranscribeStream: 'duplex',
14
+ cancel: 'reply',
15
+ classify: 'stream',
16
+ completionOrchestrate: 'duplex',
17
+ completionStream: 'stream',
18
+ deleteCache: 'reply',
19
+ diffusionStream: 'stream',
20
+ downloadAsset: 'reply',
21
+ embed: 'reply',
22
+ finetune: 'reply',
23
+ getLoadedModelInfo: 'reply',
24
+ getModelInfo: 'reply',
25
+ heartbeat: 'reply',
26
+ loadModel: 'reply',
27
+ loggingStream: 'stream',
28
+ modelRegistryGetModel: 'reply',
29
+ modelRegistryList: 'reply',
30
+ modelRegistrySearch: 'reply',
31
+ ocrStream: 'stream',
32
+ pluginInvoke: 'reply',
33
+ pluginInvokeStream: 'stream',
34
+ provide: 'reply',
35
+ rag: 'reply',
36
+ resume: 'reply',
37
+ state: 'reply',
38
+ stopProvide: 'reply',
39
+ suspend: 'reply',
40
+ textToSpeech: 'stream',
41
+ textToSpeechStream: 'duplex',
42
+ transcribe: 'stream',
43
+ transcribeStream: 'duplex',
44
+ translate: 'stream',
45
+ unloadModel: 'reply',
46
+ upscaleStream: 'stream',
47
+ videoStream: 'stream'
48
+ };
@@ -233,6 +233,16 @@ registerOperationMetrics({
233
233
  const gauges = {};
234
234
  if (res.stats.generationMs !== undefined)
235
235
  gauges['generationMs'] = res.stats.generationMs;
236
+ if (res.stats.conditionerMs !== undefined)
237
+ gauges['conditionerMs'] = res.stats.conditionerMs;
238
+ if (res.stats.denoiseMs !== undefined)
239
+ gauges['denoiseMs'] = res.stats.denoiseMs;
240
+ if (res.stats.vaeMs !== undefined)
241
+ gauges['vaeMs'] = res.stats.vaeMs;
242
+ if (res.stats.postProcessMs !== undefined)
243
+ gauges['postProcessMs'] = res.stats.postProcessMs;
244
+ if (res.stats.stepsPerSecond !== undefined)
245
+ gauges['stepsPerSecond'] = res.stats.stepsPerSecond;
236
246
  if (res.stats.totalSteps !== undefined)
237
247
  gauges['totalSteps'] = res.stats.totalSteps;
238
248
  if (res.stats.totalImages !== undefined)
@@ -252,6 +262,16 @@ registerOperationMetrics({
252
262
  const gauges = {};
253
263
  if (res.stats.generationMs !== undefined)
254
264
  gauges['generationMs'] = res.stats.generationMs;
265
+ if (res.stats.conditionerMs !== undefined)
266
+ gauges['conditionerMs'] = res.stats.conditionerMs;
267
+ if (res.stats.denoiseMs !== undefined)
268
+ gauges['denoiseMs'] = res.stats.denoiseMs;
269
+ if (res.stats.vaeMs !== undefined)
270
+ gauges['vaeMs'] = res.stats.vaeMs;
271
+ if (res.stats.postProcessMs !== undefined)
272
+ gauges['postProcessMs'] = res.stats.postProcessMs;
273
+ if (res.stats.stepsPerSecond !== undefined)
274
+ gauges['stepsPerSecond'] = res.stats.stepsPerSecond;
255
275
  if (res.stats.totalSteps !== undefined)
256
276
  gauges['totalSteps'] = res.stats.totalSteps;
257
277
  if (res.stats.totalVideos !== undefined)
@@ -1,22 +1,26 @@
1
1
  import { normalizeAssistantCacheContent } from '../../../utils/cache-normalize.js';
2
- function normalizeAssistantMessage(message) {
3
- if (message.role !== 'assistant') {
4
- return message;
2
+ function normalizeCacheMessage(message) {
3
+ const { attachments, ...normalized } = message;
4
+ if (message.role === 'assistant') {
5
+ normalized.content = normalizeAssistantCacheContent(message.content);
5
6
  }
6
- return { ...message, content: normalizeAssistantCacheContent(message.content) };
7
+ return {
8
+ ...normalized,
9
+ ...(attachments && attachments.length > 0 ? { attachments } : {})
10
+ };
7
11
  }
8
12
  export function getAutoCacheLookupHistory(currentHistory) {
9
13
  if (currentHistory.length <= 1) {
10
14
  return [];
11
15
  }
12
- return currentHistory.slice(0, -1).map(normalizeAssistantMessage);
16
+ return currentHistory.slice(0, -1).map(normalizeCacheMessage);
13
17
  }
14
18
  export function buildAutoCacheSaveHistory(currentHistory, assistantResponse) {
15
19
  return [
16
- ...currentHistory,
17
- {
20
+ ...currentHistory.map(normalizeCacheMessage),
21
+ normalizeCacheMessage({
18
22
  role: 'assistant',
19
- content: normalizeAssistantCacheContent(assistantResponse)
20
- }
23
+ content: assistantResponse
24
+ })
21
25
  ];
22
26
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qvac/sdk",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -194,29 +194,31 @@
194
194
  "bare:ensureprebuilds": "bun run bare:ensureprebuilds:llamacpp && bun run bare:ensureprebuilds:whispercpp && bun run bare:ensureprebuilds:embeddings",
195
195
  "prepare:husky": "bun run husky",
196
196
  "bare:example": "bare ./scripts/bare-bootstrap.js",
197
+ "contract:export": "tsx ./scripts/export-contract.ts",
198
+ "contract:check": "tsx ./scripts/export-contract.ts --check",
197
199
  "check-models": "tsx ./models/update-models/index.ts --check",
198
200
  "check-models:hook": "tsx ./models/update-models/index.ts --check --non-blocking",
199
- "update-models": "tsx ./models/update-models/index.ts",
201
+ "update-models": "tsx ./models/update-models/index.ts && bun run contract:export",
200
202
  "changelog:generate": "node ../../scripts/sdk/generate-changelog-sdk-pod.cjs --package=sdk && prettier --write changelog"
201
203
  },
202
204
  "dependencies": {
203
- "@qvac/bci-whispercpp": "^0.4.1",
204
- "@qvac/classification-ggml": "^0.10.2",
205
+ "@qvac/bci-whispercpp": "^0.5.0",
206
+ "@qvac/classification-ggml": "^0.13.0",
205
207
  "@qvac/decoder-audio": "^0.5.0",
206
- "@qvac/diffusion-cpp": "^0.13.3",
207
- "@qvac/embed-llamacpp": "^0.26.2",
208
+ "@qvac/diffusion-cpp": "^0.15.0",
209
+ "@qvac/embed-llamacpp": "^0.28.0",
208
210
  "@qvac/error": "^0.1.1",
209
211
  "@qvac/langdetect-text": "^0.1.2",
210
- "@qvac/llm-llamacpp": "^0.36.3",
212
+ "@qvac/llm-llamacpp": "^0.38.0",
211
213
  "@qvac/logging": "^0.1.0",
212
- "@qvac/ocr-ggml": "^0.10.2",
214
+ "@qvac/ocr-ggml": "^0.12.1",
213
215
  "@qvac/rag": "^0.6.4",
214
216
  "@qvac/registry-client": "^0.6.1",
215
- "@qvac/transcription-parakeet": "^0.9.1",
216
- "@qvac/transcription-whispercpp": "^0.11.1",
217
- "@qvac/translation-nmtcpp": "^7.2.2",
218
- "@qvac/tts-ggml": "^0.4.2",
219
- "@qvac/vla-ggml": "^0.11.2",
217
+ "@qvac/transcription-parakeet": "^0.10.0",
218
+ "@qvac/transcription-whispercpp": "^0.12.0",
219
+ "@qvac/translation-nmtcpp": "^8.1.0",
220
+ "@qvac/tts-ggml": "^0.5.0",
221
+ "@qvac/vla-ggml": "^0.14.0",
220
222
  "bare-abort-controller": "^1.0.0",
221
223
  "bare-crypto": "^1.15.0",
222
224
  "bare-env": "^3.0.0",
@@ -251,6 +253,7 @@
251
253
  "@types/node": "^24.2.1",
252
254
  "@types/semver": "^7.7.1",
253
255
  "@types/tar-stream": "^3.1.4",
256
+ "ajv": "8.20.0",
254
257
  "bare-process": "^4.4.1",
255
258
  "bare-readline": "^1.2.0",
256
259
  "bare-stdio": "^1.0.2",