@qvac/sdk 0.4.1 → 0.5.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 (179) hide show
  1. package/README.md +328 -200
  2. package/dist/client/api/completion-stream.d.ts +15 -5
  3. package/dist/client/api/completion-stream.js +50 -14
  4. package/dist/client/api/embed.d.ts +17 -3
  5. package/dist/client/api/embed.js +0 -8
  6. package/dist/client/api/get-model-info.d.ts +1 -1
  7. package/dist/client/api/index.d.ts +0 -1
  8. package/dist/client/api/index.js +0 -1
  9. package/dist/client/api/load-model.d.ts +37 -11
  10. package/dist/client/api/load-model.js +29 -117
  11. package/dist/client/api/logging-stream.d.ts +6 -3
  12. package/dist/client/api/logging-stream.js +6 -3
  13. package/dist/client/api/unload-model.js +5 -2
  14. package/dist/client/config-loader/config-utils.d.ts +5 -0
  15. package/dist/client/config-loader/config-utils.js +20 -0
  16. package/dist/client/config-loader/resolve-config.bare.d.ts +9 -0
  17. package/dist/client/config-loader/resolve-config.bare.js +87 -0
  18. package/dist/client/config-loader/resolve-config.expo.d.ts +11 -0
  19. package/dist/client/config-loader/resolve-config.expo.js +62 -0
  20. package/dist/client/config-loader/resolve-config.node.d.ts +9 -0
  21. package/dist/client/config-loader/resolve-config.node.js +118 -0
  22. package/dist/client/init-hooks.d.ts +17 -3
  23. package/dist/client/init-hooks.js +37 -18
  24. package/dist/client/logging-stream-registry.d.ts +1 -1
  25. package/dist/client/logging-stream-registry.js +14 -13
  26. package/dist/client/rpc/bare-client.d.ts +10 -14
  27. package/dist/client/rpc/bare-client.js +28 -2
  28. package/dist/client/rpc/bare-rpc-client.d.ts +1 -1
  29. package/dist/client/rpc/bare-rpc-client.js +16 -13
  30. package/dist/client/rpc/expo-rpc-client.d.ts +2 -2
  31. package/dist/client/rpc/expo-rpc-client.js +15 -12
  32. package/dist/client/rpc/node-rpc-client.d.ts +1 -1
  33. package/dist/client/rpc/node-rpc-client.js +10 -7
  34. package/dist/client/rpc/rpc-client.js +16 -15
  35. package/dist/examples/config/config-path.d.ts +8 -0
  36. package/dist/examples/config/config-path.js +13 -0
  37. package/dist/examples/config-reload.d.ts +2 -0
  38. package/dist/examples/config-reload.js +49 -0
  39. package/dist/examples/download-with-blind-relays.js +20 -20
  40. package/dist/examples/embed-hyperdrive.js +35 -3
  41. package/dist/examples/kv-cache-cleanup.js +1 -1
  42. package/dist/examples/kv-cache-custom-key.js +1 -1
  43. package/dist/examples/kv-cache-example.js +1 -1
  44. package/dist/examples/llamacpp-hyperdrive.js +1 -1
  45. package/dist/examples/llamacpp-sharded.js +1 -1
  46. package/dist/examples/logging-file-transport.d.ts +2 -0
  47. package/dist/examples/{llamacpp-file-logging.js → logging-file-transport.js} +3 -7
  48. package/dist/examples/logging-streaming.d.ts +2 -0
  49. package/dist/examples/logging-streaming.js +75 -0
  50. package/dist/examples/mcp-websearch.d.ts +13 -0
  51. package/dist/examples/mcp-websearch.js +176 -0
  52. package/dist/index.d.ts +4 -4
  53. package/dist/index.js +2 -2
  54. package/dist/logging/addon.d.ts +6 -0
  55. package/dist/logging/addon.js +59 -0
  56. package/dist/logging/base-logger.js +24 -14
  57. package/dist/logging/client-logger.d.ts +3 -0
  58. package/dist/logging/client-logger.js +13 -0
  59. package/dist/logging/index.d.ts +6 -1
  60. package/dist/logging/index.js +6 -1
  61. package/dist/logging/logger.d.ts +0 -2
  62. package/dist/logging/logger.js +0 -3
  63. package/dist/logging/namespaces.d.ts +11 -0
  64. package/dist/logging/namespaces.js +11 -0
  65. package/dist/logging/registry.d.ts +26 -0
  66. package/dist/logging/registry.js +36 -0
  67. package/dist/logging/server-logger.d.ts +3 -0
  68. package/dist/logging/server-logger.js +16 -0
  69. package/dist/logging/stream-logger.d.ts +1 -1
  70. package/dist/logging/stream-logger.js +6 -3
  71. package/dist/logging/types.d.ts +2 -0
  72. package/dist/models/hyperdrive/models.d.ts +789 -51
  73. package/dist/models/hyperdrive/models.js +979 -200
  74. package/dist/schemas/common.d.ts +86 -23
  75. package/dist/schemas/common.js +0 -3
  76. package/dist/schemas/download-asset.d.ts +5 -5
  77. package/dist/schemas/embed.d.ts +3 -3
  78. package/dist/schemas/embed.js +9 -2
  79. package/dist/schemas/get-model-info.d.ts +2 -2
  80. package/dist/schemas/index.d.ts +5 -1
  81. package/dist/schemas/index.js +5 -1
  82. package/dist/schemas/json-schema.d.ts +16 -0
  83. package/dist/schemas/json-schema.js +2 -0
  84. package/dist/schemas/llamacpp-config.d.ts +5 -4
  85. package/dist/schemas/llamacpp-config.js +7 -5
  86. package/dist/schemas/load-model.d.ts +931 -211
  87. package/dist/schemas/load-model.js +7 -1
  88. package/dist/schemas/logging-stream.d.ts +10 -3
  89. package/dist/schemas/logging-stream.js +4 -3
  90. package/dist/schemas/mcp-adapter.d.ts +47 -0
  91. package/dist/schemas/mcp-adapter.js +1 -0
  92. package/dist/schemas/model-src-utils.d.ts +8 -6
  93. package/dist/schemas/model-src-utils.js +8 -3
  94. package/dist/schemas/reload-config.d.ts +344 -0
  95. package/dist/schemas/reload-config.js +42 -0
  96. package/dist/schemas/sdk-config.d.ts +22 -0
  97. package/dist/schemas/sdk-config.js +33 -0
  98. package/dist/schemas/sdk-errors-client.d.ts +4 -0
  99. package/dist/schemas/sdk-errors-client.js +20 -0
  100. package/dist/schemas/sdk-errors-server.d.ts +3 -0
  101. package/dist/schemas/sdk-errors-server.js +15 -0
  102. package/dist/schemas/tools.d.ts +3 -0
  103. package/dist/schemas/translation-config.d.ts +81 -0
  104. package/dist/schemas/translation-config.js +3 -4
  105. package/dist/schemas/whispercpp-config.d.ts +9 -1
  106. package/dist/schemas/whispercpp-config.js +2 -1
  107. package/dist/server/bare/addons/llamacpp/create-model.js +13 -4
  108. package/dist/server/bare/addons/llamacpp/handlers/embed.d.ts +9 -1
  109. package/dist/server/bare/addons/llamacpp/handlers/embed.js +18 -4
  110. package/dist/server/bare/addons/llamacpp/kv-cache-utils.js +6 -4
  111. package/dist/server/bare/addons/load-model.js +10 -4
  112. package/dist/server/bare/addons/unload-model.js +6 -3
  113. package/dist/server/bare/addons/whispercpp/handlers/transcribe-stream.js +56 -37
  114. package/dist/server/bare/delegate-rpc-client.js +12 -10
  115. package/dist/server/bare/hyperswarm.js +7 -5
  116. package/dist/server/bare/rag-hyperdb/rag-manager.js +3 -1
  117. package/dist/server/bare/registry/config-registry.d.ts +13 -4
  118. package/dist/server/bare/registry/config-registry.js +42 -10
  119. package/dist/server/bare/registry/logging-stream-registry.d.ts +24 -7
  120. package/dist/server/bare/registry/logging-stream-registry.js +99 -20
  121. package/dist/server/bare/registry/model-registry.d.ts +3 -0
  122. package/dist/server/bare/registry/model-registry.js +9 -6
  123. package/dist/server/rpc/create-server.js +5 -3
  124. package/dist/server/rpc/handle-request.js +30 -16
  125. package/dist/server/rpc/handlers/cancelHandler.js +3 -1
  126. package/dist/server/rpc/handlers/completion-stream-delegated.js +4 -2
  127. package/dist/server/rpc/handlers/delete-cache.js +3 -1
  128. package/dist/server/rpc/handlers/download-asset.js +3 -1
  129. package/dist/server/rpc/handlers/embed.js +3 -1
  130. package/dist/server/rpc/handlers/index.d.ts +0 -1
  131. package/dist/server/rpc/handlers/index.js +0 -2
  132. package/dist/server/rpc/handlers/load-model/download-manager.js +4 -2
  133. package/dist/server/rpc/handlers/load-model/http.js +20 -18
  134. package/dist/server/rpc/handlers/load-model/hyperdrive.js +21 -19
  135. package/dist/server/rpc/handlers/load-model/resolve.js +7 -5
  136. package/dist/server/rpc/handlers/load-model-delegated.d.ts +2 -2
  137. package/dist/server/rpc/handlers/load-model-delegated.js +10 -8
  138. package/dist/server/rpc/handlers/load-model.js +55 -3
  139. package/dist/server/rpc/handlers/logging-stream.js +4 -4
  140. package/dist/server/rpc/handlers/provideHandler/connection.js +12 -10
  141. package/dist/server/rpc/handlers/provideHandler/handler.js +18 -16
  142. package/dist/server/rpc/handlers/provideHandler/proxy.js +8 -6
  143. package/dist/server/rpc/handlers/rag.js +3 -1
  144. package/dist/server/rpc/handlers/stopProvideHandler.js +3 -1
  145. package/dist/server/rpc/handlers/transcribe-stream.js +3 -1
  146. package/dist/server/rpc/handlers/translate.js +3 -1
  147. package/dist/server/rpc/handlers/unload-model.js +4 -2
  148. package/dist/server/utils/audio/decoder.d.ts +2 -1
  149. package/dist/server/utils/audio/decoder.js +48 -11
  150. package/dist/server/utils/cache.js +7 -5
  151. package/dist/server/utils/config-transform.d.ts +3 -0
  152. package/dist/server/utils/config-transform.js +21 -0
  153. package/dist/server/utils/index.d.ts +1 -0
  154. package/dist/server/utils/index.js +1 -0
  155. package/dist/server/worker.js +41 -16
  156. package/dist/utils/errors-client.d.ts +12 -0
  157. package/dist/utils/errors-client.js +20 -0
  158. package/dist/utils/errors-server.d.ts +9 -0
  159. package/dist/utils/errors-server.js +16 -0
  160. package/dist/utils/getProcessSafe.d.ts +7 -0
  161. package/dist/utils/getProcessSafe.js +17 -0
  162. package/dist/utils/mcp-adapter.d.ts +12 -0
  163. package/dist/utils/mcp-adapter.js +103 -0
  164. package/dist/utils/object.d.ts +2 -0
  165. package/dist/utils/object.js +3 -0
  166. package/dist/utils/runtime.d.ts +30 -0
  167. package/dist/utils/runtime.js +48 -0
  168. package/dist/utils/tool-helpers.d.ts +10 -2
  169. package/dist/utils/tool-helpers.js +24 -11
  170. package/package.json +46 -33
  171. package/dist/client/api/set-config.d.ts +0 -7
  172. package/dist/client/api/set-config.js +0 -20
  173. package/dist/client/config-manager.d.ts +0 -4
  174. package/dist/client/config-manager.js +0 -8
  175. package/dist/examples/llamacpp-file-logging.d.ts +0 -2
  176. package/dist/schemas/set-config.d.ts +0 -21
  177. package/dist/schemas/set-config.js +0 -14
  178. package/dist/server/rpc/handlers/set-config.d.ts +0 -3
  179. package/dist/server/rpc/handlers/set-config.js +0 -18
@@ -3,13 +3,15 @@ import Hyperswarm from "hyperswarm";
3
3
  import crypto from "bare-crypto";
4
4
  import { envSchema } from "../../schemas/provide.js";
5
5
  import { getSDKConfig } from "./registry/config-registry.js";
6
+ import { getServerLogger } from "../../logging/index.js";
7
+ const logger = getServerLogger();
6
8
  function getHyperswarmSeedBuffer() {
7
9
  const parsedEnv = envSchema.safeParse(process.env);
8
10
  if (parsedEnv.success) {
9
11
  return Buffer.from(parsedEnv.data.QVAC_HYPERSWARM_SEED, "hex");
10
12
  }
11
13
  else {
12
- console.log(`🎲 No seed provided, generating random seed (provider will have random identity)`);
14
+ logger.info(`🎲 No seed provided, generating random seed (provider will have random identity)`);
13
15
  return crypto.randomBytes(32);
14
16
  }
15
17
  }
@@ -24,20 +26,20 @@ function createFirewallFunction(config) {
24
26
  if (mode === "allow") {
25
27
  const allowed = publicKeySet.has(remoteKeyHex);
26
28
  if (!allowed) {
27
- console.log(`🚫 Firewall: Denied connection from ${remoteKeyHex.substring(0, 16)}... (not in allowlist)`);
29
+ logger.debug(`🚫 Firewall: Denied connection from ${remoteKeyHex.substring(0, 16)}... (not in allowlist)`);
28
30
  }
29
31
  else {
30
- console.log(`✅ Firewall: Allowed connection from ${remoteKeyHex.substring(0, 16)}... (in allowlist)`);
32
+ logger.debug(`✅ Firewall: Allowed connection from ${remoteKeyHex.substring(0, 16)}... (in allowlist)`);
31
33
  }
32
34
  return !allowed;
33
35
  }
34
36
  else {
35
37
  const denied = publicKeySet.has(remoteKeyHex);
36
38
  if (denied) {
37
- console.log(`🚫 Firewall: Denied connection from ${remoteKeyHex.substring(0, 16)}... (in denylist)`);
39
+ logger.debug(`🚫 Firewall: Denied connection from ${remoteKeyHex.substring(0, 16)}... (in denylist)`);
38
40
  }
39
41
  else {
40
- console.log(`✅ Firewall: Allowed connection from ${remoteKeyHex.substring(0, 16)}... (not in denylist)`);
42
+ logger.debug(`✅ Firewall: Allowed connection from ${remoteKeyHex.substring(0, 16)}... (not in denylist)`);
41
43
  }
42
44
  return denied;
43
45
  }
@@ -3,6 +3,8 @@ import Corestore from "corestore";
3
3
  import path from "bare-path";
4
4
  import { getEnv } from "../../worker.js";
5
5
  import { RAGWorkspaceModelMismatchError } from "../../../utils/errors-server.js";
6
+ import { getServerLogger } from "../../../logging/index.js";
7
+ const logger = getServerLogger();
6
8
  const ragInstances = new Map();
7
9
  const defaultWorkspace = "default";
8
10
  const getStorePath = (workspace) => {
@@ -59,6 +61,6 @@ export const closeAllRagInstances = async () => {
59
61
  await Promise.all(closures);
60
62
  }
61
63
  catch (error) {
62
- console.error("❌ Error during RAG cleanup:", error);
64
+ logger.error("❌ Error during RAG cleanup:", error);
63
65
  }
64
66
  };
@@ -1,5 +1,14 @@
1
- import type { SDKConfig } from "../../../schemas/index";
2
- export declare const setSDKConfig: (config: SDKConfig) => void;
3
- export declare const getSDKConfig: () => SDKConfig;
4
- export declare const getConfiguredCacheDir: () => string;
1
+ import type { QvacConfig } from "../../../schemas/index";
2
+ /**
3
+ * Sets the SDK configuration. This can only be called ONCE during initialization.
4
+ * After the first call, the config becomes immutable and any subsequent calls will throw.
5
+ *
6
+ * @param config - The configuration to set
7
+ * @throws {ConfigAlreadySetError} If config has already been set
8
+ * @throws {CacheDirNotAbsoluteError} If cacheDirectory is not an absolute path
9
+ * @throws {CacheDirNotWritableError} If cacheDirectory is not writable
10
+ */
11
+ export declare function setSDKConfig(config: QvacConfig): void;
12
+ export declare function getSDKConfig(): QvacConfig;
13
+ export declare function getConfiguredCacheDir(): string;
5
14
  //# sourceMappingURL=config-registry.d.ts.map
@@ -1,12 +1,30 @@
1
1
  import fs from "bare-fs";
2
2
  import path from "bare-path";
3
3
  import { getEnv } from "../../worker.js";
4
- import { CacheDirNotAbsoluteError, CacheDirNotWritableError, } from "../../../utils/errors-server.js";
4
+ import { CacheDirNotAbsoluteError, CacheDirNotWritableError, ConfigAlreadySetError, } from "../../../utils/errors-server.js";
5
+ import { getServerLogger, setGlobalConsoleOutput, setGlobalLogLevel, } from "../../../logging/index.js";
6
+ const logger = getServerLogger();
5
7
  const configRegistry = {
6
8
  cacheDirectory: undefined,
7
9
  swarmRelays: undefined,
10
+ loggerLevel: undefined,
11
+ loggerConsoleOutput: undefined,
8
12
  };
9
- export const setSDKConfig = (config) => {
13
+ let configIsSet = false;
14
+ /**
15
+ * Sets the SDK configuration. This can only be called ONCE during initialization.
16
+ * After the first call, the config becomes immutable and any subsequent calls will throw.
17
+ *
18
+ * @param config - The configuration to set
19
+ * @throws {ConfigAlreadySetError} If config has already been set
20
+ * @throws {CacheDirNotAbsoluteError} If cacheDirectory is not an absolute path
21
+ * @throws {CacheDirNotWritableError} If cacheDirectory is not writable
22
+ */
23
+ export function setSDKConfig(config) {
24
+ // Enforce immutability - config can only be set once
25
+ if (configIsSet) {
26
+ throw new ConfigAlreadySetError();
27
+ }
10
28
  if (config.cacheDirectory !== undefined && config.cacheDirectory !== null) {
11
29
  if (!path.isAbsolute(config.cacheDirectory)) {
12
30
  throw new CacheDirNotAbsoluteError();
@@ -21,19 +39,33 @@ export const setSDKConfig = (config) => {
21
39
  throw new CacheDirNotWritableError(config.cacheDirectory, error instanceof Error ? error.message : String(error), error);
22
40
  }
23
41
  configRegistry.cacheDirectory = config.cacheDirectory;
24
- console.log(`✅ Cache directory set to: ${config.cacheDirectory}`);
42
+ logger.info(`✅ Cache directory set to: ${config.cacheDirectory}`);
25
43
  }
26
44
  if (config.swarmRelays !== undefined && config.swarmRelays !== null) {
27
45
  configRegistry.swarmRelays = config.swarmRelays;
46
+ logger.info(`✅ Swarm relays configured: ${config.swarmRelays.length} relay(s)`);
28
47
  }
29
- };
30
- export const getSDKConfig = () => {
48
+ if (config.loggerLevel !== undefined && config.loggerLevel !== null) {
49
+ configRegistry.loggerLevel = config.loggerLevel;
50
+ setGlobalLogLevel(config.loggerLevel);
51
+ logger.info(`Log level set to: ${config.loggerLevel}`);
52
+ }
53
+ if (config.loggerConsoleOutput !== undefined &&
54
+ config.loggerConsoleOutput !== null) {
55
+ configRegistry.loggerConsoleOutput = config.loggerConsoleOutput;
56
+ setGlobalConsoleOutput(config.loggerConsoleOutput);
57
+ logger.info(`Console output ${config.loggerConsoleOutput ? "enabled" : "disabled"}`);
58
+ }
59
+ // Mark config as set - now it's immutable
60
+ configIsSet = true;
61
+ }
62
+ export function getSDKConfig() {
31
63
  return { ...configRegistry };
32
- };
33
- const getDefaultCacheDir = () => {
64
+ }
65
+ function getDefaultCacheDir() {
34
66
  const homeDir = getEnv().HOME_DIR;
35
67
  return path.join(homeDir, ".qvac", "models");
36
- };
37
- export const getConfiguredCacheDir = () => {
68
+ }
69
+ export function getConfiguredCacheDir() {
38
70
  return configRegistry.cacheDirectory || getDefaultCacheDir();
39
- };
71
+ }
@@ -1,13 +1,30 @@
1
+ /**
2
+ * Logging Stream Registry
3
+ *
4
+ * Manages RPC subscriptions for streaming logs from server to connected clients.
5
+ *
6
+ * Purpose:
7
+ * - Registers client subscriptions to model/SDK log streams
8
+ * - Routes log messages to subscribed clients via RPC
9
+ * - Buffers logs during model loading (before client subscribes)
10
+ * - Manages stream lifecycle (subscribe/unsubscribe)
11
+ *
12
+ */
1
13
  import type { LogLevel } from "@qvac/logging";
2
- export declare function registerLoggingStream(modelId: string, streamHandler: (level: LogLevel, namespace: string, message: string) => void): void;
3
- export declare function unregisterLoggingStream(modelId: string, streamHandler: (level: LogLevel, namespace: string, message: string) => void): void;
4
- export declare function unregisterAllLoggingStreams(modelId: string): void;
5
- export declare function sendLogToStreams(modelId: string, level: LogLevel, namespace: string, message: string): void;
6
- export declare function hasLoggingStreams(modelId: string): boolean | undefined;
14
+ export declare function startLogBuffering(id: string): void;
15
+ export declare function stopLogBufferingWithTimeout(id: string): void;
16
+ export declare function registerLoggingStream(id: string, streamHandler: (level: LogLevel, namespace: string, message: string) => void): void;
17
+ export declare function unregisterLoggingStream(id: string, streamHandler: (level: LogLevel, namespace: string, message: string) => void): void;
18
+ export declare function unregisterAllLoggingStreams(id: string): void;
19
+ export declare function sendLogToStreams(id: string, level: LogLevel, namespace: string, message: string): void;
20
+ export declare function hasLoggingStreams(id: string): boolean | undefined;
7
21
  export declare function getLoggingStreamStats(): {
8
- totalModels: number;
9
- modelIds: string[];
22
+ totalIds: number;
23
+ ids: string[];
10
24
  totalStreams: number;
25
+ bufferedIds: number;
26
+ idsWithBuffering: number;
27
+ activeTimeouts: number;
11
28
  };
12
29
  export declare function clearAllLoggingStreams(): void;
13
30
  //# sourceMappingURL=logging-stream-registry.d.ts.map
@@ -1,53 +1,132 @@
1
+ /**
2
+ * Logging Stream Registry
3
+ *
4
+ * Manages RPC subscriptions for streaming logs from server to connected clients.
5
+ *
6
+ * Purpose:
7
+ * - Registers client subscriptions to model/SDK log streams
8
+ * - Routes log messages to subscribed clients via RPC
9
+ * - Buffers logs during model loading (before client subscribes)
10
+ * - Manages stream lifecycle (subscribe/unsubscribe)
11
+ *
12
+ */
1
13
  const loggingStreams = new Map();
2
- export function registerLoggingStream(modelId, streamHandler) {
3
- if (!loggingStreams.has(modelId)) {
4
- loggingStreams.set(modelId, new Set());
14
+ // Buffering for logs emitted during model loading (before client subscribes)
15
+ const MAX_BUFFERED_LOGS_PER_MODEL = 100;
16
+ const BUFFER_EXPIRY_MS = 30_000;
17
+ const BUFFERING_TIMEOUT_MS = 5_000;
18
+ const logBuffer = new Map();
19
+ const modelsWithBuffering = new Set();
20
+ const bufferingTimeouts = new Map();
21
+ function clearBufferingTimeout(id) {
22
+ const timeout = bufferingTimeouts.get(id);
23
+ if (timeout) {
24
+ clearTimeout(timeout);
25
+ bufferingTimeouts.delete(id);
5
26
  }
6
- loggingStreams.get(modelId).add(streamHandler);
7
27
  }
8
- export function unregisterLoggingStream(modelId, streamHandler) {
9
- const streams = loggingStreams.get(modelId);
28
+ export function startLogBuffering(id) {
29
+ modelsWithBuffering.add(id);
30
+ }
31
+ export function stopLogBufferingWithTimeout(id) {
32
+ clearBufferingTimeout(id);
33
+ const timeout = setTimeout(() => {
34
+ if (modelsWithBuffering.has(id)) {
35
+ modelsWithBuffering.delete(id);
36
+ logBuffer.delete(id);
37
+ }
38
+ bufferingTimeouts.delete(id);
39
+ }, BUFFERING_TIMEOUT_MS);
40
+ bufferingTimeouts.set(id, timeout);
41
+ }
42
+ export function registerLoggingStream(id, streamHandler) {
43
+ if (!loggingStreams.has(id)) {
44
+ loggingStreams.set(id, new Set());
45
+ }
46
+ loggingStreams.get(id).add(streamHandler);
47
+ const buffered = logBuffer.get(id);
48
+ if (buffered && buffered.length > 0) {
49
+ for (const log of buffered) {
50
+ try {
51
+ streamHandler(log.level, log.namespace, log.message);
52
+ }
53
+ catch (error) {
54
+ console.error(`Error flushing buffered log for ID ${id}:`, error);
55
+ }
56
+ }
57
+ logBuffer.delete(id);
58
+ }
59
+ modelsWithBuffering.delete(id);
60
+ clearBufferingTimeout(id);
61
+ }
62
+ export function unregisterLoggingStream(id, streamHandler) {
63
+ const streams = loggingStreams.get(id);
10
64
  if (streams) {
11
65
  streams.delete(streamHandler);
12
66
  if (streams.size === 0) {
13
- loggingStreams.delete(modelId);
67
+ loggingStreams.delete(id);
14
68
  }
15
69
  }
16
70
  }
17
- export function unregisterAllLoggingStreams(modelId) {
18
- // Simply remove all logging handlers for this model
71
+ export function unregisterAllLoggingStreams(id) {
72
+ // Simply remove all logging handlers
19
73
  // Active streams will naturally terminate when no more logs flow
20
- loggingStreams.delete(modelId);
21
- console.debug(`Unregistered all logging streams for model ${modelId}`);
74
+ loggingStreams.delete(id);
75
+ logBuffer.delete(id);
76
+ modelsWithBuffering.delete(id);
77
+ clearBufferingTimeout(id);
22
78
  }
23
- export function sendLogToStreams(modelId, level, namespace, message) {
24
- const streams = loggingStreams.get(modelId);
25
- if (streams) {
79
+ export function sendLogToStreams(id, level, namespace, message) {
80
+ const streams = loggingStreams.get(id);
81
+ const isBuffering = modelsWithBuffering.has(id);
82
+ if (streams && streams.size > 0) {
26
83
  for (const streamHandler of streams) {
27
84
  try {
28
85
  streamHandler(level, namespace, message);
29
86
  }
30
87
  catch (error) {
31
- console.error(`Error sending log to stream for model ${modelId}:`, error);
88
+ console.error(`Error sending log to stream for ID ${id}:`, error);
32
89
  }
33
90
  }
34
91
  }
92
+ else if (isBuffering) {
93
+ if (!logBuffer.has(id)) {
94
+ logBuffer.set(id, []);
95
+ }
96
+ const buffer = logBuffer.get(id);
97
+ const now = Date.now();
98
+ const validLogs = buffer.filter((log) => now - log.timestamp < BUFFER_EXPIRY_MS);
99
+ if (validLogs.length >= MAX_BUFFERED_LOGS_PER_MODEL) {
100
+ validLogs.shift();
101
+ }
102
+ validLogs.push({ level, namespace, message, timestamp: now });
103
+ logBuffer.set(id, validLogs);
104
+ }
35
105
  }
36
- export function hasLoggingStreams(modelId) {
37
- const streams = loggingStreams.get(modelId);
106
+ export function hasLoggingStreams(id) {
107
+ const streams = loggingStreams.get(id);
38
108
  return streams && streams.size > 0;
39
109
  }
40
110
  export function getLoggingStreamStats() {
41
111
  return {
42
- totalModels: loggingStreams.size,
43
- modelIds: Array.from(loggingStreams.keys()),
112
+ totalIds: loggingStreams.size,
113
+ ids: Array.from(loggingStreams.keys()),
44
114
  totalStreams: Array.from(loggingStreams.values()).reduce((sum, streams) => sum + streams.size, 0),
115
+ bufferedIds: logBuffer.size,
116
+ idsWithBuffering: modelsWithBuffering.size,
117
+ activeTimeouts: bufferingTimeouts.size,
45
118
  };
46
119
  }
47
120
  export function clearAllLoggingStreams() {
48
121
  const count = loggingStreams.size;
122
+ for (const timeout of bufferingTimeouts.values()) {
123
+ clearTimeout(timeout);
124
+ }
49
125
  loggingStreams.clear();
126
+ logBuffer.clear();
127
+ modelsWithBuffering.clear();
128
+ bufferingTimeouts.clear();
50
129
  if (count > 0) {
51
- console.log(`🧹 Cleared logging streams for ${count} model(s)`);
130
+ console.log(`🧹 Cleared logging streams for ${count} ID(s)`);
52
131
  }
53
132
  }
@@ -1,5 +1,6 @@
1
1
  import type EventEmitter from "events";
2
2
  import type FilesystemDL from "@qvac/dl-filesystem";
3
+ import type { ModelType } from "../../../schemas/index";
3
4
  interface AddonInterface {
4
5
  cancel(jobId?: string): Promise<void>;
5
6
  }
@@ -40,6 +41,7 @@ interface LocalOptions {
40
41
  path: string;
41
42
  loadedAt: Date;
42
43
  config: unknown;
44
+ modelType: ModelType;
43
45
  name?: string | undefined;
44
46
  loader: FilesystemDL;
45
47
  }
@@ -53,6 +55,7 @@ export declare function registerModel(id: string, options: {
53
55
  model: AnyModel;
54
56
  path: string;
55
57
  config: unknown;
58
+ modelType: ModelType;
56
59
  loader: FilesystemDL;
57
60
  name?: string | undefined;
58
61
  } | {
@@ -1,4 +1,6 @@
1
1
  import { ModelAlreadyRegisteredError, ModelNotFoundError, ModelIsDelegatedError, } from "../../../utils/errors-server.js";
2
+ import { getServerLogger } from "../../../logging/index.js";
3
+ const logger = getServerLogger();
2
4
  // Global registry state - using stateless functions to manage it
3
5
  const modelRegistry = new Map();
4
6
  export function registerModel(id, options) {
@@ -17,7 +19,7 @@ export function registerModel(id, options) {
17
19
  timeout,
18
20
  },
19
21
  });
20
- console.log(`Delegated model registered: ${id} -> topic: ${topic}, provider: ${providerPublicKey}, timeout: ${timeout}ms`);
22
+ logger.info(`Delegated model registered: ${id} -> topic: ${topic}, provider: ${providerPublicKey}, timeout: ${timeout}ms`);
21
23
  }
22
24
  else {
23
25
  modelRegistry.set(id, {
@@ -28,12 +30,13 @@ export function registerModel(id, options) {
28
30
  path: options.path,
29
31
  loadedAt: new Date(),
30
32
  config: options.config,
33
+ modelType: options.modelType,
31
34
  loader: options.loader,
32
35
  name: options.name,
33
36
  },
34
37
  });
35
38
  const nameStr = options.name ? ` (${options.name})` : "";
36
- console.log(`Local model registered: ${id}${nameStr} -> ${options.path}`);
39
+ logger.info(`Local model registered: ${id}${nameStr} -> ${options.path}`);
37
40
  }
38
41
  }
39
42
  export function getModelEntry(id) {
@@ -56,7 +59,7 @@ export function unregisterModel(id) {
56
59
  const entry = modelRegistry.get(id);
57
60
  if (entry) {
58
61
  modelRegistry.delete(id);
59
- console.log(`Model unregistered: ${id}`);
62
+ logger.debug(`Model unregistered: ${id}`);
60
63
  return entry;
61
64
  }
62
65
  return null;
@@ -99,7 +102,7 @@ export function updateModelConfig(id, config) {
99
102
  }
100
103
  export function clearRegistry() {
101
104
  modelRegistry.clear();
102
- console.log("Model registry cleared");
105
+ logger.info("Model registry cleared");
103
106
  }
104
107
  export function getRegistryStats() {
105
108
  return {
@@ -113,9 +116,9 @@ export async function unloadAllModels() {
113
116
  const entry = modelRegistry.get(modelId);
114
117
  if (entry?.local?.model && entry.local.model.unload) {
115
118
  await entry.local.model.unload();
116
- console.log(`Model unloaded: ${modelId}`);
119
+ logger.debug(`Model unloaded: ${modelId}`);
117
120
  }
118
121
  modelRegistry.delete(modelId);
119
122
  }
120
- console.log(`Unloaded ${modelIds.length} models`);
123
+ logger.info(`Unloaded ${modelIds.length} models`);
121
124
  }
@@ -1,19 +1,21 @@
1
1
  import RPC from "bare-rpc";
2
2
  import { connect } from "bare-net";
3
3
  import { handleRequest } from "./handle-request.js";
4
+ import { getServerLogger } from "../../logging/index.js";
5
+ const logger = getServerLogger();
4
6
  export function createBareKitRPCServer() {
5
7
  const { IPC } = globalThis
6
8
  .BareKit;
7
9
  return new RPC(IPC, handleRequest);
8
10
  }
9
11
  export function createIPCClient(socketPath) {
10
- console.log(`Connecting to IPC socket at ${socketPath}`);
12
+ logger.info(`Connecting to IPC socket at ${socketPath}`);
11
13
  const socket = connect(socketPath);
12
14
  socket.on("connect", () => {
13
- console.log("Connected to IPC server");
15
+ logger.info("Connected to IPC server");
14
16
  });
15
17
  socket.on("error", (err) => {
16
- console.error("IPC client connection error:", err);
18
+ logger.error("IPC client connection error:", err);
17
19
  });
18
20
  return new RPC(socket, handleRequest);
19
21
  }
@@ -5,6 +5,7 @@ import { handleLoadModel } from "./handlers/load-model.js";
5
5
  import { handleLoadModelDelegated } from "./handlers/load-model-delegated.js";
6
6
  import { handleCompletionStreamDelegated } from "./handlers/completion-stream-delegated.js";
7
7
  import { getModelEntry } from "../bare/registry/model-registry.js";
8
+ import { setSDKConfig } from "../bare/registry/config-registry.js";
8
9
  import { handleUnloadModel } from "./handlers/unload-model.js";
9
10
  import { handleTranscribeStream } from "./handlers/transcribe-stream.js";
10
11
  import { handleEmbed } from "./handlers/embed.js";
@@ -16,7 +17,6 @@ import { stopProvideHandler } from "./handlers/stopProvideHandler.js";
16
17
  import { handleRag } from "./handlers/rag.js";
17
18
  import { handleDeleteCache } from "./handlers/delete-cache.js";
18
19
  import { handleTextToSpeech } from "./handlers/text-to-speech.js";
19
- import { handleSetConfig } from "./handlers/set-config.js";
20
20
  import { handleGetModelInfo } from "./handlers/get-model-info.js";
21
21
  import { sendErrorResponse, sendStreamErrorResponse, } from "../error-handlers.js";
22
22
  import { NoDataReceivedError, UnknownRequestTypeError, } from "../../utils/errors-client.js";
@@ -27,6 +27,24 @@ export async function handleRequest(req) {
27
27
  throw new NoDataReceivedError();
28
28
  }
29
29
  const jsonData = JSON.parse(rawData);
30
+ // Handle special internal config initialization message
31
+ if (jsonData &&
32
+ typeof jsonData === "object" &&
33
+ "type" in jsonData &&
34
+ jsonData.type === "__init_config") {
35
+ try {
36
+ const configData = jsonData;
37
+ setSDKConfig(configData.config);
38
+ req.reply(JSON.stringify({ success: true }), "utf-8");
39
+ }
40
+ catch (error) {
41
+ req.reply(JSON.stringify({
42
+ success: false,
43
+ error: error instanceof Error ? error.message : String(error),
44
+ }), "utf-8");
45
+ }
46
+ return;
47
+ }
30
48
  const request = requestSchema.parse(jsonData);
31
49
  switch (request.type) {
32
50
  case "downloadAsset": {
@@ -84,13 +102,19 @@ export async function handleRequest(req) {
84
102
  sendStreamErrorResponse(stream, error);
85
103
  }
86
104
  }
105
+ else if (request.delegate) {
106
+ try {
107
+ const response = await handleLoadModelDelegated(request);
108
+ req.reply(JSON.stringify(responseSchema.parse(response)), "utf-8");
109
+ }
110
+ catch (error) {
111
+ sendErrorResponse(req, error);
112
+ }
113
+ }
87
114
  else {
88
- // Route to appropriate handler based on delegation
115
+ // Load without progress/delegate, or reload config
89
116
  try {
90
- const handler = request.delegate
91
- ? handleLoadModelDelegated
92
- : handleLoadModel;
93
- const response = await handler(request);
117
+ const response = await handleLoadModel(request);
94
118
  req.reply(JSON.stringify(responseSchema.parse(response)), "utf-8");
95
119
  }
96
120
  catch (error) {
@@ -245,16 +269,6 @@ export async function handleRequest(req) {
245
269
  }
246
270
  break;
247
271
  }
248
- case "setConfig": {
249
- try {
250
- const response = handleSetConfig(request);
251
- req.reply(JSON.stringify(responseSchema.parse(response)), "utf-8");
252
- }
253
- catch (error) {
254
- sendErrorResponse(req, error);
255
- }
256
- break;
257
- }
258
272
  case "getModelInfo": {
259
273
  try {
260
274
  const response = await handleGetModelInfo(request);
@@ -1,5 +1,7 @@
1
1
  import { cancel } from "../../bare/addons/index.js";
2
2
  import { createCancelFunction } from "./load-model/download-manager.js";
3
+ import { getServerLogger } from "../../../logging/index.js";
4
+ const logger = getServerLogger();
3
5
  export async function cancelHandler(request) {
4
6
  try {
5
7
  switch (request.operation) {
@@ -17,7 +19,7 @@ export async function cancelHandler(request) {
17
19
  };
18
20
  }
19
21
  catch (error) {
20
- console.error("Error during cancellation:", error);
22
+ logger.error("Error during cancellation:", error);
21
23
  return {
22
24
  type: "cancel",
23
25
  success: false,
@@ -2,6 +2,8 @@ import { getModelEntry } from "../../bare/registry/model-registry.js";
2
2
  import { getRPC } from "../../bare/delegate-rpc-client.js";
3
3
  import { stream } from "../../../client/rpc/rpc-client.js";
4
4
  import { ModelIsDelegatedError } from "../../../utils/errors-server.js";
5
+ import { getServerLogger } from "../../../logging/index.js";
6
+ const logger = getServerLogger();
5
7
  export async function* handleCompletionStreamDelegated(request) {
6
8
  // Get delegation info from model registry
7
9
  const entry = getModelEntry(request.modelId);
@@ -10,7 +12,7 @@ export async function* handleCompletionStreamDelegated(request) {
10
12
  }
11
13
  const { topic, providerPublicKey, timeout } = entry.delegated;
12
14
  try {
13
- console.log(`📤 Sending delegated completionStream request to provider: ${providerPublicKey}${timeout ? `, timeout: ${timeout}ms` : ""}`);
15
+ logger.debug(`📤 Sending delegated completionStream request to provider: ${providerPublicKey}${timeout ? `, timeout: ${timeout}ms` : ""}`);
14
16
  // Create RPC instance for this HyperSwarm peer
15
17
  const rpc = await getRPC(topic, providerPublicKey, { timeout });
16
18
  // Use the regular stream function with the HyperSwarm RPC instance
@@ -21,7 +23,7 @@ export async function* handleCompletionStreamDelegated(request) {
21
23
  }
22
24
  }
23
25
  catch (error) {
24
- console.error("Error in delegated completion stream:", error);
26
+ logger.error("Error in delegated completion stream:", error);
25
27
  yield {
26
28
  type: "completionStream",
27
29
  token: `Error communicating with provider: ${error instanceof Error ? error.message : String(error)}`,
@@ -1,4 +1,6 @@
1
1
  import { deleteCache as deleteCacheUtil } from "../../bare/addons/llamacpp/kv-cache-utils.js";
2
+ import { getServerLogger } from "../../../logging/index.js";
3
+ const logger = getServerLogger();
2
4
  export async function handleDeleteCache(request) {
3
5
  try {
4
6
  if ("all" in request && request.all) {
@@ -19,7 +21,7 @@ export async function handleDeleteCache(request) {
19
21
  };
20
22
  }
21
23
  catch (error) {
22
- console.error("Error deleting cache:", error);
24
+ logger.error("Error deleting cache:", error);
23
25
  return {
24
26
  type: "deleteCache",
25
27
  success: false,
@@ -1,4 +1,6 @@
1
1
  import { resolveModelPath } from "./load-model/resolve.js";
2
+ import { getServerLogger } from "../../../logging/index.js";
3
+ const logger = getServerLogger();
2
4
  export async function handleDownloadAsset(request, progressCallback) {
3
5
  const { assetSrc, seed } = request;
4
6
  try {
@@ -10,7 +12,7 @@ export async function handleDownloadAsset(request, progressCallback) {
10
12
  };
11
13
  }
12
14
  catch (error) {
13
- console.error("Error downloading asset:", error);
15
+ logger.error("Error downloading asset:", error);
14
16
  return {
15
17
  type: "downloadAsset",
16
18
  success: false,
@@ -1,4 +1,6 @@
1
1
  import { embed } from "../../bare/addons/llamacpp/index.js";
2
+ import { getServerLogger } from "../../../logging/index.js";
3
+ const logger = getServerLogger();
2
4
  export async function handleEmbed(request) {
3
5
  const { modelId, text } = request;
4
6
  try {
@@ -10,7 +12,7 @@ export async function handleEmbed(request) {
10
12
  };
11
13
  }
12
14
  catch (error) {
13
- console.error("Error during embedding:", error);
15
+ logger.error("Error during embedding:", error);
14
16
  return {
15
17
  type: "embed",
16
18
  success: false,
@@ -27,7 +27,6 @@ export declare const handlers: {
27
27
  rag: typeof handleRag;
28
28
  cancel: typeof cancelHandler;
29
29
  textToSpeech: typeof handleTextToSpeech;
30
- setConfig: (request: import("../../../schemas").SetConfigRequest) => import("../../../schemas").SetConfigResponse;
31
30
  getModelInfo: (request: import("../../../schemas").GetModelInfoRequest) => Promise<import("../../../schemas").GetModelInfoResponse>;
32
31
  };
33
32
  //# sourceMappingURL=index.d.ts.map
@@ -12,7 +12,6 @@ import { handleRag } from "./rag.js";
12
12
  import { cancelHandler } from "./cancelHandler.js";
13
13
  import { handleDeleteCache } from "./delete-cache.js";
14
14
  import { handleTextToSpeech } from "./text-to-speech.js";
15
- import { handleSetConfig } from "./set-config.js";
16
15
  import { handleGetModelInfo } from "./get-model-info.js";
17
16
  export const handlers = {
18
17
  completionStream: handleCompletionStream,
@@ -29,6 +28,5 @@ export const handlers = {
29
28
  rag: handleRag,
30
29
  cancel: cancelHandler,
31
30
  textToSpeech: handleTextToSpeech,
32
- setConfig: handleSetConfig,
33
31
  getModelInfo: handleGetModelInfo,
34
32
  };