@qvac/sdk 0.8.2 → 0.9.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 (219) hide show
  1. package/NOTICE +267 -63
  2. package/README.md +2 -0
  3. package/dist/client/api/diffusion.d.ts +32 -0
  4. package/dist/client/api/diffusion.js +103 -0
  5. package/dist/client/api/embed.d.ts +9 -3
  6. package/dist/client/api/embed.js +4 -1
  7. package/dist/client/api/finetune.d.ts +69 -0
  8. package/dist/client/api/finetune.js +139 -0
  9. package/dist/client/api/get-model-info.d.ts +1 -1
  10. package/dist/client/api/index.d.ts +4 -0
  11. package/dist/client/api/index.js +4 -0
  12. package/dist/client/api/rag.d.ts +1 -1
  13. package/dist/client/api/rag.js +1 -1
  14. package/dist/client/api/resume.d.ts +14 -0
  15. package/dist/client/api/resume.js +20 -0
  16. package/dist/client/api/suspend.d.ts +13 -0
  17. package/dist/client/api/suspend.js +19 -0
  18. package/dist/client/api/transcribe.d.ts +25 -17
  19. package/dist/client/api/transcribe.js +115 -35
  20. package/dist/client/rpc/bare-client.d.ts +5 -1
  21. package/dist/client/rpc/bare-client.js +70 -57
  22. package/dist/client/rpc/expo-rpc-client.d.ts +4 -0
  23. package/dist/client/rpc/expo-rpc-client.js +8 -0
  24. package/dist/client/rpc/node-rpc-client.d.ts +4 -0
  25. package/dist/client/rpc/node-rpc-client.js +8 -0
  26. package/dist/client/rpc/rpc-client.d.ts +13 -0
  27. package/dist/client/rpc/rpc-client.js +131 -1
  28. package/dist/examples/delegated-inference/composite.d.ts +2 -0
  29. package/dist/examples/delegated-inference/composite.js +99 -0
  30. package/dist/examples/diffusion-flux2-klein.d.ts +2 -0
  31. package/dist/examples/diffusion-flux2-klein.js +46 -0
  32. package/dist/examples/diffusion-simple.d.ts +2 -0
  33. package/dist/examples/diffusion-simple.js +17 -0
  34. package/dist/examples/diffusion-txt2img.d.ts +2 -0
  35. package/dist/examples/diffusion-txt2img.js +40 -0
  36. package/dist/examples/embed-p2p.js +2 -2
  37. package/dist/examples/finetune/llamacpp-finetune.d.ts +2 -0
  38. package/dist/examples/finetune/llamacpp-finetune.js +78 -0
  39. package/dist/examples/logging-streaming.js +1 -1
  40. package/dist/examples/mcp-websearch.js +2 -0
  41. package/dist/examples/ocr-fasttext.js +11 -0
  42. package/dist/examples/profiling/per-call.js +3 -3
  43. package/dist/examples/rag/rag-chromadb.js +2 -2
  44. package/dist/examples/rag/rag-hyperdb/pipeline.js +1 -1
  45. package/dist/examples/rag/rag-lancedb.js +2 -2
  46. package/dist/examples/rag/rag-sqlite.js +2 -2
  47. package/dist/examples/suspend-resume.d.ts +2 -0
  48. package/dist/examples/suspend-resume.js +52 -0
  49. package/dist/examples/transcription/parakeet-ctc-filesystem.js +3 -5
  50. package/dist/examples/transcription/parakeet-microphone-record.js +42 -33
  51. package/dist/examples/transcription/parakeet-sortformer.js +13 -3
  52. package/dist/examples/transcription/parakeet-tdt-filesystem.js +5 -7
  53. package/dist/examples/transcription/whispercpp-filesystem-streaming.d.ts +2 -0
  54. package/dist/examples/transcription/whispercpp-filesystem-streaming.js +99 -0
  55. package/dist/examples/transcription/whispercpp-microphone-record.js +78 -299
  56. package/dist/examples/transcription/whispercpp-prompt.js +11 -0
  57. package/dist/examples/translation/translation-llm.js +2 -2
  58. package/dist/examples/tts/supertonic-multilingual.d.ts +2 -0
  59. package/dist/examples/tts/supertonic-multilingual.js +56 -0
  60. package/dist/examples/tts/supertonic.js +12 -7
  61. package/dist/index.d.ts +3 -2
  62. package/dist/index.js +3 -2
  63. package/dist/logging/utils.js +1 -1
  64. package/dist/models/registry/models.d.ts +15176 -4264
  65. package/dist/models/registry/models.js +18657 -7404
  66. package/dist/models/update-models/codegen.js +2 -2
  67. package/dist/models/update-models/naming.js +26 -0
  68. package/dist/pear/pre.js +2 -0
  69. package/dist/polyfills/bare-globals.d.ts +2 -0
  70. package/dist/polyfills/bare-globals.js +4 -0
  71. package/dist/polyfills/bare-globals.noop.d.ts +2 -0
  72. package/dist/polyfills/bare-globals.noop.js +1 -0
  73. package/dist/profiling/exporters.js +16 -11
  74. package/dist/profiling/model-execution.d.ts +16 -0
  75. package/dist/profiling/model-execution.js +33 -0
  76. package/dist/schemas/common.d.ts +967 -198
  77. package/dist/schemas/common.js +16 -1
  78. package/dist/schemas/completion-stream.d.ts +14 -6
  79. package/dist/schemas/completion-stream.js +4 -3
  80. package/dist/schemas/download-asset.d.ts +7 -3
  81. package/dist/schemas/embed.d.ts +19 -0
  82. package/dist/schemas/embed.js +7 -0
  83. package/dist/schemas/engine-addon-map.js +4 -1
  84. package/dist/schemas/finetune.d.ts +620 -0
  85. package/dist/schemas/finetune.js +161 -0
  86. package/dist/schemas/get-model-info.d.ts +2 -0
  87. package/dist/schemas/get-model-info.js +1 -0
  88. package/dist/schemas/index.d.ts +5 -1
  89. package/dist/schemas/index.js +5 -1
  90. package/dist/schemas/llamacpp-config.d.ts +26 -6
  91. package/dist/schemas/llamacpp-config.js +12 -0
  92. package/dist/schemas/load-model.d.ts +4005 -1400
  93. package/dist/schemas/load-model.js +34 -1
  94. package/dist/schemas/model-src-utils.d.ts +10 -2
  95. package/dist/schemas/model-types.d.ts +19 -1
  96. package/dist/schemas/model-types.js +11 -0
  97. package/dist/schemas/ocr.d.ts +2 -0
  98. package/dist/schemas/plugin.d.ts +24 -3
  99. package/dist/schemas/plugin.js +14 -0
  100. package/dist/schemas/profiling.d.ts +4 -0
  101. package/dist/schemas/profiling.js +4 -0
  102. package/dist/schemas/registry.d.ts +18 -0
  103. package/dist/schemas/registry.js +2 -0
  104. package/dist/schemas/reload-config.d.ts +9 -1
  105. package/dist/schemas/resume.d.ts +10 -0
  106. package/dist/schemas/resume.js +7 -0
  107. package/dist/schemas/sdcpp-config.d.ts +327 -0
  108. package/dist/schemas/sdcpp-config.js +102 -0
  109. package/dist/schemas/sdk-config.d.ts +1225 -235
  110. package/dist/schemas/sdk-config.js +4 -0
  111. package/dist/schemas/sdk-errors-server.d.ts +2 -0
  112. package/dist/schemas/sdk-errors-server.js +12 -0
  113. package/dist/schemas/suspend.d.ts +10 -0
  114. package/dist/schemas/suspend.js +7 -0
  115. package/dist/schemas/text-to-speech.d.ts +187 -10
  116. package/dist/schemas/text-to-speech.js +12 -4
  117. package/dist/schemas/transcription-config.d.ts +16 -56
  118. package/dist/schemas/transcription-config.js +0 -2
  119. package/dist/schemas/transcription.d.ts +66 -6
  120. package/dist/schemas/transcription.js +29 -7
  121. package/dist/schemas/translate.d.ts +14 -4
  122. package/dist/schemas/translate.js +10 -2
  123. package/dist/schemas/translation-config.d.ts +30 -10
  124. package/dist/server/bare/delegate-rpc-client.js +3 -3
  125. package/dist/server/bare/hyperswarm.js +15 -3
  126. package/dist/server/bare/ops/embed.d.ts +8 -4
  127. package/dist/server/bare/ops/embed.js +15 -4
  128. package/dist/server/bare/ops/transcribe.d.ts +6 -2
  129. package/dist/server/bare/ops/transcribe.js +53 -1
  130. package/dist/server/bare/ops/translate.d.ts +4 -1
  131. package/dist/server/bare/ops/translate.js +28 -65
  132. package/dist/server/bare/ops/unload-model.js +2 -0
  133. package/dist/server/bare/plugins/index.d.ts +1 -0
  134. package/dist/server/bare/plugins/index.js +1 -0
  135. package/dist/server/bare/plugins/llamacpp-completion/ops/cache-logger.d.ts +1 -0
  136. package/dist/server/bare/plugins/llamacpp-completion/ops/cache-logger.js +3 -0
  137. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.d.ts +3 -1
  138. package/dist/server/bare/plugins/llamacpp-completion/ops/completion-stream.js +57 -11
  139. package/dist/server/bare/plugins/llamacpp-completion/ops/finetune.d.ts +11 -0
  140. package/dist/server/bare/plugins/llamacpp-completion/ops/finetune.js +112 -0
  141. package/dist/server/bare/plugins/llamacpp-completion/plugin.d.ts +175 -5
  142. package/dist/server/bare/plugins/llamacpp-completion/plugin.js +45 -35
  143. package/dist/server/bare/plugins/llamacpp-embedding/plugin.d.ts +11 -1
  144. package/dist/server/bare/plugins/llamacpp-embedding/plugin.js +9 -4
  145. package/dist/server/bare/plugins/nmtcpp-translation/plugin.d.ts +17 -2
  146. package/dist/server/bare/plugins/nmtcpp-translation/plugin.js +16 -15
  147. package/dist/server/bare/plugins/onnx-ocr/ops/ocr-stream.d.ts +5 -7
  148. package/dist/server/bare/plugins/onnx-ocr/ops/ocr-stream.js +11 -3
  149. package/dist/server/bare/plugins/onnx-ocr/plugin.d.ts +2 -0
  150. package/dist/server/bare/plugins/onnx-ocr/plugin.js +24 -19
  151. package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech.d.ts +7 -2
  152. package/dist/server/bare/plugins/onnx-tts/ops/text-to-speech.js +22 -97
  153. package/dist/server/bare/plugins/onnx-tts/plugin.d.ts +98 -9
  154. package/dist/server/bare/plugins/onnx-tts/plugin.js +85 -46
  155. package/dist/server/bare/plugins/parakeet-transcription/plugin.d.ts +30 -60
  156. package/dist/server/bare/plugins/parakeet-transcription/plugin.js +49 -37
  157. package/dist/server/bare/plugins/sdcpp-generation/ops/diffusion.d.ts +3 -0
  158. package/dist/server/bare/plugins/sdcpp-generation/ops/diffusion.js +51 -0
  159. package/dist/server/bare/plugins/sdcpp-generation/plugin.d.ts +278 -0
  160. package/dist/server/bare/plugins/sdcpp-generation/plugin.js +70 -0
  161. package/dist/server/bare/plugins/whispercpp-transcription/plugin.d.ts +38 -2
  162. package/dist/server/bare/plugins/whispercpp-transcription/plugin.js +43 -22
  163. package/dist/server/bare/rag-hyperdb/handlers/ingest.js +2 -1
  164. package/dist/server/bare/rag-hyperdb/handlers/search.js +2 -1
  165. package/dist/server/bare/rag-hyperdb/rag-workspace-manager.js +7 -0
  166. package/dist/server/bare/registry/model-config-utils.js +3 -0
  167. package/dist/server/bare/registry/model-registry.d.ts +2 -2
  168. package/dist/server/bare/registry/model-registry.js +1 -1
  169. package/dist/server/bare/registry/registry-client.js +21 -0
  170. package/dist/server/bare/runtime-lifecycle.d.ts +28 -0
  171. package/dist/server/bare/runtime-lifecycle.js +132 -0
  172. package/dist/server/bare/types/addon-responses.d.ts +62 -0
  173. package/dist/server/bare/types/addon-responses.js +1 -0
  174. package/dist/server/env.js +3 -1
  175. package/dist/server/rpc/delegate-transport.js +1 -1
  176. package/dist/server/rpc/handle-request.js +50 -4
  177. package/dist/server/rpc/handler-registry.js +20 -1
  178. package/dist/server/rpc/handler-utils.d.ts +5 -3
  179. package/dist/server/rpc/handler-utils.js +52 -50
  180. package/dist/server/rpc/handlers/delete-cache.js +3 -0
  181. package/dist/server/rpc/handlers/diffusion-stream.d.ts +3 -0
  182. package/dist/server/rpc/handlers/diffusion-stream.js +4 -0
  183. package/dist/server/rpc/handlers/finetune.d.ts +3 -0
  184. package/dist/server/rpc/handlers/finetune.js +16 -0
  185. package/dist/server/rpc/handlers/index.d.ts +10 -0
  186. package/dist/server/rpc/handlers/index.js +10 -0
  187. package/dist/server/rpc/handlers/load-model/hyperdrive.js +24 -9
  188. package/dist/server/rpc/handlers/load-model/registry.d.ts +11 -0
  189. package/dist/server/rpc/handlers/load-model/registry.js +31 -4
  190. package/dist/server/rpc/handlers/plugin-dispatch.d.ts +1 -13
  191. package/dist/server/rpc/handlers/plugin-dispatch.js +21 -21
  192. package/dist/server/rpc/handlers/resume.d.ts +3 -0
  193. package/dist/server/rpc/handlers/resume.js +11 -0
  194. package/dist/server/rpc/handlers/suspend.d.ts +3 -0
  195. package/dist/server/rpc/handlers/suspend.js +11 -0
  196. package/dist/server/rpc/handlers/transcribe-stream.d.ts +1 -1
  197. package/dist/server/rpc/handlers/transcribe-stream.js +2 -2
  198. package/dist/server/rpc/handlers/transcribe.d.ts +3 -0
  199. package/dist/server/rpc/handlers/transcribe.js +4 -0
  200. package/dist/server/rpc/profiling/operation-metrics.js +107 -16
  201. package/dist/server/rpc/profiling/operation-wrappers.d.ts +1 -1
  202. package/dist/server/rpc/profiling/operation-wrappers.js +51 -19
  203. package/dist/server/rpc/progress-throttle.d.ts +8 -0
  204. package/dist/server/rpc/progress-throttle.js +47 -0
  205. package/dist/server/rpc/rpc-utils.d.ts +5 -0
  206. package/dist/server/rpc/rpc-utils.js +11 -0
  207. package/dist/server/utils/path-security.js +1 -1
  208. package/dist/server/utils/tool-integration.js +10 -0
  209. package/dist/server/utils/tool-parser.js +9 -5
  210. package/dist/server/worker-core.d.ts +2 -0
  211. package/dist/server/worker-core.js +26 -23
  212. package/dist/server/worker.js +2 -1
  213. package/dist/utils/encoding.d.ts +9 -0
  214. package/dist/utils/encoding.js +14 -0
  215. package/dist/utils/errors-server.d.ts +6 -0
  216. package/dist/utils/errors-server.js +11 -0
  217. package/package.json +81 -25
  218. package/dist/server/rpc/delegate-utils.d.ts +0 -2
  219. package/dist/server/rpc/delegate-utils.js +0 -5
@@ -1,5 +1,6 @@
1
1
  import { QVACRegistryClient } from "@qvac/registry-client";
2
2
  import { getCacheDir } from "../../utils/cache.js";
3
+ import { registerSwarm, unregisterSwarm, registerCorestore, unregisterCorestore, } from "../runtime-lifecycle.js";
3
4
  import { getServerLogger } from "../../../logging/index.js";
4
5
  import { DEFAULT_REGISTRY_CORE_KEY } from "../../../constants/index.js";
5
6
  const logger = getServerLogger();
@@ -15,6 +16,18 @@ export async function getRegistryClient() {
15
16
  storage: getCacheDir(`registry-corestore/${DEFAULT_REGISTRY_CORE_KEY}`),
16
17
  });
17
18
  await registryClient.ready();
19
+ if (registryClient.corestore) {
20
+ registerCorestore(registryClient.corestore, {
21
+ label: "registry-client",
22
+ createdAt: Date.now(),
23
+ });
24
+ }
25
+ if (registryClient.hyperswarm) {
26
+ registerSwarm(registryClient.hyperswarm, {
27
+ label: "registry-client",
28
+ createdAt: Date.now(),
29
+ });
30
+ }
18
31
  logger.info("✅ Registry client ready");
19
32
  return registryClient;
20
33
  }
@@ -23,6 +36,8 @@ export async function closeRegistryClient() {
23
36
  return;
24
37
  const client = registryClient;
25
38
  registryClient = null;
39
+ const corestore = client.corestore;
40
+ const hyperswarm = client.hyperswarm;
26
41
  logger.info("🔌 Closing registry client...");
27
42
  try {
28
43
  await client.close();
@@ -31,6 +46,12 @@ export async function closeRegistryClient() {
31
46
  catch (error) {
32
47
  logger.error("❌ Error closing registry client:", error instanceof Error ? error.message : String(error));
33
48
  }
49
+ finally {
50
+ if (corestore)
51
+ unregisterCorestore(corestore);
52
+ if (hyperswarm)
53
+ unregisterSwarm(hyperswarm);
54
+ }
34
55
  }
35
56
  export function hasActiveRegistryClient() {
36
57
  return registryClient !== null;
@@ -0,0 +1,28 @@
1
+ export interface SuspendableSwarm {
2
+ readonly suspended: boolean;
3
+ suspend(): Promise<void>;
4
+ resume(): Promise<void>;
5
+ }
6
+ export interface SuspendableStore {
7
+ suspend(): Promise<void>;
8
+ resume(): Promise<void>;
9
+ }
10
+ type LifecycleState = "active" | "suspending" | "suspended" | "resuming";
11
+ interface ResourceMeta {
12
+ label: string;
13
+ createdAt: number;
14
+ }
15
+ export declare function registerSwarm(swarm: SuspendableSwarm, meta: ResourceMeta): void;
16
+ export declare function unregisterSwarm(swarm: SuspendableSwarm): void;
17
+ export declare function registerCorestore(store: SuspendableStore, meta: ResourceMeta): void;
18
+ export declare function unregisterCorestore(store: SuspendableStore): void;
19
+ export declare function getLifecycleState(): LifecycleState;
20
+ export declare function getRegisteredResourceCounts(): {
21
+ swarms: number;
22
+ stores: number;
23
+ };
24
+ export declare function resetLifecycleState(): void;
25
+ export declare function suspendRuntime(): Promise<void>;
26
+ export declare function resumeRuntime(): Promise<void>;
27
+ export {};
28
+ //# sourceMappingURL=runtime-lifecycle.d.ts.map
@@ -0,0 +1,132 @@
1
+ import { getServerLogger } from "../../logging/index.js";
2
+ const logger = getServerLogger();
3
+ const swarms = new Map();
4
+ const stores = new Map();
5
+ let state = "active";
6
+ let transitionPromise = null;
7
+ export function registerSwarm(swarm, meta) {
8
+ swarms.set(swarm, meta);
9
+ logger.debug(`Lifecycle: registered swarm [${meta.label}]`);
10
+ }
11
+ export function unregisterSwarm(swarm) {
12
+ const meta = swarms.get(swarm);
13
+ swarms.delete(swarm);
14
+ if (meta) {
15
+ logger.debug(`Lifecycle: unregistered swarm [${meta.label}]`);
16
+ }
17
+ }
18
+ export function registerCorestore(store, meta) {
19
+ stores.set(store, meta);
20
+ logger.debug(`Lifecycle: registered corestore [${meta.label}]`);
21
+ }
22
+ export function unregisterCorestore(store) {
23
+ const meta = stores.get(store);
24
+ stores.delete(store);
25
+ if (meta) {
26
+ logger.debug(`Lifecycle: unregistered corestore [${meta.label}]`);
27
+ }
28
+ }
29
+ export function getLifecycleState() {
30
+ return state;
31
+ }
32
+ export function getRegisteredResourceCounts() {
33
+ return { swarms: swarms.size, stores: stores.size };
34
+ }
35
+ export function resetLifecycleState() {
36
+ swarms.clear();
37
+ stores.clear();
38
+ state = "active";
39
+ transitionPromise = null;
40
+ }
41
+ async function runPhase(snapshot, liveSet, fn, phaseLabel) {
42
+ const errors = [];
43
+ for (const [resource, meta] of snapshot) {
44
+ try {
45
+ await fn(resource);
46
+ logger.debug(`Lifecycle: ${phaseLabel} [${meta.label}] OK`);
47
+ }
48
+ catch (error) {
49
+ if (!liveSet.has(resource))
50
+ continue;
51
+ logger.error(`Lifecycle: ${phaseLabel} [${meta.label}] failed:`, error);
52
+ errors.push(new Error(`${meta.label}: ${String(error)}`));
53
+ }
54
+ }
55
+ if (errors.length > 0) {
56
+ throw new AggregateError(errors, `Lifecycle ${phaseLabel} phase failed`);
57
+ }
58
+ }
59
+ export async function suspendRuntime() {
60
+ if (state === "suspended")
61
+ return;
62
+ if (state === "suspending" && transitionPromise)
63
+ return transitionPromise;
64
+ // Opposite transition in flight: wait for it, then re-evaluate
65
+ if (state === "resuming" && transitionPromise) {
66
+ await transitionPromise;
67
+ return suspendRuntime();
68
+ }
69
+ state = "suspending";
70
+ logger.info(`⏸️ Suspending runtime (${swarms.size} swarms, ${stores.size} stores)`);
71
+ transitionPromise = (async () => {
72
+ const swarmSnapshot = Array.from(swarms.entries());
73
+ const storeSnapshot = Array.from(stores.entries());
74
+ await runPhase(swarmSnapshot, swarms, async (swarm) => {
75
+ if (!swarm.suspended)
76
+ await swarm.suspend();
77
+ }, "suspend-swarm");
78
+ await runPhase(storeSnapshot, stores, async (store) => {
79
+ await store.suspend();
80
+ }, "suspend-store");
81
+ })()
82
+ .then(() => {
83
+ state = "suspended";
84
+ logger.info("⏸️ Runtime suspended");
85
+ })
86
+ .catch((error) => {
87
+ // Partial failure: commit to target so recovery resume() can repair
88
+ // instead of leaving state as "suspending" which blocks all future calls.
89
+ state = "suspended";
90
+ logger.error("⏸️ Runtime suspend partially failed, state committed for recovery");
91
+ throw error;
92
+ })
93
+ .finally(() => {
94
+ transitionPromise = null;
95
+ });
96
+ return transitionPromise;
97
+ }
98
+ export async function resumeRuntime() {
99
+ if (state === "active")
100
+ return;
101
+ if (state === "resuming" && transitionPromise)
102
+ return transitionPromise;
103
+ if (state === "suspending" && transitionPromise) {
104
+ await transitionPromise;
105
+ return resumeRuntime();
106
+ }
107
+ state = "resuming";
108
+ logger.info(`▶️ Resuming runtime (${stores.size} stores, ${swarms.size} swarms)`);
109
+ transitionPromise = (async () => {
110
+ const storeSnapshot = Array.from(stores.entries());
111
+ const swarmSnapshot = Array.from(swarms.entries());
112
+ await runPhase(storeSnapshot, stores, async (store) => {
113
+ await store.resume();
114
+ }, "resume-store");
115
+ await runPhase(swarmSnapshot, swarms, async (swarm) => {
116
+ await swarm.resume();
117
+ }, "resume-swarm");
118
+ })()
119
+ .then(() => {
120
+ state = "active";
121
+ logger.info("▶️ Runtime resumed");
122
+ })
123
+ .catch((error) => {
124
+ state = "active";
125
+ logger.error("▶️ Runtime resume partially failed, state committed for recovery");
126
+ throw error;
127
+ })
128
+ .finally(() => {
129
+ transitionPromise = null;
130
+ });
131
+ return transitionPromise;
132
+ }
@@ -0,0 +1,62 @@
1
+ export interface LlmStats {
2
+ TTFT?: number;
3
+ TPS?: number;
4
+ CacheTokens?: number;
5
+ generatedTokens?: number;
6
+ backendDevice?: "cpu" | "gpu";
7
+ }
8
+ export interface LlmResponse {
9
+ stats?: LlmStats;
10
+ iterate(): AsyncIterable<string>;
11
+ }
12
+ export interface NmtStats {
13
+ totalTime?: number;
14
+ totalTokens?: number;
15
+ decodeTime?: number;
16
+ encodeTime?: number;
17
+ TPS?: number;
18
+ TTFT?: number;
19
+ }
20
+ export interface NmtResponse {
21
+ stats?: NmtStats;
22
+ iterate(): AsyncIterable<string>;
23
+ }
24
+ export interface TtsStats {
25
+ audioDurationMs?: number;
26
+ totalSamples?: number;
27
+ }
28
+ export interface TtsResponse {
29
+ stats?: TtsStats;
30
+ iterate(): AsyncIterable<{
31
+ outputArray: ArrayLike<number>;
32
+ }>;
33
+ }
34
+ export interface EmbedStats {
35
+ total_time_ms?: number;
36
+ tokens_per_second?: number;
37
+ total_tokens?: number;
38
+ backendDevice?: "cpu" | "gpu";
39
+ }
40
+ export interface EmbedResponse {
41
+ stats?: EmbedStats;
42
+ await(): Promise<Float32Array[][]>;
43
+ }
44
+ export interface TranscribeStats {
45
+ audioDurationMs?: number;
46
+ realTimeFactor?: number;
47
+ tokensPerSecond?: number;
48
+ totalTokens?: number;
49
+ totalSegments?: number;
50
+ whisperEncodeMs?: number;
51
+ whisperDecodeMs?: number;
52
+ encoderMs?: number;
53
+ decoderMs?: number;
54
+ melSpecMs?: number;
55
+ }
56
+ export interface TranscribeResponse {
57
+ stats?: TranscribeStats;
58
+ iterate(): AsyncIterable<Array<{
59
+ text: string;
60
+ }>>;
61
+ }
62
+ //# sourceMappingURL=addon-responses.d.ts.map
@@ -0,0 +1 @@
1
+ export {};
@@ -11,7 +11,9 @@ let validatedEnv = null;
11
11
  * Returns whether RPC config was parsed from arguments.
12
12
  */
13
13
  export function initEnv() {
14
- const defaultHomeDir = process.env["HOME"] || process.env["USERPROFILE"] || "/tmp";
14
+ const defaultHomeDir = process.env["HOME"] ??
15
+ process.env["USERPROFILE"] ??
16
+ "/tmp";
15
17
  let envConfig = {
16
18
  HOME_DIR: defaultHomeDir,
17
19
  };
@@ -12,7 +12,7 @@ import { DelegateProviderError } from "../../utils/errors-server.js";
12
12
  import { cleanupStaleConnection } from "../bare/delegate-rpc-client.js";
13
13
  import { shouldProfileDelegation, createDelegationTimings, createDelegationStreamTimings, recordDelegationEvents, recordDelegationStreamEvents, buildDelegationStreamBreakdown, flushServerConnectionEvent, consumeBreakdownConnectionTime, } from "./profiling/delegation-profiler.js";
14
14
  const logger = getServerLogger();
15
- import { getNextCommandId } from "./delegate-utils.js";
15
+ import { getNextCommandId } from "./rpc-utils.js";
16
16
  function checkAndThrowError(response) {
17
17
  if (response.type === "error") {
18
18
  throw new DelegateProviderError(response.message || "Unknown provider error", response.code);
@@ -1,18 +1,21 @@
1
1
  import { requestSchema, normalizeModelType, PROFILING_KEY, } from "../../schemas/index.js";
2
2
  import { nowMs } from "../../profiling/index.js";
3
3
  import { resolveModelConfig } from "../bare/registry/model-config-registry.js";
4
- import { sendErrorResponse } from "../error-handlers.js";
5
- import { RPCNoDataReceivedError, RPCUnknownRequestTypeError, } from "../../utils/errors-server.js";
4
+ import { sendErrorResponse, sendStreamErrorResponse, } from "../error-handlers.js";
5
+ import { RPCUnknownRequestTypeError, PluginHandlerTypeMismatchError, } from "../../utils/errors-server.js";
6
6
  import { registry } from "./handler-registry.js";
7
- import { executeHandler, handleInitConfig, isInitConfigMessage, } from "./handler-utils.js";
7
+ import { executeHandler, executeDuplexHandler, handleInitConfig, isInitConfigMessage, } from "./handler-utils.js";
8
8
  import { createServerProfiler } from "./profiling/index.js";
9
9
  export async function handleRequest(req) {
10
10
  let profiler;
11
11
  let validationStart = 0;
12
12
  try {
13
13
  const rawData = req.data?.toString();
14
+ // Duplex stream request: metadata arrives as the first chunk on the
15
+ // request stream (client used createRequestStream instead of send).
14
16
  if (!rawData) {
15
- throw new RPCNoDataReceivedError();
17
+ await handleDuplexRequest(req);
18
+ return;
16
19
  }
17
20
  // Timing runs unconditionally since we can't know if client
18
21
  // requested profiling until after parsing.
@@ -67,6 +70,49 @@ function extractProfilingMeta(data) {
67
70
  profilingMeta: meta,
68
71
  };
69
72
  }
73
+ async function handleDuplexRequest(req) {
74
+ const inputStream = req.createRequestStream();
75
+ const outputStream = req.createResponseStream();
76
+ let profiler;
77
+ try {
78
+ const firstChunk = await new Promise((resolve, reject) => {
79
+ const onData = (data) => {
80
+ inputStream.off("error", onError);
81
+ inputStream.pause();
82
+ resolve(data);
83
+ };
84
+ const onError = (err) => {
85
+ inputStream.off("data", onData);
86
+ reject(err instanceof Error ? err : new Error(String(err)));
87
+ };
88
+ inputStream.once("data", onData);
89
+ inputStream.once("error", onError);
90
+ });
91
+ const parseStart = nowMs();
92
+ const jsonData = JSON.parse(firstChunk.toString());
93
+ const jsonParseMs = nowMs() - parseStart;
94
+ const { data: cleanData, profilingMeta } = extractProfilingMeta(jsonData);
95
+ profiler = createServerProfiler(profilingMeta);
96
+ profiler.markRequestParsed(jsonParseMs);
97
+ const validationStart = nowMs();
98
+ const processedData = applyDeviceDefaultsToRequest(cleanData);
99
+ const request = requestSchema.parse(processedData);
100
+ attachProfilingMetaToRequest(request, profilingMeta);
101
+ profiler.markRequestValidated(nowMs() - validationStart);
102
+ const entry = registry[request.type];
103
+ if (!entry) {
104
+ throw new RPCUnknownRequestTypeError(request.type);
105
+ }
106
+ if (entry.type !== "duplex") {
107
+ throw new PluginHandlerTypeMismatchError(request.type, "duplex", entry.type);
108
+ }
109
+ await executeDuplexHandler(req, request, entry, inputStream, outputStream, profiler);
110
+ }
111
+ catch (error) {
112
+ inputStream.destroy();
113
+ sendStreamErrorResponse(outputStream, error, profiler);
114
+ }
115
+ }
70
116
  /**
71
117
  * Apply device-specific config defaults to loadModel requests before schema parsing.
72
118
  * This ensures device defaults are applied before schema defaults.
@@ -7,6 +7,7 @@ import { handleCompletionStreamDelegated } from "./handlers/completion-stream-de
7
7
  import { getModelEntry } from "../bare/registry/model-registry.js";
8
8
  import { handleUnloadModel } from "./handlers/unload-model.js";
9
9
  import { handleUnloadModelDelegated } from "./handlers/unload-model-delegated.js";
10
+ import { handleTranscribe } from "./handlers/transcribe.js";
10
11
  import { handleTranscribeStream } from "./handlers/transcribe-stream.js";
11
12
  import { handleEmbed } from "./handlers/embed.js";
12
13
  import { handleTranslate } from "./handlers/translate.js";
@@ -20,15 +21,24 @@ import { handleTextToSpeech } from "./handlers/text-to-speech.js";
20
21
  import { handleGetModelInfo } from "./handlers/get-model-info.js";
21
22
  import { handleOCRStream } from "./handlers/ocr-stream.js";
22
23
  import { handleHeartbeat } from "./handlers/heartbeat.js";
24
+ import { handleFinetune } from "./handlers/finetune.js";
23
25
  import { handleHeartbeatDelegated } from "./handlers/heartbeat-delegated.js";
24
26
  import { handleCancelDelegated } from "./handlers/cancel-delegated.js";
27
+ import { handleDiffusionStream } from "./handlers/diffusion-stream.js";
25
28
  import { handlePluginInvoke, handlePluginInvokeStream, } from "./handlers/plugin-invoke.js";
26
29
  import { handleModelRegistryList, handleModelRegistrySearch, handleModelRegistryGetModel, } from "./handlers/registry.js";
30
+ import { handleSuspend } from "./handlers/suspend.js";
31
+ import { handleResume } from "./handlers/resume.js";
27
32
  function ragSupportsProgress(request) {
28
33
  if (request.type !== "rag")
29
34
  return false;
30
35
  return ["ingest", "saveEmbeddings", "reindex"].includes(request.operation);
31
36
  }
37
+ function finetuneSupportsProgress(request) {
38
+ if (request.type !== "finetune")
39
+ return false;
40
+ return ["start", "resume", undefined].includes(request.operation);
41
+ }
32
42
  function isModelDelegated(request) {
33
43
  if (!("modelId" in request))
34
44
  return false;
@@ -78,12 +88,16 @@ export const registry = {
78
88
  type: "reply",
79
89
  handler: handleModelRegistryGetModel,
80
90
  },
91
+ suspend: { type: "reply", handler: handleSuspend },
92
+ resume: { type: "reply", handler: handleResume },
81
93
  // Simple Stream handlers
82
- transcribeStream: { type: "stream", handler: handleTranscribeStream },
94
+ transcribe: { type: "stream", handler: handleTranscribe },
95
+ transcribeStream: { type: "duplex", handler: handleTranscribeStream },
83
96
  loggingStream: { type: "stream", handler: handleLoggingStream },
84
97
  translate: { type: "stream", handler: handleTranslate },
85
98
  textToSpeech: { type: "stream", handler: handleTextToSpeech },
86
99
  ocrStream: { type: "stream", handler: handleOCRStream },
100
+ diffusionStream: { type: "stream", handler: handleDiffusionStream },
87
101
  pluginInvokeStream: { type: "stream", handler: handlePluginInvokeStream },
88
102
  // Handlers with delegation support
89
103
  loadModel: {
@@ -110,4 +124,9 @@ export const registry = {
110
124
  handler: handleRag,
111
125
  supportsProgress: ragSupportsProgress,
112
126
  },
127
+ finetune: {
128
+ type: "reply",
129
+ handler: handleFinetune,
130
+ supportsProgress: finetuneSupportsProgress,
131
+ },
113
132
  };
@@ -4,13 +4,15 @@ import { type ServerProfiler } from "./profiling/index";
4
4
  type ReplyHandler = (request: any, ...args: any[]) => Promise<Response> | Response;
5
5
  type StreamHandler = (request: any, ...args: any[]) => AsyncGenerator<Response>;
6
6
  type ProgressHandler = (request: any, ...args: any[]) => Promise<Response>;
7
+ type DuplexStreamHandler = (request: any, inputStream: any) => AsyncGenerator<Response>;
7
8
  export type HandlerEntry = {
8
- type: "reply" | "stream";
9
- handler: ReplyHandler | StreamHandler | ProgressHandler;
10
- delegatedHandler?: ReplyHandler | StreamHandler | ProgressHandler;
9
+ type: "reply" | "stream" | "duplex";
10
+ handler: ReplyHandler | StreamHandler | ProgressHandler | DuplexStreamHandler;
11
+ delegatedHandler?: ReplyHandler | StreamHandler | ProgressHandler | DuplexStreamHandler;
11
12
  isDelegated?: (request: Request) => boolean;
12
13
  supportsProgress?: boolean | ((request: Request) => boolean);
13
14
  };
15
+ export declare function executeDuplexHandler(_req: RPC.IncomingRequest, request: Request, entry: HandlerEntry, inputStream: ReturnType<RPC.IncomingRequest["createRequestStream"]>, outputStream: ReturnType<RPC.IncomingRequest["createResponseStream"]>, profiler: ServerProfiler): Promise<void>;
14
16
  export declare function executeHandler(req: RPC.IncomingRequest, request: Request, entry: HandlerEntry, profiler: ServerProfiler): Promise<void>;
15
17
  type InitConfigMessage = {
16
18
  type: "__init_config";
@@ -1,9 +1,11 @@
1
1
  import { PROFILING_KEY, } from "../../schemas/index.js";
2
2
  import { sendErrorResponse, sendStreamErrorResponse, } from "../error-handlers.js";
3
+ import { PluginHandlerTypeMismatchError } from "../../utils/errors-server.js";
3
4
  import { setSDKConfig } from "../bare/registry/config-registry.js";
4
5
  import { setRuntimeContext } from "../bare/registry/runtime-context-registry.js";
5
6
  import {} from "./profiling/index.js";
6
- import { nowMs } from "../../profiling/clock.js";
7
+ import { isTerminalChunk } from "./rpc-utils.js";
8
+ import { createProgressThrottle } from "./progress-throttle.js";
7
9
  function getProfilingMetaFromRequest(request) {
8
10
  if (PROFILING_KEY in request) {
9
11
  return request[PROFILING_KEY];
@@ -32,6 +34,7 @@ async function executeReplyHandler(req, request, handler, profiler, isDelegated)
32
34
  async function executeStreamHandler(req, request, handler, profiler, isDelegated) {
33
35
  const stream = req.createResponseStream();
34
36
  profiler.startHandler();
37
+ let sentFinalChunk = false;
35
38
  try {
36
39
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
40
  let generator;
@@ -43,12 +46,22 @@ async function executeStreamHandler(req, request, handler, profiler, isDelegated
43
46
  generator = handler(request);
44
47
  }
45
48
  for await (const response of generator) {
46
- stream.write(profiler.serialize(response, false) + "\n", "utf-8");
49
+ if (isTerminalChunk(response)) {
50
+ profiler.endHandler();
51
+ stream.write(profiler.serialize(response, true) + "\n", "utf-8");
52
+ sentFinalChunk = true;
53
+ }
54
+ else {
55
+ stream.write(profiler.serialize(response, false) + "\n", "utf-8");
56
+ }
47
57
  }
48
- profiler.endHandler();
49
- const trailer = profiler.serialize();
50
- if (trailer) {
51
- stream.write(trailer + "\n", "utf-8");
58
+ // Fallback
59
+ if (!sentFinalChunk) {
60
+ profiler.endHandler();
61
+ const trailer = profiler.serialize();
62
+ if (trailer) {
63
+ stream.write(trailer + "\n", "utf-8");
64
+ }
52
65
  }
53
66
  stream.end();
54
67
  }
@@ -57,73 +70,59 @@ async function executeStreamHandler(req, request, handler, profiler, isDelegated
57
70
  sendStreamErrorResponse(stream, error, profiler);
58
71
  }
59
72
  }
60
- const PROGRESS_THROTTLE_MS = 150;
61
73
  async function executeProgressHandler(req, request, handler, profiler, isDelegated) {
62
74
  const stream = req.createResponseStream();
63
75
  profiler.startHandler();
64
- let lastProgressWrite = 0;
65
- let pendingUpdate = null;
66
- let flushTimer = null;
67
- const writeProgress = (update) => {
68
- stream.write(profiler.serialize(update, false) + "\n", "utf-8");
69
- };
70
- const progressCallback = (update) => {
71
- const now = nowMs();
72
- if (now - lastProgressWrite >= PROGRESS_THROTTLE_MS) {
73
- lastProgressWrite = now;
74
- pendingUpdate = null;
75
- writeProgress(update);
76
- }
77
- else {
78
- pendingUpdate = update;
79
- if (!flushTimer) {
80
- flushTimer = setTimeout(() => {
81
- flushTimer = null;
82
- if (pendingUpdate) {
83
- lastProgressWrite = nowMs();
84
- writeProgress(pendingUpdate);
85
- pendingUpdate = null;
86
- }
87
- }, PROGRESS_THROTTLE_MS - (now - lastProgressWrite));
88
- }
89
- }
76
+ const writeBatch = (updates) => {
77
+ const payload = updates
78
+ .map((u) => profiler.serialize(u, false))
79
+ .join("\n");
80
+ stream.write(payload + "\n", "utf-8");
90
81
  };
82
+ const throttle = createProgressThrottle(writeBatch);
91
83
  try {
92
84
  let response;
93
85
  if (isDelegated) {
94
86
  const profilingMeta = getProfilingMetaFromRequest(request);
95
- const options = { progressCallback };
87
+ const options = { progressCallback: throttle.push };
96
88
  if (profilingMeta) {
97
89
  options.profilingMeta = profilingMeta;
98
90
  }
99
91
  response = await handler(request, options);
100
92
  }
101
93
  else {
102
- response = await handler(request, progressCallback);
103
- }
104
- if (flushTimer) {
105
- clearTimeout(flushTimer);
106
- flushTimer = null;
107
- }
108
- if (pendingUpdate) {
109
- writeProgress(pendingUpdate);
110
- pendingUpdate = null;
94
+ response = await handler(request, throttle.push);
111
95
  }
96
+ throttle.flush();
112
97
  profiler.endHandler();
113
98
  stream.write(profiler.serialize(response, true) + "\n", "utf-8");
114
99
  stream.end();
115
100
  }
116
101
  catch (error) {
117
- if (flushTimer) {
118
- clearTimeout(flushTimer);
119
- flushTimer = null;
102
+ throttle.flush();
103
+ profiler.endHandler();
104
+ sendStreamErrorResponse(stream, error, profiler);
105
+ }
106
+ }
107
+ export async function executeDuplexHandler(_req, request, entry, inputStream, outputStream, profiler) {
108
+ const handler = entry.delegatedHandler && entry.isDelegated?.(request)
109
+ ? entry.delegatedHandler
110
+ : entry.handler;
111
+ profiler.startHandler();
112
+ try {
113
+ for await (const response of handler(request, inputStream)) {
114
+ outputStream.write(profiler.serialize(response, false) + "\n", "utf-8");
120
115
  }
121
- if (pendingUpdate) {
122
- writeProgress(pendingUpdate);
123
- pendingUpdate = null;
116
+ profiler.endHandler();
117
+ const trailer = profiler.serialize();
118
+ if (trailer) {
119
+ outputStream.write(trailer + "\n", "utf-8");
124
120
  }
121
+ outputStream.end();
122
+ }
123
+ catch (error) {
125
124
  profiler.endHandler();
126
- sendStreamErrorResponse(stream, error, profiler);
125
+ sendStreamErrorResponse(outputStream, error, profiler);
127
126
  }
128
127
  }
129
128
  // Unified handler executor with delegation and progress support
@@ -135,6 +134,9 @@ export async function executeHandler(req, request, entry, profiler) {
135
134
  (typeof entry.supportsProgress === "function"
136
135
  ? entry.supportsProgress(request)
137
136
  : entry.supportsProgress);
137
+ if (entry.type === "duplex") {
138
+ throw new PluginHandlerTypeMismatchError(request.type, "reply or stream", "duplex");
139
+ }
138
140
  if (entry.type === "stream") {
139
141
  await executeStreamHandler(req, request, handler, profiler, isDelegated);
140
142
  }
@@ -1,10 +1,12 @@
1
1
  import { deleteCache as deleteCacheUtil } from "../../bare/ops/kv-cache-utils.js";
2
+ import { clearCachedMessageCounts } from "../../bare/plugins/llamacpp-completion/ops/completion-stream.js";
2
3
  import { getServerLogger } from "../../../logging/index.js";
3
4
  const logger = getServerLogger();
4
5
  export async function handleDeleteCache(request) {
5
6
  try {
6
7
  if ("all" in request && request.all) {
7
8
  await deleteCacheUtil({ all: true });
9
+ clearCachedMessageCounts();
8
10
  }
9
11
  else if ("kvCacheKey" in request) {
10
12
  const params = {
@@ -14,6 +16,7 @@ export async function handleDeleteCache(request) {
14
16
  params.modelId = request.modelId;
15
17
  }
16
18
  await deleteCacheUtil(params);
19
+ clearCachedMessageCounts();
17
20
  }
18
21
  return {
19
22
  type: "deleteCache",
@@ -0,0 +1,3 @@
1
+ import type { DiffusionStreamRequest, DiffusionStreamResponse } from "../../../schemas/sdcpp-config";
2
+ export declare function handleDiffusionStream(request: DiffusionStreamRequest): AsyncGenerator<DiffusionStreamResponse>;
3
+ //# sourceMappingURL=diffusion-stream.d.ts.map
@@ -0,0 +1,4 @@
1
+ import { dispatchPluginStream } from "./plugin-dispatch.js";
2
+ export async function* handleDiffusionStream(request) {
3
+ yield* dispatchPluginStream(request.modelId, "diffusionStream", request);
4
+ }
@@ -0,0 +1,3 @@
1
+ import type { FinetuneProgressResponse, FinetuneRequest, FinetuneResult } from "../../../schemas/index";
2
+ export declare function handleFinetune(request: FinetuneRequest, progressCallback?: (update: FinetuneProgressResponse) => void): Promise<FinetuneResult>;
3
+ //# sourceMappingURL=finetune.d.ts.map
@@ -0,0 +1,16 @@
1
+ import { dispatchPluginReply } from "./plugin-dispatch.js";
2
+ import { startFinetune } from "../../bare/plugins/llamacpp-completion/ops/finetune.js";
3
+ export async function handleFinetune(request, progressCallback) {
4
+ if (progressCallback &&
5
+ (request.operation === "start" || request.operation === "resume" || request.operation === undefined)) {
6
+ return startFinetune(request, (progress) => {
7
+ const update = {
8
+ type: "finetune:progress",
9
+ modelId: request.modelId,
10
+ ...progress,
11
+ };
12
+ progressCallback(update);
13
+ });
14
+ }
15
+ return dispatchPluginReply(request.modelId, "finetune", request);
16
+ }