@qvac/sdk 0.3.0 → 0.4.1

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 (210) hide show
  1. package/README.md +22 -0
  2. package/dist/client/api/cancel.d.ts +1 -1
  3. package/dist/client/api/cancel.js +4 -3
  4. package/dist/client/api/completion-stream.d.ts +24 -32
  5. package/dist/client/api/completion-stream.js +142 -50
  6. package/dist/client/api/delete-cache.js +3 -2
  7. package/dist/client/api/download-asset.d.ts +3 -3
  8. package/dist/client/api/download-asset.js +12 -17
  9. package/dist/client/api/embed.d.ts +1 -1
  10. package/dist/client/api/embed.js +4 -3
  11. package/dist/client/api/get-model-info.d.ts +29 -0
  12. package/dist/client/api/get-model-info.js +14 -0
  13. package/dist/client/api/index.d.ts +3 -0
  14. package/dist/client/api/index.js +3 -0
  15. package/dist/client/api/load-model.d.ts +3 -3
  16. package/dist/client/api/load-model.js +13 -22
  17. package/dist/client/api/logging-stream.d.ts +1 -1
  18. package/dist/client/api/logging-stream.js +3 -2
  19. package/dist/client/api/ping.d.ts +1 -1
  20. package/dist/client/api/ping.js +3 -2
  21. package/dist/client/api/provide.d.ts +1 -1
  22. package/dist/client/api/provide.js +4 -3
  23. package/dist/client/api/rag.d.ts +3 -3
  24. package/dist/client/api/rag.js +13 -12
  25. package/dist/client/api/set-config.d.ts +7 -0
  26. package/dist/client/api/set-config.js +20 -0
  27. package/dist/client/api/stop-provider.d.ts +1 -1
  28. package/dist/client/api/stop-provider.js +4 -3
  29. package/dist/client/api/text-to-speech.d.ts +7 -0
  30. package/dist/client/api/text-to-speech.js +58 -0
  31. package/dist/client/api/transcribe.d.ts +4 -2
  32. package/dist/client/api/transcribe.js +9 -5
  33. package/dist/client/api/translate.d.ts +1 -1
  34. package/dist/client/api/translate.js +3 -2
  35. package/dist/client/api/unload-model.d.ts +5 -1
  36. package/dist/client/api/unload-model.js +14 -4
  37. package/dist/client/config-manager.d.ts +4 -0
  38. package/dist/client/config-manager.js +8 -0
  39. package/dist/client/index.d.ts +1 -1
  40. package/dist/client/index.js +1 -1
  41. package/dist/client/init-hooks.d.ts +6 -0
  42. package/dist/client/init-hooks.js +37 -0
  43. package/dist/client/rpc/bare-client.d.ts +69 -0
  44. package/dist/client/rpc/bare-client.js +5 -4
  45. package/dist/client/rpc/bare-rpc-client.js +7 -3
  46. package/dist/client/rpc/expo-rpc-client.d.ts +1 -0
  47. package/dist/client/rpc/expo-rpc-client.js +9 -1
  48. package/dist/client/rpc/node-rpc-client.d.ts +1 -1
  49. package/dist/client/rpc/node-rpc-client.js +22 -9
  50. package/dist/client/rpc/rpc-client.d.ts +1 -0
  51. package/dist/client/rpc/rpc-client.js +20 -1
  52. package/dist/constants/audio.d.ts +1 -2
  53. package/dist/constants/audio.js +1 -17
  54. package/dist/examples/cache-management.d.ts +2 -0
  55. package/dist/examples/cache-management.js +97 -0
  56. package/dist/examples/delegated-inference/consumer.js +2 -2
  57. package/dist/examples/download-with-blind-relays.d.ts +2 -0
  58. package/dist/examples/download-with-blind-relays.js +48 -0
  59. package/dist/examples/download-with-cancel.js +3 -4
  60. package/dist/examples/embed-hyperdrive.js +0 -1
  61. package/dist/examples/kv-cache-cleanup.js +0 -1
  62. package/dist/examples/kv-cache-custom-key.js +0 -1
  63. package/dist/examples/kv-cache-example.js +0 -1
  64. package/dist/examples/llamacpp-file-logging.js +0 -1
  65. package/dist/examples/llamacpp-filesystem.js +2 -2
  66. package/dist/examples/llamacpp-http.js +0 -1
  67. package/dist/examples/llamacpp-hyperdrive.js +0 -1
  68. package/dist/examples/llamacpp-multimodal.js +0 -1
  69. package/dist/examples/llamacpp-native-tools.js +118 -36
  70. package/dist/examples/llamacpp-sharded.d.ts +2 -0
  71. package/dist/examples/llamacpp-sharded.js +44 -0
  72. package/dist/examples/multi-model-demo.js +0 -1
  73. package/dist/examples/parallel-download.js +2 -2
  74. package/dist/examples/rag/rag-chromadb.js +0 -1
  75. package/dist/examples/rag/rag-hyperdb-workspaces.js +0 -1
  76. package/dist/examples/rag/rag-hyperdb.js +0 -1
  77. package/dist/examples/rag/rag-lancedb.js +0 -1
  78. package/dist/examples/rag/rag-sqlite.js +0 -1
  79. package/dist/examples/text-to-speech.d.ts +3 -0
  80. package/dist/examples/text-to-speech.js +137 -0
  81. package/dist/examples/translation/translation-indic.js +3 -1
  82. package/dist/examples/translation/translation-llm-context.js +0 -1
  83. package/dist/examples/translation/translation-llm.js +2 -2
  84. package/dist/examples/translation/translation-opus.js +3 -1
  85. package/dist/examples/translation/translation-stream.js +0 -1
  86. package/dist/examples/whispercpp-filesystem.js +32 -5
  87. package/dist/examples/whispercpp-microphone-record.js +9 -9
  88. package/dist/examples/whispercpp-prompt.d.ts +2 -0
  89. package/dist/examples/whispercpp-prompt.js +68 -0
  90. package/dist/expo/plugins/withMobileBundle.js +9 -3
  91. package/dist/index.d.ts +4 -2
  92. package/dist/index.js +4 -2
  93. package/dist/models/hyperdrive/models.d.ts +1916 -100
  94. package/dist/models/hyperdrive/models.js +2042 -102
  95. package/dist/schemas/common.d.ts +413 -58
  96. package/dist/schemas/common.js +9 -0
  97. package/dist/schemas/completion-stream.d.ts +26 -22
  98. package/dist/schemas/completion-stream.js +9 -23
  99. package/dist/schemas/download-asset.d.ts +77 -2
  100. package/dist/schemas/download-asset.js +15 -4
  101. package/dist/schemas/get-model-info.d.ts +100 -0
  102. package/dist/schemas/get-model-info.js +40 -0
  103. package/dist/schemas/index.d.ts +7 -0
  104. package/dist/schemas/index.js +7 -0
  105. package/dist/schemas/llamacpp-config.d.ts +2 -1
  106. package/dist/schemas/llamacpp-config.js +3 -4
  107. package/dist/schemas/load-model.d.ts +2316 -266
  108. package/dist/schemas/load-model.js +157 -10
  109. package/dist/schemas/model-src-utils.d.ts +98 -0
  110. package/dist/schemas/model-src-utils.js +31 -0
  111. package/dist/schemas/sdk-errors-client.d.ts +25 -0
  112. package/dist/schemas/sdk-errors-client.js +111 -0
  113. package/dist/schemas/sdk-errors-server.d.ts +55 -0
  114. package/dist/schemas/sdk-errors-server.js +271 -0
  115. package/dist/schemas/set-config.d.ts +21 -0
  116. package/dist/schemas/set-config.js +14 -0
  117. package/dist/schemas/text-to-speech.d.ts +34 -0
  118. package/dist/schemas/text-to-speech.js +25 -0
  119. package/dist/schemas/tools.d.ts +62 -0
  120. package/dist/schemas/tools.js +43 -0
  121. package/dist/schemas/transcription.d.ts +25 -2
  122. package/dist/schemas/transcription.js +12 -1
  123. package/dist/schemas/translation-config.d.ts +33 -5
  124. package/dist/schemas/translation-config.js +18 -1
  125. package/dist/schemas/unload-model.d.ts +2 -0
  126. package/dist/schemas/unload-model.js +2 -0
  127. package/dist/schemas/whispercpp-config.d.ts +55 -18
  128. package/dist/schemas/whispercpp-config.js +63 -15
  129. package/dist/server/bare/addons/cancel.js +2 -1
  130. package/dist/server/bare/addons/llamacpp/create-model.d.ts +9 -2
  131. package/dist/server/bare/addons/llamacpp/create-model.js +23 -23
  132. package/dist/server/bare/addons/llamacpp/handlers/completion-stream.d.ts +10 -2
  133. package/dist/server/bare/addons/llamacpp/handlers/completion-stream.js +62 -43
  134. package/dist/server/bare/addons/llamacpp/handlers/embed.js +3 -2
  135. package/dist/server/bare/addons/llamacpp/kv-cache-utils.d.ts +1 -1
  136. package/dist/server/bare/addons/llamacpp/kv-cache-utils.js +6 -2
  137. package/dist/server/bare/addons/load-model.js +59 -28
  138. package/dist/server/bare/addons/translation/create-model.d.ts +5 -1
  139. package/dist/server/bare/addons/translation/create-model.js +17 -25
  140. package/dist/server/bare/addons/translation/handlers/translate.js +10 -1
  141. package/dist/server/bare/addons/tts/create-model.d.ts +10 -0
  142. package/dist/server/bare/addons/tts/create-model.js +25 -0
  143. package/dist/server/bare/addons/tts/handlers/text-to-speech.d.ts +3 -0
  144. package/dist/server/bare/addons/tts/handlers/text-to-speech.js +87 -0
  145. package/dist/server/bare/addons/tts/index.d.ts +3 -0
  146. package/dist/server/bare/addons/tts/index.js +2 -0
  147. package/dist/server/bare/addons/unload-model.js +21 -3
  148. package/dist/server/bare/addons/whispercpp/create-model.d.ts +5 -1
  149. package/dist/server/bare/addons/whispercpp/create-model.js +13 -32
  150. package/dist/server/bare/addons/whispercpp/handlers/transcribe-stream.js +41 -20
  151. package/dist/server/bare/delegate-rpc-client.js +3 -2
  152. package/dist/server/bare/hyperswarm.d.ts +3 -0
  153. package/dist/server/bare/hyperswarm.js +22 -1
  154. package/dist/server/bare/rag-hyperdb/rag-manager.js +2 -3
  155. package/dist/server/bare/registry/config-registry.d.ts +5 -0
  156. package/dist/server/bare/registry/config-registry.js +39 -0
  157. package/dist/server/bare/registry/model-registry.d.ts +13 -0
  158. package/dist/server/bare/registry/model-registry.js +24 -7
  159. package/dist/server/rpc/handle-request.js +42 -3
  160. package/dist/server/rpc/handlers/completion-stream-delegated.js +2 -1
  161. package/dist/server/rpc/handlers/completion-stream.js +11 -4
  162. package/dist/server/rpc/handlers/download-asset.js +2 -3
  163. package/dist/server/rpc/handlers/get-model-info.d.ts +3 -0
  164. package/dist/server/rpc/handlers/get-model-info.js +148 -0
  165. package/dist/server/rpc/handlers/index.d.ts +4 -0
  166. package/dist/server/rpc/handlers/index.js +6 -0
  167. package/dist/server/rpc/handlers/load-model/http.js +51 -10
  168. package/dist/server/rpc/handlers/load-model/hyperdrive.js +336 -156
  169. package/dist/server/rpc/handlers/load-model/index.js +1 -1
  170. package/dist/server/rpc/handlers/load-model/resolve.d.ts +1 -1
  171. package/dist/server/rpc/handlers/load-model/resolve.js +10 -6
  172. package/dist/server/rpc/handlers/load-model-delegated.js +7 -4
  173. package/dist/server/rpc/handlers/load-model.js +19 -1
  174. package/dist/server/rpc/handlers/provideHandler/handler.js +2 -1
  175. package/dist/server/rpc/handlers/rag.js +0 -3
  176. package/dist/server/rpc/handlers/set-config.d.ts +3 -0
  177. package/dist/server/rpc/handlers/set-config.js +18 -0
  178. package/dist/server/rpc/handlers/stopProvideHandler.js +3 -1
  179. package/dist/server/rpc/handlers/text-to-speech.d.ts +3 -0
  180. package/dist/server/rpc/handlers/text-to-speech.js +7 -0
  181. package/dist/server/rpc/handlers/transcribe-stream.js +6 -2
  182. package/dist/server/rpc/handlers/unload-model.js +7 -0
  183. package/dist/server/utils/audio/decoder.js +1 -1
  184. package/dist/server/utils/cache.d.ts +13 -8
  185. package/dist/server/utils/cache.js +69 -14
  186. package/dist/server/utils/checksum.d.ts +2 -0
  187. package/dist/server/utils/checksum.js +24 -0
  188. package/dist/server/utils/index.d.ts +2 -0
  189. package/dist/server/utils/index.js +2 -0
  190. package/dist/server/utils/shard-utils.d.ts +22 -0
  191. package/dist/server/utils/shard-utils.js +37 -0
  192. package/dist/server/utils/tool-integration.d.ts +13 -0
  193. package/dist/server/utils/tool-integration.js +43 -0
  194. package/dist/server/utils/tool-parser.d.ts +7 -0
  195. package/dist/server/utils/tool-parser.js +244 -0
  196. package/dist/utils/errors-base.d.ts +3 -0
  197. package/dist/utils/errors-base.js +13 -0
  198. package/dist/utils/errors-client.d.ts +107 -0
  199. package/dist/utils/errors-client.js +186 -0
  200. package/dist/utils/errors-server.d.ts +146 -0
  201. package/dist/utils/errors-server.js +253 -0
  202. package/dist/utils/tool-helpers.d.ts +17 -0
  203. package/dist/utils/tool-helpers.js +99 -0
  204. package/package.json +14 -10
  205. package/dist/examples/llamacpp-tools-routing.d.ts +0 -2
  206. package/dist/examples/llamacpp-tools-routing.js +0 -364
  207. package/dist/examples/llamacpp-tools.d.ts +0 -2
  208. package/dist/examples/llamacpp-tools.js +0 -81
  209. package/dist/server/http-server.d.ts +0 -2
  210. package/dist/server/http-server.js +0 -189
@@ -0,0 +1,37 @@
1
+ import { getCachedConfig } from "./config-manager.js";
2
+ /**
3
+ * Replays cached configuration to the worker after initialization.
4
+ * This ensures config persists across worker restarts.
5
+ */
6
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
+ export const replayConfigIfCached = async (rpc) => {
8
+ const config = getCachedConfig();
9
+ if (!config) {
10
+ console.log("No cached config to replay");
11
+ return;
12
+ }
13
+ console.log("🔄 Replaying cached config to worker:", config);
14
+ try {
15
+ const request = {
16
+ type: "setConfig",
17
+ config,
18
+ };
19
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
20
+ const req = rpc.request(1);
21
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
22
+ req.send(JSON.stringify(request), "utf8");
23
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
24
+ const response = await req.reply("utf8");
25
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
26
+ const parsed = JSON.parse(response.toString());
27
+ if (parsed.type !== "setConfig" || !parsed.success) {
28
+ console.error("Failed to replay config:", parsed.error);
29
+ }
30
+ else {
31
+ console.log("✅ Config successfully replayed to worker");
32
+ }
33
+ }
34
+ catch (error) {
35
+ console.error("Error replaying config:", error);
36
+ }
37
+ };
@@ -13,17 +13,51 @@ export declare function stream<T extends Request>(request: T): AsyncGenerator<{
13
13
  tokensPerSecond: number;
14
14
  cacheTokens: number;
15
15
  } | undefined;
16
+ toolCallEvent?: {
17
+ type: "toolCall";
18
+ call: {
19
+ id: string;
20
+ name: string;
21
+ arguments: Record<string, unknown>;
22
+ raw?: string | undefined;
23
+ };
24
+ } | {
25
+ type: "toolCallError";
26
+ error: {
27
+ code: "PARSE_ERROR" | "VALIDATION_ERROR" | "UNKNOWN_TOOL";
28
+ message: string;
29
+ raw?: string | undefined;
30
+ };
31
+ } | undefined;
32
+ toolCalls?: {
33
+ id: string;
34
+ name: string;
35
+ arguments: Record<string, unknown>;
36
+ raw?: string | undefined;
37
+ }[] | undefined;
16
38
  error?: string | undefined;
17
39
  } | {
18
40
  type: "deleteCache";
19
41
  success: boolean;
20
42
  error?: string | undefined;
43
+ } | {
44
+ type: "textToSpeech";
45
+ buffer: number[];
46
+ done: boolean;
21
47
  } | {
22
48
  type: "modelProgress";
23
49
  downloaded: number;
24
50
  total: number;
25
51
  percentage: number;
26
52
  downloadKey: string;
53
+ shardInfo?: {
54
+ currentShard: number;
55
+ totalShards: number;
56
+ shardName: string;
57
+ overallDownloaded: number;
58
+ overallTotal: number;
59
+ overallPercentage: number;
60
+ } | undefined;
27
61
  } | {
28
62
  type: "loadModel";
29
63
  success: boolean;
@@ -59,6 +93,8 @@ export declare function stream<T extends Request>(request: T): AsyncGenerator<{
59
93
  type: "unloadModel";
60
94
  success: boolean;
61
95
  error?: string | undefined;
96
+ hasActiveModels?: boolean | undefined;
97
+ hasActiveProviders?: boolean | undefined;
62
98
  } | {
63
99
  type: "pong";
64
100
  number: number;
@@ -110,6 +146,39 @@ export declare function stream<T extends Request>(request: T): AsyncGenerator<{
110
146
  success: boolean;
111
147
  operation: "deleteEmbeddings";
112
148
  error?: string | undefined;
149
+ } | {
150
+ type: "setConfig";
151
+ success: boolean;
152
+ error?: string | undefined;
153
+ } | {
154
+ type: "getModelInfo";
155
+ modelInfo: {
156
+ name: string;
157
+ modelId: string;
158
+ hyperdriveKey: string;
159
+ hyperbeeKey: string;
160
+ expectedSize: number;
161
+ sha256Checksum: string;
162
+ addon: "llm" | "whisper" | "embeddings" | "nmt" | "vad" | "tts";
163
+ isCached: boolean;
164
+ isLoaded: boolean;
165
+ cacheFiles: {
166
+ filename: string;
167
+ path: string;
168
+ expectedSize: number;
169
+ sha256Checksum: string;
170
+ isCached: boolean;
171
+ actualSize?: number | undefined;
172
+ cachedAt?: Date | undefined;
173
+ }[];
174
+ actualSize?: number | undefined;
175
+ cachedAt?: Date | undefined;
176
+ loadedInstances?: {
177
+ registryId: string;
178
+ loadedAt: Date;
179
+ config?: unknown;
180
+ }[] | undefined;
181
+ };
113
182
  }, void, any>;
114
183
  export declare function getRPC(): {
115
184
  request(): {
@@ -1,4 +1,5 @@
1
1
  import { handlers } from "../../server/rpc/handlers/index.js";
2
+ import { RPCNoHandlerError, RPCRequestNotSentError, } from "../../utils/errors-client.js";
2
3
  // Get the handler for a request type
3
4
  const getHandler = (type) => {
4
5
  const handler = handlers[type];
@@ -10,13 +11,13 @@ export async function send(request) {
10
11
  }
11
12
  const handler = getHandler(request.type);
12
13
  if (!handler)
13
- throw new Error(`No handler function for ${request.type}`);
14
+ throw new RPCNoHandlerError(request.type);
14
15
  return (await handler(request));
15
16
  }
16
17
  export async function* stream(request) {
17
18
  const handler = getHandler(request.type);
18
19
  if (!handler)
19
- throw new Error(`No handler function for ${request.type}`);
20
+ throw new RPCNoHandlerError(request.type);
20
21
  // Special handling for loadModel with progress
21
22
  if (request.type === "loadModel" &&
22
23
  "withProgress" in request &&
@@ -94,14 +95,14 @@ const createMockRPCRequest = () => {
94
95
  },
95
96
  async reply() {
96
97
  if (!requestData) {
97
- throw new Error("No request data - call send() first");
98
+ throw new RPCRequestNotSentError();
98
99
  }
99
100
  const response = await send(requestData);
100
101
  return Buffer.from(JSON.stringify(response));
101
102
  },
102
103
  async *createResponseStream() {
103
104
  if (!requestData) {
104
- throw new Error("No request data - call send() first");
105
+ throw new RPCRequestNotSentError();
105
106
  }
106
107
  for await (const response of stream(requestData)) {
107
108
  yield Buffer.from(JSON.stringify(response) + "\n");
@@ -23,10 +23,10 @@ else {
23
23
  WORKER_PATH = path.resolve(cwd, "dist/server/worker.js");
24
24
  }
25
25
  const SOCKET_PATH = path.join(os.tmpdir(), `qvac-worker-${process.pid}.sock`);
26
- export function getRPC() {
26
+ export async function getRPC() {
27
27
  if (rpcInstance) {
28
28
  console.log("returning cached bare rpc");
29
- return Promise.resolve(rpcInstance);
29
+ return rpcInstance;
30
30
  }
31
31
  console.log("initRPC for bare runtime with socket:", SOCKET_PATH);
32
32
  // Start IPC server (Unix socket)
@@ -71,7 +71,11 @@ export function getRPC() {
71
71
  });
72
72
  });
73
73
  });
74
- return serverPromise;
74
+ // Wait for RPC to initialize, then replay config
75
+ const rpc = await serverPromise;
76
+ const { replayConfigIfCached } = await import("../init-hooks.js");
77
+ await replayConfigIfCached(rpc);
78
+ return rpc;
75
79
  }
76
80
  // Clean up function
77
81
  export const cleanup = () => {
@@ -1,3 +1,4 @@
1
1
  import RPC from "bare-rpc";
2
2
  export declare const getRPC: () => Promise<RPC>;
3
+ export declare const close: () => void;
3
4
  //# sourceMappingURL=expo-rpc-client.d.ts.map
@@ -1,4 +1,5 @@
1
1
  import RPC from "bare-rpc";
2
+ import { RPCConnectionFailedError } from "../../utils/errors-client.js";
2
3
  let rpcInstance = null;
3
4
  let rpcPromise = null;
4
5
  console.log("EXPO RPC Client bundle");
@@ -28,7 +29,7 @@ export const getRPC = async () => {
28
29
  `Add '@qvac/sdk/expo-plugin' to your app.json plugins array. ` +
29
30
  `Error: ${String(error)}`;
30
31
  console.error(message);
31
- throw new Error(message);
32
+ throw new RPCConnectionFailedError(message, error instanceof Error ? error : undefined);
32
33
  }
33
34
  worklet.start("worker.bundle", mobileBundle, [
34
35
  // Normalize arg number across platforms
@@ -42,6 +43,8 @@ export const getRPC = async () => {
42
43
  rpcInstance = new RPC(worklet.IPC, () => {
43
44
  // Use this for async callbacks
44
45
  });
46
+ const { replayConfigIfCached } = await import("../init-hooks.js");
47
+ await replayConfigIfCached(rpcInstance);
45
48
  return rpcInstance;
46
49
  })();
47
50
  try {
@@ -55,3 +58,8 @@ export const getRPC = async () => {
55
58
  rpcPromise = null;
56
59
  }
57
60
  };
61
+ export const close = () => {
62
+ console.log("🧹 Closing RPC client (Expo)");
63
+ rpcInstance = null;
64
+ rpcPromise = null;
65
+ };
@@ -5,5 +5,5 @@ export declare function getRPC(): {
5
5
  createResponseStream: () => AsyncGenerator<unknown, void, unknown>;
6
6
  };
7
7
  };
8
- export declare const cleanup: () => void;
8
+ export declare const close: () => void;
9
9
  //# sourceMappingURL=node-rpc-client.d.ts.map
@@ -4,11 +4,13 @@ import { createServer } from "node:net";
4
4
  import os from "node:os";
5
5
  import path from "node:path";
6
6
  import { fileURLToPath } from "node:url";
7
+ import { RPCRequestNotSentError } from "../../utils/errors-client.js";
7
8
  const __filename = fileURLToPath(import.meta.url);
8
9
  const __dirname = path.dirname(__filename);
9
10
  let rpcInstance = null;
10
11
  let rpcPromise = null;
11
12
  let bareWorkerProc = null;
13
+ let ipcServer = null;
12
14
  // Smart path resolution for worker
13
15
  let WORKER_PATH;
14
16
  if (__dirname.includes("/dist/") || __dirname.includes("\\dist\\")) {
@@ -29,12 +31,12 @@ async function ensureRPC() {
29
31
  if (rpcPromise)
30
32
  return rpcPromise;
31
33
  rpcPromise = new Promise((resolve, reject) => {
32
- const server = createServer((socket) => {
34
+ ipcServer = createServer((socket) => {
33
35
  rpcInstance = new RPC(socket, () => { });
34
36
  resolve(rpcInstance);
35
37
  });
36
- server.on("error", reject);
37
- server.listen(SOCKET_PATH, () => {
38
+ ipcServer.on("error", reject);
39
+ ipcServer.listen(SOCKET_PATH, () => {
38
40
  bareWorkerProc = spawn("bare", {
39
41
  args: [
40
42
  WORKER_PATH,
@@ -47,7 +49,10 @@ async function ensureRPC() {
47
49
  });
48
50
  });
49
51
  });
50
- return rpcPromise;
52
+ const rpc = await rpcPromise;
53
+ const { replayConfigIfCached } = await import("../init-hooks.js");
54
+ await replayConfigIfCached(rpc);
55
+ return rpc;
51
56
  }
52
57
  const mockRPC = {
53
58
  request: (command) => {
@@ -58,7 +63,7 @@ const mockRPC = {
58
63
  },
59
64
  reply: async (encoding) => {
60
65
  if (!sentData) {
61
- throw new Error("Must call send() before reply()");
66
+ throw new RPCRequestNotSentError();
62
67
  }
63
68
  const rpc = await ensureRPC();
64
69
  const req = rpc.request(command);
@@ -70,7 +75,7 @@ const mockRPC = {
70
75
  },
71
76
  createResponseStream: async function* () {
72
77
  if (!sentData) {
73
- throw new Error("Must call send() before createResponseStream()");
78
+ throw new RPCRequestNotSentError();
74
79
  }
75
80
  const rpc = await ensureRPC();
76
81
  const req = rpc.request(command);
@@ -88,12 +93,20 @@ const mockRPC = {
88
93
  export function getRPC() {
89
94
  return mockRPC;
90
95
  }
91
- export const cleanup = () => {
92
- console.log("🧹 Cleaning up RPC client");
96
+ export const close = () => {
97
+ console.log("🧹 Closing RPC client");
93
98
  if (bareWorkerProc) {
94
99
  console.log("🐻🔫 Killing bare worker process");
95
100
  bareWorkerProc.kill("SIGTERM");
101
+ bareWorkerProc = null;
96
102
  }
103
+ if (ipcServer) {
104
+ console.log("🔌 Closing IPC server");
105
+ ipcServer.close();
106
+ ipcServer = null;
107
+ }
108
+ rpcInstance = null;
109
+ rpcPromise = null;
97
110
  };
98
111
  // Register cleanup handlers for the parent process
99
- process.once("exit", cleanup);
112
+ process.once("exit", close);
@@ -2,4 +2,5 @@ import type RPC from "bare-rpc";
2
2
  import { type Request, type Response, type RPCOptions } from "../../schemas/index";
3
3
  export declare function send<T extends Request>(request: T, rpc?: RPC, options?: RPCOptions): Promise<Response>;
4
4
  export declare function stream<T extends Request>(request: T, rpc?: RPC, options?: RPCOptions): AsyncGenerator<Response>;
5
+ export declare function close(): Promise<void>;
5
6
  //# sourceMappingURL=rpc-client.d.ts.map
@@ -53,7 +53,8 @@ export async function send(request, rpc, options) {
53
53
  console.log("RPC Client sending:", {
54
54
  type: request.type,
55
55
  modelId: request.modelId,
56
- audioChunkSize: request.audioChunk.length,
56
+ audioChunkType: request.audioChunk.type,
57
+ audioChunkSize: request.audioChunk.value.length,
57
58
  });
58
59
  }
59
60
  else {
@@ -94,3 +95,21 @@ export async function* stream(request, rpc, options = {}) {
94
95
  }
95
96
  }
96
97
  }
98
+ export async function close() {
99
+ if (!rpcInstance)
100
+ return;
101
+ const isRN = typeof navigator !== "undefined" && navigator.product === "ReactNative";
102
+ const isBare = typeof globalThis !== "undefined" && "Bare" in globalThis;
103
+ if (isRN) {
104
+ const mod = (await import("./expo-rpc-client.js"));
105
+ mod.close();
106
+ }
107
+ else if (isBare) {
108
+ // Bare runs in-process (no separate worker), so no cleanup needed
109
+ }
110
+ else {
111
+ const mod = (await import("./node-rpc-client.js"));
112
+ mod.close();
113
+ }
114
+ rpcInstance = null;
115
+ }
@@ -1,3 +1,2 @@
1
- export declare const FORMATS_NEEDING_DECODE: readonly [".mp3", ".m4a", ".ogg", ".flac", ".aac", ".wav"];
2
- export declare const SUPPORTED_AUDIO_FORMATS: readonly [".mp3", ".m4a", ".ogg", ".wav", ".flac", ".aac", ".raw"];
1
+ export { FORMATS_NEEDING_DECODE, SUPPORTED_AUDIO_FORMATS, } from "@qvac/decoder-audio/constants";
3
2
  //# sourceMappingURL=audio.d.ts.map
@@ -1,17 +1 @@
1
- export const FORMATS_NEEDING_DECODE = [
2
- ".mp3",
3
- ".m4a",
4
- ".ogg",
5
- ".flac",
6
- ".aac",
7
- ".wav",
8
- ];
9
- export const SUPPORTED_AUDIO_FORMATS = [
10
- ".mp3",
11
- ".m4a",
12
- ".ogg",
13
- ".wav",
14
- ".flac",
15
- ".aac",
16
- ".raw",
17
- ];
1
+ export { FORMATS_NEEDING_DECODE, SUPPORTED_AUDIO_FORMATS, } from "@qvac/decoder-audio/constants.js";
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cache-management.d.ts.map
@@ -0,0 +1,97 @@
1
+ import { WHISPER_TINY } from "../models/hyperdrive/index.js";
2
+ import { downloadAsset, getModelInfo, loadModel, unloadModel } from "..";
3
+ const printModelStatus = (info, label) => {
4
+ console.log(`\n${label}`);
5
+ console.log(` Model Name: ${info.name}`);
6
+ console.log(` Model ID: ${info.modelId}`);
7
+ console.log(` Hyperdrive Key: ${info.hyperdriveKey.substring(0, 16)}...`);
8
+ console.log(` Expected Size: ${(info.expectedSize / 1024 / 1024).toFixed(2)} MB`);
9
+ console.log(` Addon: ${info.addon}`);
10
+ console.log(` Cache Files: ${info.cacheFiles.length}`);
11
+ console.log(` Is Cached: ${info.isCached ? "✅" : "❌"}`);
12
+ console.log(` Is Loaded: ${info.isLoaded ? "✅" : "❌"}`);
13
+ if (info.isCached) {
14
+ if (info.cacheFiles.length === 1) {
15
+ console.log(` Cache Path: ${info.cacheFiles[0]?.path}`);
16
+ }
17
+ else {
18
+ const cachedFiles = info.cacheFiles.filter((f) => f.isCached).length;
19
+ console.log(` Cached: ${cachedFiles}/${info.cacheFiles.length}`);
20
+ }
21
+ console.log(` Actual Size: ${(info.actualSize / 1024 / 1024).toFixed(2)} MB`);
22
+ console.log(` Cached At: ${info.cachedAt?.toLocaleString()}`);
23
+ }
24
+ if (info.loadedInstances && info.loadedInstances.length > 0) {
25
+ console.log(` Loaded Instances: ${info.loadedInstances.length}`);
26
+ info.loadedInstances.forEach((instance, i) => {
27
+ console.log(` ${i + 1}. Registry ID: ${instance.registryId}`);
28
+ console.log(` Loaded At: ${instance.loadedAt.toLocaleString()}`);
29
+ });
30
+ }
31
+ };
32
+ try {
33
+ console.log("=== Model Cache Management Demo ===");
34
+ // 1. Check initial status
35
+ console.log("\n1️⃣ INITIAL STATUS CHECK");
36
+ const initialInfo = await getModelInfo(WHISPER_TINY);
37
+ printModelStatus(initialInfo, "Initial Status:");
38
+ // 2. Download if not cached
39
+ if (!initialInfo.isCached) {
40
+ console.log("\n2️⃣ DOWNLOADING MODEL (not cached)");
41
+ console.log(" Downloading from hyperdrive...");
42
+ await downloadAsset({ assetSrc: WHISPER_TINY });
43
+ console.log(" ✅ Download complete!");
44
+ const afterDownload = await getModelInfo(WHISPER_TINY);
45
+ printModelStatus(afterDownload, "Status After Download:");
46
+ }
47
+ else {
48
+ console.log("\n2️⃣ MODEL ALREADY CACHED");
49
+ console.log(" Skipping download...");
50
+ }
51
+ // 3. Load if not loaded
52
+ console.log("\n3️⃣ LOADING MODEL INTO MEMORY");
53
+ const beforeLoad = await getModelInfo(WHISPER_TINY);
54
+ let modelId;
55
+ if (!beforeLoad.isLoaded) {
56
+ console.log(" Loading model into memory...");
57
+ modelId = await loadModel({
58
+ modelSrc: WHISPER_TINY,
59
+ modelType: "whisper",
60
+ });
61
+ console.log(` ✅ Model loaded! ID: ${modelId}`);
62
+ const afterLoad = await getModelInfo(WHISPER_TINY);
63
+ printModelStatus(afterLoad, "Status After Load:");
64
+ }
65
+ else {
66
+ console.log(" Model already loaded!");
67
+ const instances = beforeLoad.loadedInstances;
68
+ if (!instances || instances.length === 0) {
69
+ throw new Error("Model is loaded but no instances found");
70
+ }
71
+ const firstInstance = instances[0];
72
+ if (!firstInstance) {
73
+ throw new Error("First instance is undefined");
74
+ }
75
+ modelId = firstInstance.registryId;
76
+ console.log(` Using existing model ID: ${modelId}`);
77
+ }
78
+ // 4. Demonstrate unload
79
+ console.log("\n4️⃣ UNLOADING MODEL");
80
+ console.log(" Unloading model from memory...");
81
+ await unloadModel({ modelId });
82
+ console.log(" ✅ Model unloaded!");
83
+ const afterUnload = await getModelInfo(WHISPER_TINY);
84
+ printModelStatus(afterUnload, "Status After Unload:");
85
+ // 5. Summary
86
+ console.log("\n5️⃣ SUMMARY");
87
+ console.log(" ✅ Model Info API works correctly");
88
+ console.log(" ✅ Cache status tracked accurately");
89
+ console.log(" ✅ Loaded status reflects memory state");
90
+ console.log(" ✅ All operations completed successfully");
91
+ console.log("\n=== Demo Complete ===\n");
92
+ process.exit(0);
93
+ }
94
+ catch (error) {
95
+ console.error("❌ Error:", error);
96
+ process.exit(1);
97
+ }
@@ -1,4 +1,4 @@
1
- import { completion, LLAMA_3_2_1B_INST_Q4_0, loadModel } from "@qvac/sdk";
1
+ import { completion, LLAMA_3_2_1B_INST_Q4_0, loadModel, close, } from "@qvac/sdk";
2
2
  // Topic hex (required)
3
3
  const topicHex = process.argv[2];
4
4
  if (!topicHex) {
@@ -48,7 +48,7 @@ try {
48
48
  }
49
49
  console.log("🔍 Stats:", await response.stats);
50
50
  console.log("\n🎯 Delegation infrastructure working! Server correctly detected and routed the delegated request.");
51
- process.exit(0);
51
+ void close();
52
52
  }
53
53
  catch (error) {
54
54
  console.error("❌ Error:", error);
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=download-with-blind-relays.d.ts.map
@@ -0,0 +1,48 @@
1
+ import { downloadAsset, setConfig, close, LLAMA_3_2_1B_INST_Q4_0, } from "@qvac/sdk";
2
+ // ⚠️ IMPORTANT: These are MOCK relay public keys for demonstration only
3
+ // To use blind relays in production:
4
+ // 1. Run your own relay servers using hyperswarm
5
+ // 2. Use well-known public relays from trusted sources
6
+ // 3. Never rely on example/mock keys for production use
7
+ const MOCK_RELAY_PUBLIC_KEYS = [
8
+ "0000000000000000000000000000000000000000000000000000000000000001",
9
+ "0000000000000000000000000000000000000000000000000000000000000002",
10
+ "0000000000000000000000000000000000000000000000000000000000000003",
11
+ ];
12
+ console.log(`🚀 Download with Blind Relays Example`);
13
+ console.log(`${"=".repeat(60)}\n`);
14
+ console.log(`⚠️ Using MOCK relay keys - replace with real relays!\n`);
15
+ try {
16
+ // Configure SDK to use blind relays for improved connectivity
17
+ // Blind relays help with NAT traversal and firewall bypassing
18
+ await setConfig({
19
+ swarmRelays: MOCK_RELAY_PUBLIC_KEYS,
20
+ });
21
+ console.log(`✅ Configured ${MOCK_RELAY_PUBLIC_KEYS.length} blind relays`);
22
+ console.log(`📥 Starting model download from Hyperdrive...\n`);
23
+ const startTime = Date.now();
24
+ // Download model with progress tracking
25
+ await downloadAsset({
26
+ assetSrc: LLAMA_3_2_1B_INST_Q4_0,
27
+ onProgress: (progress) => {
28
+ const downloadedMB = (progress.downloaded / 1024 / 1024).toFixed(2);
29
+ const totalMB = (progress.total / 1024 / 1024).toFixed(2);
30
+ const percentage = progress.percentage.toFixed(1);
31
+ const elapsedSeconds = (Date.now() - startTime) / 1000;
32
+ const speedMBps = (progress.downloaded /
33
+ 1024 /
34
+ 1024 /
35
+ elapsedSeconds).toFixed(2);
36
+ console.log(`📊 ${percentage}% - ${downloadedMB}MB / ${totalMB}MB (${speedMBps} MB/s)`);
37
+ },
38
+ });
39
+ console.log(`\n✅ Model downloaded successfully using blind relays!`);
40
+ console.log(`Blind relays helped establish peer connections through NAT/firewalls\n`);
41
+ await close();
42
+ }
43
+ catch (error) {
44
+ console.error("❌ Error:", error);
45
+ console.log(`\nIf download failed, ensure you're using valid relay public keys`);
46
+ console.log(` Mock keys in this example won't work in practice!`);
47
+ process.exit(1);
48
+ }
@@ -1,4 +1,4 @@
1
- import { downloadAsset, cancel, LLAMA_3_2_1B_INST_Q4_0 } from "@qvac/sdk";
1
+ import { cancel, close, downloadAsset, LLAMA_3_2_1B_INST_Q4_0, } from "@qvac/sdk";
2
2
  console.log(`🚀 Starting download with pause/resume example`);
3
3
  console.log(`\n💡 Press Ctrl+C to pause the download (it will resume on restart)\n`);
4
4
  let modelId;
@@ -31,13 +31,12 @@ try {
31
31
  });
32
32
  console.log(`\n✅ Model downloaded successfully! Model ID: ${modelId}`);
33
33
  console.log("🎯 Download completed without interruption");
34
- // Clean up
35
- process.exit(0);
34
+ void close();
36
35
  }
37
36
  catch (error) {
38
37
  if (error instanceof Error && error.message.includes("cancelled")) {
39
38
  console.log("✅ Download was successfully cancelled");
40
- process.exit(0);
39
+ void close();
41
40
  }
42
41
  else {
43
42
  console.error("❌ Error:", error);
@@ -11,7 +11,6 @@ try {
11
11
  console.log("Embedding (first 20 elements)", embedding.slice(0, 20));
12
12
  console.log("Embeddings length", embedding.length);
13
13
  await unloadModel({ modelId, clearStorage: false });
14
- process.exit(0);
15
14
  }
16
15
  catch (error) {
17
16
  console.error("❌ Error:", error);
@@ -80,7 +80,6 @@ try {
80
80
  console.log(" - Privacy → Clear conversation history");
81
81
  console.log(" - App reset → Delete all caches with { all: true }");
82
82
  await unloadModel({ modelId, clearStorage: false });
83
- process.exit(0);
84
83
  }
85
84
  catch (error) {
86
85
  console.error("❌ Error:", error);
@@ -79,7 +79,6 @@ try {
79
79
  console.log(" - Different cache keys provide complete isolation between sessions");
80
80
  await deleteCache({ all: true });
81
81
  await unloadModel({ modelId, clearStorage: false });
82
- process.exit(0);
83
82
  }
84
83
  catch (error) {
85
84
  console.error("❌ Error:", error);
@@ -66,7 +66,6 @@ try {
66
66
  console.log(`\n⏱️ Non-cached completion stats: ${JSON.stringify(stats3)}\n`);
67
67
  console.log("✅ KV Cache test completed!");
68
68
  await unloadModel({ modelId, clearStorage: false });
69
- process.exit(0);
70
69
  }
71
70
  catch (error) {
72
71
  console.error("❌ Error:", error);
@@ -54,7 +54,6 @@ try {
54
54
  // Show user where logs were saved
55
55
  console.log(`\n📄 All logs (including model internals) saved to: ${logFile}`);
56
56
  console.log("You can inspect the file to see detailed model operation logs!");
57
- process.exit(0);
58
57
  }
59
58
  catch (error) {
60
59
  console.error("❌ Error:", error);
@@ -1,4 +1,4 @@
1
- import { completion, loadModel } from "@qvac/sdk";
1
+ import { completion, loadModel, unloadModel } from "@qvac/sdk";
2
2
  // Get GGUF file path from command line arguments
3
3
  const ggufPath = process.argv[2];
4
4
  if (!ggufPath) {
@@ -32,7 +32,7 @@ try {
32
32
  const stats = await result.stats;
33
33
  console.log("\n📊 Performance Stats:", stats);
34
34
  console.log("\n\n🎉 Completed!");
35
- process.exit(0);
35
+ await unloadModel({ modelId, clearStorage: false });
36
36
  }
37
37
  catch (error) {
38
38
  console.error("❌ Error:", error);
@@ -33,7 +33,6 @@ try {
33
33
  console.log("\n📊 Performance Stats:", stats);
34
34
  console.log("\n\n🎉 Completed!");
35
35
  await unloadModel({ modelId, clearStorage: false });
36
- process.exit(0);
37
36
  }
38
37
  catch (error) {
39
38
  console.error("❌ Error:", error);